您的位置:首页 > 移动开发

ASP.NET Web Api中使用Session、Cache和Application的几个方法

2015-08-31 15:29 417 查看
在ASP.NET中,Web Api的控制器类派生自ApiControll,该类与ASP.NET的Control类没有直接关系,因此不能像在ASPX.CS代码隐藏类中直接使用HttpContext、HttpApplicationState或HttpSessionState等状态数据。要使用的话,一般是从System.Web.HttpContext.Current静态对象引用HttpContext,从而使用Session等状态数据。

不过,要在控制器类中通过HttpContext的Session属性直接使用Session状态数据,将抛出null reference异常。网查主要有两个解决办法,一个是重载Global的Init()方法,在该方法的中开放Session状态,另一个设计带Session的路由处理器。

下面代码是包含两个解决方法的Global类。

<pre name="code" class="csharp">using System;
using System.Web;
using System.Web.Routing;
using System.Web.Http;
using System.Web.Http.WebHost;
using System.Web.SessionState;

namespace ApiControllerExample
{
public class Global : System.Web.HttpApplication
{

public override void Init()
{
//this.PostAuthenticateRequest += (s, e) => HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
base.Init();
}

protected void Application_Start(object sender, EventArgs e)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);  // 注册路由
}
}

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

public class SessionStateRouteHandler : IRouteHandler
{
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return new SessionableControllerHandler(requestContext.RouteData);
}
}

public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapHttpRoute(
name: "WebApiRoute1",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
).RouteHandler = new SessionStateRouteHandler();  // 使用Session

routes.MapHttpRoute(
name: "WebApiRoute2",
routeTemplate: "api/{controller}/{id}/{id2}",
defaults: new{id = RouteParameter.Optional }
);  // 不使用Session
}
}
}


为测试上述行为,编写了如下控制器代码。

using System;
using System.Web.Http;

namespace ApiControllerExample
{
public class StateController : ApiController
{
public string Get(int id)
{
try
{
return  GetStateInfo(id);
}
catch (Exception err)
{
return "excep: " + err.Message;
}
}

private string GetStateInfo(int id)
{
System.Web.HttpContext context = System.Web.HttpContext.Current;

if (id == 1)
{
return context.Session["state"].ToString();
}
else if (id == 2)
{
return context.Cache["state"].ToString();
}
else
{
return context.Application["state"].ToString();
}
}

public string Get(int id, int id2)
{
System.Web.HttpContext context = System.Web.HttpContext.Current;

try
{
return context.Session["state"].ToString();
}
catch (Exception err)
{
return "excep: " + err.Message;
}
}
}
}
下面是测试用的ASPX网页代码。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ApiControllerExample.Test" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script>
        function GetXmlHttpRequest() {
            if (window.XMLHttpRequest) {
                return new XMLHttpRequest();
            }
            else if (window.ActiveXObject) {
                return new ActiveXObject("Microsoft.XMLHTTP");
            }
            return null;
        }

        function GetState(id) {
            var request = GetXmlHttpRequest();
            var url = "/api/state/" + id;
            request.open("GET", url, false);
            request.send(null);
            alert(request.responseText);
        }

        function GetState2() {
            var request = GetXmlHttpRequest();
            var url = "/api/state/1/1";
            request.open("GET", url, false);
            request.send(null);
            alert(request.responseText);
        }
    </script>
</head>
<body>
    <input type="button" value="GetSession" onclick="GetState(1)" />
    <input type="button" value="GetCache" onclick="GetState(2)" />
    <input type="button" value="GetAppication" onclick="GetState(3)" />
    <input type="button" value="GetSession(state2)" onclick="GetState2()" />
</body>
</html>

下面是网页的代码隐藏类。

using System;

namespace ApiControllerExample
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string time = DateTime.Now.ToString();

Session["state"] = time;
Cache["state"] = time;
Application["state"] = time;
}
}
}
测试时,可以取消Global类中的有关注释即可。

比较两个实现方法可以知道,使用带Session的路由处理器方法可以指定某个路由开放Session(比如上面的api/{controller}/{id}/{id2},就不能读取Session中的数据)。而使用Global的Init()方法中开放Session,将使得全部Api都可以访问Session。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: