码迷,mamicode.com
首页 > 其他好文 > 详细

Handler

时间:2015-07-12 22:57:07      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

Handlers are responsible for generating the response content for an HTTP request. 

 

1. ASP.NET Handlers

As part of request handling life cycle, ASP.NET selects a handler to generate the content that will be returned to the client. There are handlers for the MVC framework, Web Forms, SignalR, and the Web API, and the asp.net platform treats them all equally. 

 

1.1 understanding handlers in the Request life cycle

A common source of confusion when working with the ASP.net platform is the difference between modules and handlers. 

Modules have two roles in request handling. They can be used for diagnosis and debugging, or they can provide services used by other components. Modules are instantiated at the start of the request handling process, and they set up services that are consumed through the asp.net context objects, but the selection and creation of the handler are built right into the life cycle. 

The MapRequestHanlder event is triggered before the asp.net platform locates the handler that will generate the content for the request. 

 

1.2 Understanding handlers

Hanlders are classes that implement System.Web.IHttpHandler interface. 

ProcessRequest(context)                                             This method is called when the asp.net framework wants the handler to generate a response for a request                                                
IsReusable This property tells the asp.net framework whether the handler can be used to handle further requests. 

 The ProcessRequest method is passed an HttpContext object, which can be used to inspect the request and the state of the application. 

1.3 Hanlders and the life-cycle events

MapRequestHandler MapRequestHandler is triggered when the asp.net framework wants to locate a handler for the request. 

PreRequestHandlerExecute

PostRequestHandlerExecute

These events are tirggered immediately before and after the call to the handler ProcessRequest

 

 2. Creating a handler

   public class DayOfWeekHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            string day = DateTime.Now.DayOfWeek.ToString();
            if (context.Request.CurrentExecutionFilePathExtension == ".json")
            {
                context.Response.ContentType = "application/json";
                context.Response.Write(string.Format("{{\"day\": \"{0}\"}}", day));
            }
            else
            {
                context.Response.ContentType = "text/html";
                context.Response.Write(string.Format("<span>It is: {0}</span>",day));
            }
        }
    }

 

When content is required for a request, the asp.net platform calls the ProcessRequest method and provides the handler with an HttpContext object. After that, it is up to the handler to figure out what‘s need.

 

2.1 Registering a hanlder using URL Routing

Hanlders must be registered before they can be generate content for requests. The first technique for registering a handler is to use the routing system. 

   public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute("myRoute", "{controller}/{action}");

            routes.Add(new Route("handler/{*path}", new CustomRouteHandler{HandlerType = typeof(DayOfWeekHandler)}));

            routes.MapRoute(
                name:"default",
                url:"{controller}/{action}/{id}",
                defaults: new { controller="Home", action="Index", id=UrlParameter.Optional}
                );
        }
    }

    class CustomRouteHandler : IRouteHandler
    {
        public Type HandlerType { get; set; }

        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return (IHttpHandler) Activator.CreateInstance(HandlerType);
        }
    }

 

2.2 Registering a handler using the configuration file

Using the routing system to set up custom handler is workable, but using web.config to register hanlder is more flexible as not all projects use the routing system. 

    <handlers>
      <add name="DayJSON" path="/handler/*.json" verb="GET" type="UrlRoutes.Infrastructure.DayOfWeekHandler"/>
      <add name="DayHTML" path="/handler/day.html" verb="*" type="UrlRoutes.Infrastructure.DayOfWeekHandler"/>
    </handlers>

 

name   defines a name that uniquely identifies the hander
path specifies the URL path for which the handler can process
verb

specifies the HTTP method that the hanlder supports. 

type Specifies the type of the IHttpHandler or IHttpHandlerFactory implementation class. 

You can be as general or as specific as you want when you register a custom handler, and you can create any number of configuration entries for each handler. For this particular example, you will have to add routes.IgnoreRoute("handler/{*path}"), because the default routing configuration assumes that all incoming requests will routed and sends 404 when a request can‘t be matched to a route. 

3. Creating asynchronous handlers

