我知道会话和REST并不完全是齐头并进的,但是使用新的Web API访问会话状态是不可能的吗?session总是空的。
当前回答
为什么在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)。
其他回答
回到基础,为什么不保持它的简单和存储会话值在一个隐藏的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 */}
}
最后一个不行,拿这个,我用过。
在WebApiConfig.cs中的App_Start
public static string _WebApiExecutionPath = "api";
public static void Register(HttpConfiguration config)
{
var basicRouteTemplate = string.Format("{0}/{1}", _WebApiExecutionPath, "{controller}");
// Controller Only
// To handle routes like `/api/VTRouting`
config.Routes.MapHttpRoute(
name: "ControllerOnly",
routeTemplate: basicRouteTemplate//"{0}/{controller}"
);
// Controller with ID
// To handle routes like `/api/VTRouting/1`
config.Routes.MapHttpRoute(
name: "ControllerAndId",
routeTemplate: string.Format ("{0}/{1}", basicRouteTemplate, "{id}"),
defaults: null,
constraints: new { id = @"^\d+$" } // Only integers
);
Global.asax
protected void Application_PostAuthorizeRequest()
{
if (IsWebApiRequest())
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
private static bool IsWebApiRequest()
{
return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(_WebApiExecutionPath);
}
第四点:http://forums.asp.net/t/1773026.aspx/1
您可以使用自定义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
是的,会话与Rest API并不是紧密相连的,而且我们应该避免这种做法。但是根据需求,我们需要以某种方式维护会话,以便在每个请求中客户端服务器可以交换或维护状态或数据。因此,在不破坏REST协议的情况下实现这一点的最佳方法是通过JWT这样的令牌进行通信。
https://jwt.io/
根据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);
}
推荐文章
- 什么是Kestrel (vs IIS / Express)
- 如何为ASP.net/C#应用程序配置文件值中的值添加&号
- 我如何解决“HTTP错误500.19 -内部服务器错误”在IIS7.0
- 可选查询字符串参数。NET Web API
- 将列表序列化为JSON
- 运行计划任务的最佳方式
- Global.asax中的“解析器错误消息:无法加载类型”
- 什么时候我应该在ASP中使用异步控制器。净MVC吗?
- ASP。NET“特殊”标签
- 如何编辑。csproj文件
- 如何使用网络强制HTTPS。配置文件
- 如何在WebAPI上使用Swashbuckle省略Swagger文档中的方法
- 无法加载.ps1,因为在此系统上禁止执行脚本
- 找不到如何使用HttpContent
- 我如何循环通过日期范围?