我知道会话和REST并不完全是齐头并进的,但是使用新的Web API访问会话状态是不可能的吗?session总是空的。
当前回答
回到基础,为什么不保持它的简单和存储会话值在一个隐藏的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 */}
}
其他回答
你说得对,REST是无状态的。如果您使用会话,处理将变成有状态的,后续请求将能够使用状态(来自会话)。
为了给会话补水,您需要提供一个键来关联状态。在普通的asp.net应用程序中,该密钥是通过使用cookie (cookie-sessions)或url参数(无cookie会话)来提供的。
如果你需要一个会话而不是休息,那么会话在基于rest的设计中是无关紧要的。如果您需要一个会话进行验证,则使用令牌或通过IP地址授权。
要解决这个问题:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
在Global.asax.cs
为什么在WebAPI中避免使用Session ?
业绩,业绩,业绩!
有一个很好的,但经常被忽视的原因,为什么你不应该在WebAPI中使用Session。
ASP。NET在使用Session时的工作是序列化从单个客户端接收的所有请求。现在我不是在谈论对象序列化——而是按照接收到的顺序运行它们,并在运行下一个之前等待每个对象完成。这是为了避免当两个请求同时访问Session时出现糟糕的线程/竞争情况。
Concurrent Requests and Session State Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.) If the EnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.
那么这对Web API意味着什么呢?如果您的应用程序运行许多AJAX请求,那么一次只能运行一个。如果你有一个较慢的请求,那么它将阻止来自该客户端的所有其他请求,直到它完成。在某些应用程序中,这可能会导致非常明显的缓慢性能。
因此,如果你绝对需要用户会话中的某些东西,你可能应该使用MVC控制器,以避免为WebApi启用它所带来的不必要的性能损失。
你可以通过将Thread.Sleep(5000)放在WebAPI方法中并启用Session来轻松测试。向它运行5个请求,总共需要25秒才能完成。如果没有塞申斯,他们总共只需要5秒多一点。
(同样的道理也适用于SignalR)。
我在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;
}
}
}
}
希望这能有所帮助。
是的,会话与Rest API并不是紧密相连的,而且我们应该避免这种做法。但是根据需求,我们需要以某种方式维护会话,以便在每个请求中客户端服务器可以交换或维护状态或数据。因此,在不破坏REST协议的情况下实现这一点的最佳方法是通过JWT这样的令牌进行通信。
https://jwt.io/
推荐文章
- 如何在没有任何错误或警告的情况下找到构建失败的原因
- Post参数始终为空
- 有没有办法注释掉.ASPX页面中的标记?
- jQuery为ajax请求返回“parsererror”
- 不带查询字符串获取url
- <%$, <%@, <%=, <%#…怎么回事?
- 无法找到适合特定区域性或中性区域性的任何资源
- 转换JSON字符串到JSON对象c#
- IIS7部署-重复` system.web。扩展/脚本/ scriptResourceHandler”部分
- 如何用msbuild发布Web ?
- Swagger UI Web Api文档呈现枚举字符串?
- 为什么使用HttpClient进行同步连接
- Visual Studio 2012 Web Publish不复制文件
- 成员“<成员名>”不能通过实例引用访问
- 如何返回一个文件(FileContentResult)在ASP。净WebAPI