我知道会话和REST并不完全是齐头并进的,但是使用新的Web API访问会话状态是不可能的吗?session总是空的。
当前回答
要解决这个问题:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
在Global.asax.cs
其他回答
你说得对,REST是无状态的。如果您使用会话,处理将变成有状态的,后续请求将能够使用状态(来自会话)。
为了给会话补水,您需要提供一个键来关联状态。在普通的asp.net应用程序中,该密钥是通过使用cookie (cookie-sessions)或url参数(无cookie会话)来提供的。
如果你需要一个会话而不是休息,那么会话在基于rest的设计中是无关紧要的。如果您需要一个会话进行验证,则使用令牌或通过IP地址授权。
@LachlanB的回答中有一件事需要提一下。
protected void Application_PostAuthorizeRequest()
{
if (IsWebApiRequest())
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
如果省略了If (IsWebApiRequest())
如果你的网站混合了网页表单,整个网站都会有页面加载缓慢的问题。
要解决这个问题:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
在Global.asax.cs
MVC
对于MVC项目进行以下更改(WebForms和Dot Net Core的答案在下面):
WebApiConfig.cs
public static class WebApiConfig
{
public static string UrlPrefix { get { return "api"; } }
public static string UrlPrefixRelative { get { return "~/api"; } }
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
...
protected void Application_PostAuthorizeRequest()
{
if (IsWebApiRequest())
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
private bool IsWebApiRequest()
{
return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiConfig.UrlPrefixRelative);
}
}
这个解决方案有额外的好处,我们可以在javascript中获取基本URL来进行AJAX调用:
_Layout.cshtml
<body>
@RenderBody()
<script type="text/javascript">
var apiBaseUrl = '@Url.Content(ProjectNameSpace.WebApiConfig.UrlPrefixRelative)';
</script>
@RenderSection("scripts", required: false)
然后在我们的Javascript文件/代码,我们可以使我们的webapi调用,可以访问会话:
$.getJSON(apiBaseUrl + '/MyApi')
.done(function (data) {
alert('session data received: ' + data.whatever);
})
);
网络表单
执行上述操作,但更改WebApiConfig。寄存器函数来代替一个RouteCollection:
public static void Register(RouteCollection routes)
{
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
然后在Application_Start中调用以下命令:
WebApiConfig.Register(RouteTable.Routes);
网点核心
添加Microsoft.AspNetCore.Session NuGet包,然后进行以下代码更改:
Startup.cs
在ConfigureServices函数的服务对象上调用AddDistributedMemoryCache和AddSession方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
...
services.AddDistributedMemoryCache();
services.AddSession();
在Configure函数中添加一个对UseSession的调用:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseSession();
app.UseMvc();
SessionController.cs
在你的控制器中,在顶部添加一个using语句:
using Microsoft.AspNetCore.Http;
然后使用HttpContext。会话对象在你的代码中,如下所示:
[HttpGet("set/{data}")]
public IActionResult setsession(string data)
{
HttpContext.Session.SetString("keyname", data);
return Ok("session data set");
}
[HttpGet("get")]
public IActionResult getsessiondata()
{
var sessionData = HttpContext.Session.GetString("keyname");
return Ok(sessionData);
}
你现在应该可以点击:
http://localhost:1234/api/session/set/thisissomedata
然后转到这个URL会把它拉出来:
http://localhost:1234/api/session/get
更多关于在。net core中访问会话数据的信息请访问:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state
性能问题
下面是西蒙·韦弗关于性能的回答。如果你在WebApi项目中访问会话数据,可能会有非常严重的性能后果。NET对并发请求强制执行200ms延迟。如果您有许多并发请求,这可能会导致灾难性的后果。
安全问题
确保你为每个用户锁定了资源——一个经过身份验证的用户不应该能够从你的WebApi中检索他们没有权限访问的数据。
阅读微软关于ASP中的身份验证和授权的文章。NET Web API - https://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
阅读微软关于避免跨站点请求伪造黑客攻击的文章。(简而言之,看看AntiForgery。验证方法)- https://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks
根据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);
}
推荐文章
- 如何编辑。csproj文件
- 如何使用网络强制HTTPS。配置文件
- 如何在WebAPI上使用Swashbuckle省略Swagger文档中的方法
- 无法加载.ps1,因为在此系统上禁止执行脚本
- 找不到如何使用HttpContent
- 我如何循环通过日期范围?
- 无效的回发或回调参数。使用'<pages enableEventValidation="true"/>'启用事件验证
- 一个潜在的危险请求。从客户端检测到路径值(*)
- 从Web Api控制器返回http状态代码
- 为什么反应。重定向导致System.Threading.ThreadAbortException?
- 微软Web API:你如何做一个Server.MapPath?
- 使iframe高度动态基于内容里面- JQUERY/Javascript
- ASP。NET MVC Razor渲染没有编码
- 在ASP中服务favicon.ico。NET MVC
- 无法加载文件或程序集'Newtonsoft。Json,版本=4.5.0.0,文化=中性,PublicKeyToken=30ad4fe6b2a6aeed'