C#学习教程:在Identity Framework的方法中,HttpContext.Current为null分享


在Identity Framework的方法中,HttpContext.Current为null

我正在使用ASP.NET MVC 5和Identity Framework。 当我在ApplicationDbContext()上调用UserManager.UpdateAsync(…)时,我的事件处理程序将运行SaveChanges。 这里我使用HttpContext.Current用于不同的目的(日志记录和审计)所以我必须说当前用户。 但是整个方法在一个工作线程中运行,这里HttpContext.Current为null。

UserManager的“同步”方法最大的问题只是异步版本的包装,因此调用是序列化的,但方法(和事件处理程序)仍然在不同的工作线程中运行。

请注意,此问题与async / await上下文无关。 在await之后的控制器中(或调用’sync’版本)我已经返回正确的HttpContext,即使控制器的方法在另一个线程中继续。 没关系。

所以问题出在异步工作者中,它将同时在“同步”和异步版本中运行。 我想我理解这种现象(但我对假’同步’方法版本不满意,真正的同步方法不会出现这个问题。)我只是不知道如何处理/解决它。

[btw:将UserManager的操作实现为简单的纯同步版本,然后用异步multithreading包装器包装它们不是更自然吗? 如果我们继续这种异步方式而不考虑我们将很快发明异步赋值运算符。 它花了我几十个小时(只是这个问题),全球成本高达数十亿美元,我相信在很多情况下,它的回报低于它的价格。

额外奖励:我们所说的UserManager的影响非常小,但相同的原则和问题可以应用任何开箱即用的库(黑盒子),作者没有实现同步版本,或者不关心控制器线程的上下文。 那么EF,它不是那么边缘……那么DI容器实例化基础设施如“请求范围”或“会话范围”呢? 如果在没有HttpContext.Current的线程中进行解析,他们肯定会行为不端。 最近我刷新了SendGrid NuGet,并且(作为一个突破性的变化)Deliver()方法消失了,现在只有DeliverAsync()存在…

我想有一个安全可靠的方法,如何访问此worker中的HttpContext以进行日志记录和审计。

示例代码,控制器’sync’版本:

[AcceptVerbs(HttpVerbs.Post)] public virtual ActionResult Edit(ApplicationUser user) { // validation etc // Update() seems to be only a poor wrapper around the async version, still uses a worker thread. var result = UserManager.Update(user); // Note: HttpContext is correct here so it is not an async/await problem // error handling, creating ActionResult etc. } 

示例代码,控制器异步版本:

 [AcceptVerbs(HttpVerbs.Post)] public virtual async Task Edit(ApplicationUser user) { // validation etc var result = await UserManager.UpdateAsync(user); // Note: HttpContext is correct here so it is not an async/await problem // error handling, creating ActionResult etc. } 

和HttpContext为null的事件处理程序:

 public ApplicationDbContext() : base("DefaultConnection", false) { InitializeAudit(); } private void InitializeAudit() { var octx = ((IObjectContextAdapter) this).ObjectContext; octx.SavingChanges += (sender, args) => { // HttpContext.Current is null here }; } 

有任何想法吗?

如你所说,这是因为线程。 委托在不同的线程中运行,使得HttpContext无法访问。

您可以将变量移到委托之外,使其成为闭包。

 private void InitializeAudit() { var octx = ((IObjectContextAdapter) this).ObjectContext; HttpContext context = HttpContext.Current; octx.SavingChanges += (sender, args) => { // context is not null }; } 

您正在通过owin使用asp.net标识,因此每个请求都会创建一个dbcontext实例,您可以从请求管道中的任何位置获取此引用。

NB。 这很方便,但我认为不应该在经理外部访问dbcontext。 在asp.net身份设计中,只有经理应该知道商店。 我相信dbcontext是暴露的,因为有几个asp.net身份中间件依赖于它。

但是,它可以帮助您解决问题:

允许在类外部设置自定义dbcontext处理程序:

 public EventHandler SavingChangesEventHandler { set { (((System.Data.Entity.Infrastructure.IObjectContextAdapter)this).ObjectContext).SavingChanges += value; } } 

声明一个自定义ActionFilter类并注册它,然后重写OnActionExecuting:

在ASP.NET MVC中过滤https://msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx

 public class CustomizeAppDbcontextFilter : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var dbcontext = HttpContext.GetOwinContext().Get(); var currentuser = HttpContext.Current.User; dbcontext.SavingChangesEventHandler = (sender, args) => { // use currentuser }; } } 

您可能需要这些using语句才能调用identity.owin扩展方法:

使用Microsoft.AspNet.Identity;

使用Microsoft.AspNet.Identity.Owin;

您应该在控制器线程中,因为OnActionExecuting正在包装控制器操作。

我没有测试它,所以它可能需要一些抛光,但这个概念应该有效。

上述就是C#学习教程:在Identity Framework的方法中,HttpContext.Current为null分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/1031826.html

发表评论

邮箱地址不会被公开。 必填项已用*标注