首页 | 新闻 | 交流 | 问吧 | 文档 | 手册 | 下载 | 博客

对用户控件的访问方式重写

作者:  时间: 2010-12-30

首先增加一个继承IHttpHandler的截获类

代码
public class UserControlRenderingHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string fileType = context.Request.FilePath;
string appRelativePath = context.Request.AppRelativeCurrentExecutionFilePath;
string controlPath = appRelativePath.ToLower().Replace(".uc", ".ascx");

ViewManager
<UserControl> viewManager = new ViewManager<UserControl>();
UserControl control
= viewManager.LoadViewControl(controlPath);

SetPropertyValues(control, context);

context.Response.ContentType
= "text/html";
context.Response.Write(viewManager.RenderView(control));
}

private static Dictionary<
Type,
Dictionary
<
PropertyInfo,
List
<UserControlRenderingPropertyAttribute>>> s_metadataCache =
new Dictionary<
Type,
Dictionary
<
PropertyInfo,
List
<UserControlRenderingPropertyAttribute>>>();
private static Dictionary<PropertyInfo, object> s_defaultValueCache =
new Dictionary<PropertyInfo, object>();
private static object s_mutex = new object();

private static Dictionary<
PropertyInfo,
List
<UserControlRenderingPropertyAttribute>> GetMetadata(Type type)
{
if (!s_metadataCache.ContainsKey(type))
{
lock (s_mutex)
{
if (!s_metadataCache.ContainsKey(type))
{
s_metadataCache[type]
= LoadMetadata(type);
}
}
}

return s_metadataCache[type];
}

private static Dictionary<
PropertyInfo,
List
<UserControlRenderingPropertyAttribute>> LoadMetadata(Type type)
{
Dictionary
<PropertyInfo, List<UserControlRenderingPropertyAttribute>> result = new Dictionary<PropertyInfo, List<UserControlRenderingPropertyAttribute>>();
PropertyInfo[] properties
= type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty);
foreach (PropertyInfo p in properties)
{
object[] oo = p.GetCustomAttributes(typeof(UserControlRenderingPropertyAttribute), true);
if (oo.Length > 0)
{
List
<UserControlRenderingPropertyAttribute> list = new List<UserControlRenderingPropertyAttribute>();
list.Add(((UserControlRenderingPropertyAttribute)oo[
0]));
result[p]
= list;
}
}
return result;
}

private static object GetDefaultValue(PropertyInfo property)
{
if (!s_defaultValueCache.ContainsKey(property))
{
lock (s_mutex)
{
if (!s_defaultValueCache.ContainsKey(property))
{
object[] attributes = property.GetCustomAttributes(typeof(DefaultValueAttribute), true);
object value = attributes.Length > 0 ?
((DefaultValueAttribute)attributes[
0]).Value : null;
s_defaultValueCache[property]
= value;
}
}
}

return s_defaultValueCache[property];
}

public static void SetPropertyValues(UserControl control, HttpContext context)
{
Dictionary
<
PropertyInfo,
List
<UserControlRenderingPropertyAttribute>> metadata = GetMetadata(control.GetType());
foreach (PropertyInfo property in metadata.Keys)
{
object value = GetValue(metadata[property], context) ?? GetDefaultValue(property);
if (value != null)
{
property.SetValue(control, Convert.ChangeType(value, property.PropertyType),
null);
}
}
}

private static object GetValue(
IEnumerable
<UserControlRenderingPropertyAttribute> metadata,
HttpContext context)
{
foreach (UserControlRenderingPropertyAttribute att in metadata)
{
NameValueCollection collection
= (att.Source == UserControlRenderingPropertySource.QueryString) ?
context.Request.QueryString : context.Request.Form;
object value = collection[att.Key];

if (value != null) return value;
}

return null;
}

public bool IsReusable
{
get
{
return false;
}
}

上面类相关的东西

 

代码
public class ViewManager<T> where T : UserControl
{
private AjaxPageBase m_pageHolder;

public T LoadViewControl(string path)
{
this.m_pageHolder = new AjaxPageBase();

return (T)this.m_pageHolder.LoadControl(path);
}

public string RenderView(T control)
{
StringWriter output
= new StringWriter();
this.m_pageHolder.Controls.Add(control);
HttpContext.Current.Server.Execute(
this.m_pageHolder, output, true);
return output.ToString();
}
}

 

代码
public class AjaxPageBase : Page
{
public override void VerifyRenderingInServerForm(Control control)
{

}

protected override void OnError(EventArgs e)
{



}
}

 

下面这个是对form表单的参数截获

代码
public enum UserControlRenderingPropertySource
{
Form,
QueryString
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple
= true, Inherited = true)]
public class UserControlRenderingPropertyAttribute : Attribute
{
string _key;

public string Key
{
get { return _key; }
set { _key = value; }
}

UserControlRenderingPropertySource _source;

public UserControlRenderingPropertySource Source
{
get { return _source; }
set { _source = value; }
}
}

 

 

这样就将用户的控件.ascx转成.uc的方式 重新写出来了。

解决了.ascx不能直接访问的问题。

web.config的<httpHandlers>节增加

<add verb="*" path="*.uc" type="Core.Web.UserControlRenderingHandler"/>

再到IIS6中增加映射

IIS7配置