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

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

  • 相关阅读:
    面试官问你如何解决web高并发这样回答就好了
    react-native页面间传递数据的几种方式
    图片上传知识点梳理
    使用Vue CLI 3将基于element-ui二次封装的组件发布到npm
    OpenCV学习笔记09--通过cvPtr2D或指针算法绘制图形
    [code segments] OpenCV3.0 SVM with C++ interface
    LINUX设备驱动程序笔记(一)设备驱动程序简单介绍
    redis 简单安装使用
    Linux常见压缩命令
    计算机网络13--网络应用的体系结构
  • 原文地址:https://www.cnblogs.com/aidanzsj/p/5212485.html
Copyright © 2011-2022 走看看