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 api中的RouteHandler的更多相关文章

  1. Web APi 2.0优点和特点?在Web APi中如何启动Session状态?

    前言 曾几何时,微软基于Web服务技术给出最流行的基于XML且以扩展名为.asmx结尾的Web Service,此服务在.NET Framework中风靡一时同时也被.NET业界同仁所青睐,几年后在此 ...

  2. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  3. ASP.NET Web API中的Controller

    虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...

  4. 在ASP.NET Web API中使用OData

    http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...

  5. Web Api中的get传值和post传值

    GET 方式 get方式传参 我们一般用于获取数据做条件筛选,也就是 “查” 1.无参 var look = function () { $.ajax({ type: "GET", ...

  6. WEB API 中HTTP的get、post、put,delete 请求方式

    一.WEB API 中HTTP 请求方式的四个主要方法 (GET, PUT, POST, DELETE), 按照下列方式映射为 CURD 操作: 1.POST 用于新建资源,服务端在指定的URI 上创 ...

  7. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【五】——在Web Api中实现Http方法(Put,Post,Delete)

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我们对资源的CRUD操作都是通过相应的Http方法来实现——Post(新 ...

  8. ASP.NET Web API 中的异常处理(转载)

    转载地址:ASP.NET Web API 中的异常处理

  9. Web Api 中Get 和 Post 请求的多种情况分析

    转自:http://www.cnblogs.com/babycool/p/3922738.html 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用J ...

随机推荐

  1. WebForms VS. MVC(翻译)

    (本文翻译自CodeProject上阿三写的一篇文章,原文地址:http://www.codeproject.com/Articles/528117/WebForms-vs-MVC,讲了有关ASP.A ...

  2. 在JavaScript中对HTML进行反转义

    在JavaScript中对字符串进行转义和反转义操作,常用的方法莫过于使用encodeURI (decodeURI).encodeURIComponent (decodeURIComponent)这几 ...

  3. Objective-C 观察者模式--简单介绍和使用

    观察者模式(有时又被称为发布-订阅模式) 在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知. 这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实 ...

  4. 《Spark快速大数据分析》—— 第七章 在集群上运行Spark

  5. salesforce 零基础学习(四十三)运算取余

    工作中遇到一个简单的小问题,判断两个数是否整除,如果不整除,获取相关的余数. 习惯java的我毫不犹豫的写下了代码 public Boolean isDivisibility(Integer divi ...

  6. 研究一下javascript的模块规范(CommonJs/AMD/CMD)

    最近写react需要使用nodejs作为开发环境,需要通过npm安装一些第三方的依赖库,因此慢慢感觉到nodejs基础薄弱对我带来了一些不安全感,尤其是javascript模块这一块听到了很多概念,比 ...

  7. Hexo的Next主题配置

    使用Next主题 在这里Downloads Next主题代码 将下载的代码放在myBlog/next目录下 设置站点myBlog/_config.yml的theme字段值为next 生成新页面hexo ...

  8. LINQ系列:Linq to Object排序操作符

    LINQ排序操作符包括:OrderBy.OrderByDescending.ThenBy.ThenByDescending及Reverse. 1. OrderBy 1>. 原型定义 public ...

  9. 实战MEF(3):只导出类的成员

    通过前面两篇文章的介绍,相信各位会明白MEF中有不少实用价值.上一文中我们也讨论了导入与导出,对于导出导入,今天我们再深入一点点,嗯,只是深入一点点而已,不会很难的,请大家务必放心,如果大家觉得看文章 ...

  10. Lightmaping

    一.基本知识点 1.Baked Only:不会传入shader,只有烘焙时才有用,也就是_LightColor0等这种变量不会表示一个Baked Only Light(前提是场景有lightmap,如 ...