zoukankan      html  css  js  c++  java
  • web api中的RouteHandler

    ASP.NET MVC4中引入的Web API可以说是进行REST软件开发的利器(个人意见),但是最近在web form中混入web api时,发现一个问题:由于以前的web form项目中,使用到了session(包括那些复杂的底层逻辑),所以为了最小改动,必须保证web api能支持session。而web api默认情况下,是不支持session的。

    问题重现

    重现这个不支持session的问题,其实很简单。只需要新建一个web api项目,然后修改ValuesController的Get方法为:

    public string Get()
    {
        return HttpContext.Current.Session == null ? "Session is null" : string.Format("SessionID is '{0}'", HttpContext.Current.Session.SessionID);
    }

    在运行后,发现页面输出为:"Session is null"。

    解决方案

    经过一番努力,发现Route中有一个IRouteHandler类型的属性RouteHandler,而默认情况下,这个RouteHandler是System.Web.Http.WebHost.HttpControllerRouteHandler,而HttpControllerRouteHandler中的GetHttpHandler会返回一个IHttpHandler的对象,来对web api的请求进行预处理。对于IHttpHandler其实大家应该不陌生,这个正是asp.net web form中,经常使用到的iis管道处理的一个环节。那么为了让IHttpHandler支持session,我们知道只需要实现一个标记接口IRequiresSessionState。而默认的System.Web.Http.WebHost.HttpControllerHandler只实现了IHttpHandler并没有实现IRequiresSessionState。所以问题就变成了如何让IRouteHandler的GetHttpHandler方法返回一个既实现了IHttpHandler,又实现了IRequiresSessionState对象。所以有了下面的类:

    public class WebApiSessionControllerHandler : HttpControllerHandler, IRequiresSessionState 
    {
        public WebApiSessionControllerHandler(RouteData routeData) : base(routeData) { }        
    }

    为了使用WebApiSessionControllerHandler,还需要实现一个IRouteHandler自定义类:

    public class WebApiSessionRouteHandler : HttpControllerRouteHandler
    {
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new WebApiSessionControllerHandler(requestContext.RouteData);
        }        
    }

    接下来,就是要让WebApiSessionRouteHandler真正起作用的时候了,只需要在你RegisterRoutes时,把MapHttpRoute修改为:

    var route = routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }                    
    );
    route.RouteHandler = new WebApiSessionRouteHandler(); 

    现在再来看下/api/values的输出:"SessionID is 'me4exrjgv4lecvixa0ab2z1g'",发现session不在为null。

    优化方案

    为了在map route操作时,能够有一个统一的写法,可以增加一个扩展方法:

    public static class HttpRouteExtensions
    {
        public static Route MapHttpRoute(this RouteCollection routes, string name, string routeTemplate, object defaults, IRouteHandler routeHandler)
        {
            object constraints = null;
            HttpMessageHandler handler = null;
            var route = routes.MapHttpRoute(name, routeTemplate, defaults, constraints, handler);
            if (routeHandler != null)
            {
                route.RouteHandler = routeHandler;
            }
            return route;
        }
    }

    这样,MapHttpRoute就可以改为:

    routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            routeHandler: new WebApiSessionRouteHandler()
    );

    结论

    对HttpControllerHandler使用,不仅仅局限于是web api支持session。前面已经提到我们可以对web api的请求进行预处理,也可以创建自定义类,重现HttpControllerHandler中的:

    1、BeginProcessRequest

    2、EndProcessRequest

    3、ProcessRequest

    具体应该重写哪一个就需要根据具体的业务具体分析了。

  • 相关阅读:
    [AGC030F] Permutation and Minimum
    [GYM102904B]Dispatch Money
    [ZOJ3989]Triangulation
    [HDU6094]Rikka with KMatch
    CF739E Gosha is hunting
    [国家集训队]Tree I
    [BZOJ3864]Hero meet devil
    编程是一门实践性的科学
    IE下的flash加载中文URL文件 问题
    多线程1号
  • 原文地址:https://www.cnblogs.com/aidanzsj/p/5212485.html
Copyright © 2011-2022 走看看