我知道会话和REST并不完全是齐头并进的,但是使用新的Web API访问会话状态是不可能的吗?session总是空的。
当前回答
我采用了@LachlanB方法,当请求上有会话cookie时,会话确实是可用的。缺失的部分是会话cookie是如何第一次发送到客户端?
我创建了一个HttpModule,它不仅启用httpessionstate可用性,而且还在创建新会话时向客户端发送cookie。
public class WebApiSessionModule : IHttpModule
{
private static readonly string SessionStateCookieName = "ASP.NET_SessionId";
public void Init(HttpApplication context)
{
context.PostAuthorizeRequest += this.OnPostAuthorizeRequest;
context.PostRequestHandlerExecute += this.PostRequestHandlerExecute;
}
public void Dispose()
{
}
protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (this.IsWebApiRequest(context))
{
context.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
protected virtual void PostRequestHandlerExecute(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (this.IsWebApiRequest(context))
{
this.AddSessionCookieToResponseIfNeeded(context);
}
}
protected virtual void AddSessionCookieToResponseIfNeeded(HttpContext context)
{
HttpSessionState session = context.Session;
if (session == null)
{
// session not available
return;
}
if (!session.IsNewSession)
{
// it's safe to assume that the cookie was
// received as part of the request so there is
// no need to set it
return;
}
string cookieName = GetSessionCookieName();
HttpCookie cookie = context.Response.Cookies[cookieName];
if (cookie == null || cookie.Value != session.SessionID)
{
context.Response.Cookies.Remove(cookieName);
context.Response.Cookies.Add(new HttpCookie(cookieName, session.SessionID));
}
}
protected virtual string GetSessionCookieName()
{
var sessionStateSection = (SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");
return sessionStateSection != null && !string.IsNullOrWhiteSpace(sessionStateSection.CookieName) ? sessionStateSection.CookieName : SessionStateCookieName;
}
protected virtual bool IsWebApiRequest(HttpContext context)
{
string requestPath = context.Request.AppRelativeCurrentExecutionFilePath;
if (requestPath == null)
{
return false;
}
return requestPath.StartsWith(WebApiConfig.UrlPrefixRelative, StringComparison.InvariantCultureIgnoreCase);
}
}
其他回答
您可以使用自定义RouteHandler访问会话状态。
// In global.asax
public class MvcApp : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
var route = routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
route.RouteHandler = new MyHttpControllerRouteHandler();
}
}
// Create two new classes
public class MyHttpControllerHandler
: HttpControllerHandler, IRequiresSessionState
{
public MyHttpControllerHandler(RouteData routeData) : base(routeData)
{ }
}
public class MyHttpControllerRouteHandler : HttpControllerRouteHandler
{
protected override IHttpHandler GetHttpHandler(
RequestContext requestContext)
{
return new MyHttpControllerHandler(requestContext.RouteData);
}
}
// Now Session is visible in your Web API
public class ValuesController : ApiController
{
public string Get(string input)
{
var session = HttpContext.Current.Session;
if (session != null)
{
if (session["Time"] == null)
session["Time"] = DateTime.Now;
return "Session Time: " + session["Time"] + input;
}
return "Session is not availabe" + input;
}
}
在这里找到:http://techhasnoboundary.blogspot.com/2012/03/mvc-4-web-api-access-session.html
根据LachlanB的回答,如果你的ApiController不在特定的目录(比如/api)中,你可以使用RouteTable.Routes来测试请求。GetRouteData,例如:
protected void Application_PostAuthorizeRequest()
{
// WebApi SessionState
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
if (routeData != null && routeData.RouteHandler is HttpControllerRouteHandler)
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
Mark,如果你检查nerddinner MVC示例,逻辑几乎是一样的。
您只需要检索cookie并在当前会话中设置它。
Global.asax.cs
public override void Init()
{
this.AuthenticateRequest += new EventHandler(WebApiApplication_AuthenticateRequest);
base.Init();
}
void WebApiApplication_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
SampleIdentity id = new SampleIdentity(ticket);
GenericPrincipal prin = new GenericPrincipal(id, null);
HttpContext.Current.User = prin;
}
enter code here
您必须定义“SampleIdentity”类,可以从nerddinner项目中借用这个类。
回到基础,为什么不保持它的简单和存储会话值在一个隐藏的html值传递给你的API?
控制器
public ActionResult Index()
{
Session["Blah"] = 609;
YourObject yourObject = new YourObject();
yourObject.SessionValue = int.Parse(Session["Blah"].ToString());
return View(yourObject);
}
cshtml
@model YourObject
@{
var sessionValue = Model.SessionValue;
}
<input type="hidden" value="@sessionValue" id="hBlah" />
Javascript
$(文件)。准备(函数(){
var sessionValue = $('#hBlah').val();
alert(sessionValue);
/* Now call your API with the session variable */}
}
@LachlanB的回答中有一件事需要提一下。
protected void Application_PostAuthorizeRequest()
{
if (IsWebApiRequest())
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
如果省略了If (IsWebApiRequest())
如果你的网站混合了网页表单,整个网站都会有页面加载缓慢的问题。
推荐文章
- 使用ASP访问会话。NET Web API
- 会话锁导致ASP。网络网站速度慢
- jQuery用户界面对话框。NET按钮回发
- 如何在Visual Studio中启用NuGet包恢复?
- 请求格式无法识别URL意外以
- 可以吗网上广告
- 对于每个循环,确定哪个是循环的最后一次迭代
- ViewResult()和ActionResult()的区别
- 系统。方法未找到?
- “由于扩展配置的原因,您请求的页面无法提供服务”错误消息
- 如何在HttpClient的HttpRequestMessage上设置cookie
- HttpClient不支持c# PostAsJsonAsync方法
- IIS/ASP的所有用户帐户是什么?NET和它们有什么不同?
- Web应用程序项目[…]]配置为使用IIS。Web服务器[…]找不到。
- 日志记录最佳实践