上一篇讲到IHttpModule,以及在HttpModule中响应的一系统事件的顺序,在HttpHandler之前,有各种的HttpModule,可以在这些模块的响应事件中处理我们自己的逻辑,
而HttpHandler才是真正的服务器端进行请求处理的实现,这篇就是对HttpHandler进行一个总结。
首先在.Net 2.0,找到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\ 目录下的web.config 文件,找到httpHandlers结点,应该可以看到如下这样的配置.
<httpHandlers> <add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True" /> <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" /> <add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True" /> <add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*.ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*.cs" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True" /> </httpHandlers>
可以看到,<httpHandlers>结点中将不同的文件类型映射给不同的Handler去处理,于.aspx来说,由 System.Web.UI.PageHandlerFactory来处理。而对于.cs来说,是由 System.Web.HttpForbiddenHandler处理,ForbiddenHandler名字中出现的Forbidden (翻译过来是"禁止")可以看出,个Handler可以避免我们的源码被看到,而PageHandlerFactory类是 ASP.NET 页的默认处理程序工厂实现,继承的是IHttpHandlerFactory接口,IHttpHandlerFactory后面会再讲.
在Asp.Net中有这样一种文件扩展名为ashx,叫"一般处理文件",这个文件就是继承IHttphandler接口,是一种完全自定义的处理Http请求的文件.
现在写个小例子,通过继承IHttphandler来实现.
public class HttpGetData : IHttpHandler { public void ProcessRequest(HttpContext context) //处理请求的方法 { if (context.Request.Params.Count > 0) { string id = string.Empty; string tableName = string.Empty; if (context.Request["id"] != null) { id = context.Request["id"]; } if (context.Request["tableName"] != null) { tableName = context.Request["tableName"]; } string sql = string.Format("select [code],[name] from {0} where FID='{1}'", tableName, id); DataSet ds = DBHelperToSql.QueryData(sql); //获取数据 string FormatStr = string.Empty; foreach (DataRow row in ds.Tables[0].Rows) FormatStr += "$" + row.ItemArray[0].ToString() + row.ItemArray[1].ToString();
FormatStr = FormatStr.Substring(1); context.Response.Write(FormatStr); //返回响应数据 context.Response.End(); } else { context.Response.Write("禁止非法访问此页面!"); context.Response.End(); } } public bool IsReusable { get { return ture; } } }
JS代码:
function AjaxRequstFn(FID, id, tableName) { $.ajax({ type: 'GET', url: 'HttpGetData.ashx',//向HttpGetData.ashx请求,在HttpGetData.ashx进行请求处理 processData: false, dataType: 'text', data: 'id=' + escape($('#' + FID).val()) + '&tableName=' + tableName, success: function(data, textStatus) { FormatData(data, id); //格式化字符串 }, error: function(XMLHttpRequest, textStatus, errorThrown) { $('#showResult').html(ErrorMessage); } }); } //格式化字符串 function FormatData(data, id) { var items = data.split('$'); var value = ''; var text = ''; for (var i = 0; i < items.length; i++) { value = items[i].substr(0, 6); text = items[i].substr(6, items[i].length); $('#' + id).append('<option value="' + value + '">' + text + '</option>'); } $('#' + id).removeAttr('disabled'); }
Html代码:
<select id="SelProvince"> </select> <select id="SelCity" disabled="disabled"> <option value="请选择城市">==请选择城市==</option> </select> <select id="SelArea" disabled="disabled"> <option value="请选择地区">==请选择地区==</option> </select>
上述例子就是通过前台ajax请求,然后在后台进行HttpHandler,之后返回前台再进行数据转化再展示.是一个完整的Http请求的流程.
当然在我的上述例子中没有用到Session,如果在Http请求类中需要使用Session, 那仅需要实现 IHttpHandler接口(这个显然),为了在这个Handler类中使用SessionState,
还需要实现 IRequiresSessionState接口,对于这个接口,MSDN的解释是这样的:Specifies that the target HTTP handler requires read and write access to session-state values. This is a marker interface and has no methods.(翻译过来是:指定当前Http Handler需要对SessionState值的读写访问权。这是一个标记接口,没有任何方法)。
IRequiresSessionState的接口定义是这样的:
public interface IRequiresSessionState{}
当然你也可以不使用ashx文件,直接定义类去继承IHttpHandler,如果是这样,还需要在web.config当中去设置.例如:
<system.web>
<httpHandlers>
<add path="*.jpg" verb="*" type="MyCustomHandler.JpgHandler, MyCustomHandler" />
</httpHandlers>
</system.web>
下面说下IHttpHandlerFactory,实现 IHttpHandlerFactory 接口的类是为了动态创建实现 IHttpHandler 接口的类的新实例
public class MyFactory : IHttpHandlerFactory { [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] public virtual IHttpHandler GetHandler(HttpContext context, String requestType, String url, String pathTranslated) { String fname = url.Substring(url.LastIndexOf('/')+1); String cname = fname.Substring(0, fname.IndexOf('.')); String className = "test." + cname; Object h = null; // Try to create the handler object. try { // Create the handler by calling class abc or class xyz. h = Activator.CreateInstance(Type.GetType(className)); } catch(Exception e) { throw new HttpException("Factory couldn't create instance " + "of type " + className, e); } return (IHttpHandler)h; } // This is a must override method. public virtual void ReleaseHandler(IHttpHandler handler) { } }
<configuration> <system.web> <httpHandlers> <add verb="*" path="abc.aspx,xyz.aspx" type="test.MyFactory,HandlerFactoryTest" /> </httpHandlers> </system.web> </configuration>