Asp.net MVC4 WebAPI启用Session

小柊 发表于 2017年02月22日 19时08分48秒

原标题:Asp.net MVC4 WebAPI Session总是为null的解决方案

一、背景

之前群里有位大神说,现在Web开发最好的结构就是MVC+WebAPI+AngularJS/Ajax,通过这样来降低后端对前端的控制和影响。

正好最近在整理一个项目的代码,这个项目原本有一个BackGroundController控制器,里面所有的Action返回的都是JsonResult,心里想想干脆就改成WebAPI算了。结果改代码改到一半的时候发现了一个问题:由于有个数据提交接口的代码做了防机器提交的操作,所以在执行的时候需要访问Session取得验证字符串。但在访问Session的时候直接被抛出了NullReferenceException。

经过检查,发现是HttpContext.Current.Session为null,才使得在这里抛出异常。

 

但单步调试的时候,发现普通的Controller是可以正常访问Session对象的,也可以将随机字符串写入Session之中,就是ApiController无法访问Session。

 

二、问题原因

没办法,逛了一圈Stack Overflow,发现有很多类似的问题,最后看到这个问题《ASP.NET Web API session or something?》,下面有一个非常完美的回答:

Well, REST by design is stateless. By adding session (or anything else of that kind) you are making it stateful and defeating any purpose of having a RESTful API.

The whole idea of RESTful service is that every resource is uniquely addressable using a universal syntax for use in hypermedia links and each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP".

So whatever you are trying to do with Web API here, should most likely be re-architectured if you wish to have a RESTful API.

With that said, if you are still willing to go down that route, there is a hacky way of adding session to Web API, and it's been posted by Imran here http://forums.asp.net/t/1780385.aspx/1

Filip W

 

个人渣翻:

很好,REST本来就是被设计为无状态的。通过添加Session(或者任何其他类似的)你让它成为有状态的,这就违反了RESTful的所有宗旨。

RESTful服务的整体思想是所有资源都能使用通用的语法进行唯一寻址,当使用超链接时,每一个HTTP请求自身应该可以携带足够的信息,使其接收者处理它能与HTTP的无状态特性完全协调。

所以无论如何,你要在这里尝试使用Web API的话,如果你希望有一个RESTful API的话都应该进行重新设计。

不过呢,如果你还是要沿着你现在的这条路走下去,这里有一个添加Session到Web API的解决方法,它由Imran发布在这里:http://forums.asp.net/t/1780385.aspx/1

Filip W

 

为什么ApiController访问Session为null的原因这下明白了:

Asp.net MVC WebAPI是基于RESTful标准的,而RESTful标准最重要的原则是客户与服务器之间的交互是无状态的。如果在WebAPI里添加了Session就打破了这条原则,所以在ApiController里默认是访问不了Session的。

 

那除了重新设计接口以外还有没有别的解决方法了呢?

当然还是有的。

 

三、解决方案

解决方案有两种,以下两种方案二选一:

1.重写Global.asax的Init()方法

打开Asp.net MVC WebAPI项目根目录下的Global.asax文件。

添加以下代码:

 

 

SessionStateBehavior是一个枚举类型,具体每一项的含义是:

Default 使用默认 ASP.NET 逻辑来确定请求的会话状态行为。默认逻辑是寻找 System.Web.IHttpHandler 中是否存在标记会话状态接口。
Disabled 未启用会话状态来处理请求。此设置将覆盖已通过检查请求的处理程序确定的任何会话行为。
ReadOnly 为请求启用只读会话状态。这意味着会话状态无法更新。此设置将覆盖已通过检查请求的处理程序确定的任何会话状态行为。
Required 为请求启用完全的读写会话状态行为。此设置将覆盖已通过检查请求的处理程序确定的任何会话行为。

参考:《SessionStateBehavior Enumeration

 

2.修改WebApiConfig.cs

打开Asp.net MVC WebAPI项目App_Start目录下的WebApiConfig.cs文件。

先添加四个命名空间:

 

然后在namespace范围内加入以下两个类:

 

之后修改一下WebApiConfig类中的Register方法第一行和最后一行。

把第一行的:

 

改成:

 

把最后一行的:

 

改成:

 

即可。

 

四、重新调试

按【三】中的解决方案改好代码之后按F5重新启动调试,在访问Session的地方设下断点看一下Session的情况:

 

可以看到这时候ApiController可以正常的访问Session了。

 

 

 

小柊

2017年2月22日 19:03:24

相关文章

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注