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

来源:互联网 发布:coc加农炮升级数据 编辑:程序博客网 时间:2024/06/06 13:56

        在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。



0 0
原创粉丝点击