我知道会话和REST并不完全是齐头并进的,但是使用新的Web API访问会话状态是不可能的吗?session总是空的。
当前回答
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
其他回答
我在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;
}
}
}
}
希望这能有所帮助。
回到基础,为什么不保持它的简单和存储会话值在一个隐藏的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的回答,如果你的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);
}
要解决这个问题:
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
推荐文章
- 如何编辑。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'