You can create asynchronous handler is you need to perform operations such as making a network request. 

Asynchronous handlers implement the IHttpAsyncHanlder interface, but this interface follows the old pattern of having begin and end methods, and relying on IAsyncResult. A much simpler approach is to derive the handler from HttpTaskAsynHandler class, which use task objects and async and await keywords. 

 

    public class SiteLengthHandler : HttpTaskAsyncHandler
    {
        public override async System.Threading.Tasks.Task ProcessRequestAsync(HttpContext context)
        {
            string data = await new HttpClient().GetStringAsync("http://www.apress.com");
            context.Response.ContentType = "text/html";
            context.Response.Write(string.Format("<span>Length: {0}</span>", data.Length));
        }
    }

 

 

<handlers>
      <add name="DayJSON" path="/handler/*.json" verb="GET" type="UrlRoutes.Infrastructure.DayOfWeekHandler"/>
      <add name="DayHTML" path="/handler/day.html" verb="*" type="UrlRoutes.Infrastructure.DayOfWeekHandler"/>
      <add name="SiteLength" path="/handler/site" verb="*" type="UrlRoutes.Infrastructure.SiteLengthHandler"/>
    </handlers>

 

4. Creating modules that provide services to handlers

 Modules can provide services to handlers by assigning data values to the context objects. You can set a value for one of the predefined context object properties, such as HttpContext.Session, but modules can also pass arbitrary data to the handler using the HttpContext.Items property. The Items property returns an IDictionary implementation that can be used to store any data that the handler requires access to.

public class DayModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            app.BeginRequest += (src, orgs) =>
            {
                app.Context.Items["DayModule_Time"] = DateTime.Now;
            };
        }
        public void Dispose()
        {

        }
    }

 

4.1 Cosuming the items data

The same Items collection that the module uses is available to the handler via the HttpContext.Items property. 

 

       public void ProcessRequest(HttpContext context)
        {

            if (context.Items.Contains("DayModuel_Time") && (context.Items["DayModule_Time"] is DateTime))
            {
                string day = ((DateTime) context.Items["DayModule_Time"]).DayOfWeek.ToString();


                if (context.Request.CurrentExecutionFilePathExtension == ".json")
                {
                    context.Response.ContentType = "application/json";
                    context.Response.Write(string.Format("{{\"day\": \"{0}\"}}", day));
                }
                else
                {
                    context.Response.ContentType = "text/html";
                    context.Response.Write(string.Format("<span>It is: {0}</span>", day));
                }
            }
            else
            {
                context.Response.ContentType = "text/html";
                context.Response.Write("no module data available");
            }
        }

 

4.2 Targeting a specific handler

The module that I defined adds data to the Items collection for every request, whether or not the handler that is selected will use it. You can respond to the PostMapRequestHandler life-cycle event in the module and add data to the Items collection only if the handler that ASP.NET has selected is one that will consume the data. 

        public void Init(HttpApplication app)
        {
            app.PostMapRequestHandler += (src, orgs) =>
            {
                if (app.Context.Handler is DayOfWeekHandler)
                {
                    app.Context.Items["DayModule_Time"] = DateTime.Now;
                }
            };
        }

The module now handles the PostMapRequestHandler event, which is triggered after the handler has been selected go generate content for the request and uses the HttpContext.Handler property to check the type of the selected handler. 

 

4.3 Decoupling components using declarative interfaces

A more flexible approach is to identify handlers that a module will provide servcies to using declarative interfaces, which are regular c# interfaces. 

    interface IRequireDate
    {
    }
        public void Init(HttpApplication app)
        {
            app.PostMapRequestHandler += (src, orgs) =>
            {
                if (app.Context.Handler is IRequireDate)
                {
                    app.Context.Items["DayModule_Time"] = DateTime.Now;
                }
            };
        }

 

Not only does this make it easier to test and maintain both the hanlder and the module, it also allows any handler that implements the declarative interface to receive the servcies that the module provides. 

 

 

 

Handler

标签:

原文地址:http://www.cnblogs.com/timBo/p/4605434.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!