我知道会话和REST并不完全是齐头并进的,但是使用新的Web API访问会话状态是不可能的吗?session总是空的。
当前回答
你说得对,REST是无状态的。如果您使用会话,处理将变成有状态的,后续请求将能够使用状态(来自会话)。
为了给会话补水,您需要提供一个键来关联状态。在普通的asp.net应用程序中,该密钥是通过使用cookie (cookie-sessions)或url参数(无cookie会话)来提供的。
如果你需要一个会话而不是休息,那么会话在基于rest的设计中是无关紧要的。如果您需要一个会话进行验证,则使用令牌或通过IP地址授权。
其他回答
回到基础,为什么不保持它的简单和存储会话值在一个隐藏的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 */}
}
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项目中借用这个类。
@LachlanB的回答中有一件事需要提一下。
protected void Application_PostAuthorizeRequest()
{
if (IsWebApiRequest())
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
如果省略了If (IsWebApiRequest())
如果你的网站混合了网页表单,整个网站都会有页面加载缓慢的问题。
我在asp.net mvc中也有同样的问题,我把这个方法放在我的基础api控制器中,我所有的api控制器都继承了这个方法:
/// <summary>
/// Get the session from HttpContext.Current, if that is null try to get it from the Request properties.
/// </summary>
/// <returns></returns>
protected HttpContextWrapper GetHttpContextWrapper()
{
HttpContextWrapper httpContextWrapper = null;
if (HttpContext.Current != null)
{
httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
}
else if (Request.Properties.ContainsKey("MS_HttpContext"))
{
httpContextWrapper = (HttpContextWrapper)Request.Properties["MS_HttpContext"];
}
return httpContextWrapper;
}
然后在你想要访问会话的api调用中,你只需要做:
HttpContextWrapper httpContextWrapper = GetHttpContextWrapper();
var someVariableFromSession = httpContextWrapper.Session["SomeSessionValue"];
我在我的Global.asax.cs文件中也有这个,就像其他人发布的一样,不确定你是否仍然需要使用上面的方法,但这里只是以防万一:
/// <summary>
/// The following method makes Session available.
/// </summary>
protected void Application_PostAuthorizeRequest()
{
if (HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith("~/api"))
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
你也可以只做一个自定义过滤器属性,你可以粘在你的api调用,你需要会话,然后你可以在你的api调用中使用会话,就像你通常会通过HttpContext.Current.Session["SomeValue"]:
/// <summary>
/// Filter that gets session context from request if HttpContext.Current is null.
/// </summary>
public class RequireSessionAttribute : ActionFilterAttribute
{
/// <summary>
/// Runs before action
/// </summary>
/// <param name="actionContext"></param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (HttpContext.Current == null)
{
if (actionContext.Request.Properties.ContainsKey("MS_HttpContext"))
{
HttpContext.Current = ((HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"]).ApplicationInstance.Context;
}
}
}
}
希望这能有所帮助。
我采用了@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);
}
}
推荐文章
- 转换JSON字符串到JSON对象c#
- IIS7部署-重复` system.web。扩展/脚本/ scriptResourceHandler”部分
- 如何用msbuild发布Web ?
- Swagger UI Web Api文档呈现枚举字符串?
- 为什么使用HttpClient进行同步连接
- Visual Studio 2012 Web Publish不复制文件
- 成员“<成员名>”不能通过实例引用访问
- 如何返回一个文件(FileContentResult)在ASP。净WebAPI
- 什么是Kestrel (vs IIS / Express)
- 如何为ASP.net/C#应用程序配置文件值中的值添加&号
- 我如何解决“HTTP错误500.19 -内部服务器错误”在IIS7.0
- 可选查询字符串参数。NET Web API
- 将列表序列化为JSON
- 运行计划任务的最佳方式
- Global.asax中的“解析器错误消息:无法加载类型”