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. C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图

    C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图 +BIT祝威+悄悄在此留下版了个权的信息说: 最近需要用OpenGL绘制文字,这是个很费时费力的事.一般的思路就是 ...

  2. EF:oracle的number类型映射为C#的boolean类型

    一开始用下面的方法映射, Property(p => p.IsFixed).HasColumnName("IS_FIXED").HasColumnType("num ...

  3. WCF 安全性之 自定义用户名密码验证

    案例下载 http://download.csdn.net/detail/woxpp/4113172 客户端调用代码 通过代理类 代理生成 参见 http://www.cnblogs.com/woxp ...

  4. 移动开发--Hybrid和Native混合开发-->HybridApp 、NativeApp、WebApp

    1.1.     APP三种开发模式 智能手机之普及不用多说,手机APP渗投到各个行业:电商(淘宝.京东等).金融(各手机行业.P2P借贷等).医疗(智慧医疗).交通(滴滴.Uber等).教育(慕课网 ...

  5. C#开源日志Nlog入门

    c#语言使用的日志比较多,比如:Log4.NLog等,今天我就简单随笔记录哈NLog的使用. 1.NLog的安装: 直接在VS编译器中打开程序包管理器,输入Install-Package NLogin ...

  6. VS2013常用快捷键你敢不会?

    F1 帮助文档 F5 运行 F12 跳转到定义 F11 单步调试 Shift+F5 停止调试 Ctrl+滚轮 放大缩小当前视图 Ctrl+L 删除当前行 Ctrl+K,Ctrl+C 注释选中代码 Ct ...

  7. 【转】如何让你的Android SDK下载或者升级快如闪电

    准备学习Android开发,但是Android SDK Manager界面都刷不出来,今天看到了一篇文章,顿时就解决了,原文地址http://qichaochen.github.io/2014/12/ ...

  8. Angular.js Services

    Angular带来了很多类型的services.每个都会它自己不同的使用场景.我们将在本节来阐述. 首先我们必须记在心里的是所有的services都是singleton(单例)的,这也是我们所希望得到 ...

  9. Ubuntu杂记——Apache+PHP+MySQL的安装

    昨天晚上,参考博客园的另一篇文章,在自己的Ubuntu上搭建了一个Apache+PHP+MySQL的服务器,在此谨记,以备不时之需. 一.安装Apache sudo apt-get install a ...

  10. phpstorm 63342默认端口怎么修改

    phpstorm进行网页调试的时候,默认是加端口号63342,在配置本地php环境的时候默认端口不一定是63342这个,更多的是系统默认的端口号80,那么问题就出现了,如何在phpstorm中将633 ...