webapi中使用session
修改global.cs里面的内容
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()
{
//取下注释下面这行语句,将使得全部Api都可以访问Session
//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
}
}
}
webapi用例:
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();
}
}
//这个方法无法使用Session
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;
}
}
}
}
Web APi全局启动Session(一)
以下皆在Global.asax全局文件中进行。
第一步(定义两个变量)
private const string WebApiPrefix = "APi";
private static string WebApiExecutePath = string.Format("~/{0}", WebApiPrefix);
第二步(获取当前请求的路径)
private bool isWebAPiRequest() { return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiExecutePath); }
第三步(若请求Web APi则启动Session)
protected void Application_PostAuthorizeRequest() { if (isWebAPiRequest()) { HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); } }
第四步(测试代码)
protected void Session_Start()
{
HttpContext.Current.Session.Add("xpy0928", "嗨-博客"); var session_value = HttpContext.Current.Session["xpy0928"]; }
Web APi全局启动Session(二)
之前我们在Web APi系列中讲到过HttpControllerRouteHandler,此类中的GetHttpHandler方法返回HttpControllerHandler的一个实例即HttpHandler,通过此HttpHandler是进入Web APi消息处理管道的入口点,我们可以使用在IHttpHandler上的Session实现IRquiressionstate接口即可。
第一步(启动Session)
protected void Application_PostAuthorizeRequest() { HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); }
第二步(自定义实现HttpHandler)
public class EnableSession_ControllerHandler : HttpControllerHandler, IRequiresSessionState { public EnableSession_ControllerHandler(RouteData routeData) : base(routeData) { } }
第三步(获取HttpHandler)
public class EnableSession_ControllerHandler : HttpControllerHandler, IRequiresSessionState { public EnableSession_ControllerHandler(RouteData routeData) : base(routeData) { } }
第四步(路由配置进行获取自定义RouteHandler)
routes.MapHttpRoute(
name: "DefaultAPi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = UrlParameter.Optional }
).RouteHandler = new EnableSession_HttpControllerRouteHandler();
第五步(在Web APi配置文件中实现自定义HttpControllerRouteHandler)
public static void Register(HttpConfiguration config)
{
var httpControllerRouteHandler = typeof(HttpControllerRouteHandler).GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic); if (httpControllerRouteHandler != null) { httpControllerRouteHandler.SetValue(null, new Lazy<HttpControllerRouteHandler>(() => new EnableSession_HttpControllerRouteHandler(), true)); } config.MapHttpAttributeRoutes(); }
此时运行将出现如下错误:
第六步(测试代码)
public void Get()
{
object context; if (Request.Properties.TryGetValue("MS_HttpContext", out context)) { var httpContext = context as HttpContextBase; if (httpContext != null && httpContext.Session != null) { var lastValue = httpContext.Session["xpy0928"] as int?; httpContext.Session["xpy0928"] = "博客园"; var session_value = httpContext.Session["xpy0928"]; } } }
总结
以上两种方法皆可在Web APi中启动Session,你觉得那个简单就按照对应的来。我们需要注意一个问题是:在Web APi中,Web APi是不依赖于HttpContext,也就是HttpContext.Current肯定是为null的,我们要访问Session或者其他对象需要使用Rquest对象中的属性Properties来获得你想的值或者来设置值。
在Controller里:
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
var context = HttpContext.Current;
context.Session["a"] = "aaa";
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
var ses = HttpContext.Current.Session["a"];
return ses.ToString();
}
}
执行时出报异常,这时要在Global.asax里添加:开启Session功能
public class WebApiApplication : System.Web.HttpApplication
{
public override void Init()
{
this.PostAuthenticateRequest += (sender, e) => HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
base.Init();
}
}
----------------------------------------------------------------------------------------------
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“sv”。
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class sv : Isv
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class sv : Isv
<system.serviceModel>
<services>
<service name="Tools.sv">
<endpoint address="" binding="webHttpBinding" bindingConfiguration=""
contract="Tools.Isv" />
</service>
</services>
<bindings />
<behaviors>
<endpointBehaviors>
<behavior name="">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<standardEndpoints />
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"></serviceHostingEnvironment>
<services>
<service name="Tools.sv">
<endpoint address="" binding="webHttpBinding" bindingConfiguration=""
contract="Tools.Isv" />
</service>
</services>
<bindings />
<behaviors>
<endpointBehaviors>
<behavior name="">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<standardEndpoints />
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"></serviceHostingEnvironment>