c# - 异步任务在自定义操作过滤器中挂起?

标签 c# asp.net-mvc asynchronous

我需要你的帮助!我已经研究这个问题有一段时间了,但一直无法弄清楚。假设我们有以下 Controller :

class NotifierController : MyBaseController {
    ... 
    [HttpGet]
    [CanNotifyUser]
    public async Task<ActionResult> NotifyUser(string id)
    {
        return View(await DataBase.Users.FindAsync(id));
    }
    // More actions decorated with the CanNotifyUserAttribute attribute
}

DataBaseMyBaseController 中定义的属性像:

static ApplicationDbContext _appDbContext;
public ApplicationDbContext DataBase 
{ 
    get { return _appDbContext ?? (_appDbContext = new ApplicationDbContext()); } 
}

ApplicationDbContext继承自IdentityDbContext<MyUser>哪里MyUser继承自IdentityUser 。所以,我的问题(我认为)涉及自定义操作过滤器 CanNotifyUserAttribute ,其OnActionExecuting override 定义为(删除所有检查以尽可能减少):

public override async void OnActionExecuting(ActionExecutingContext filterContext)
{
    NotifierController controller = filterContext.Controller as NotifierController;
    Boss boss = await controller.DataBase.Bosses.FindAsync(filterContext.HttpContext.User.Identity.GetUserId());
    object id = filterContext.ActionParameters["id"];
    User user = await controller.DataBase.Users.FindAsync(id.ToString());
    if (user.Department.Id != boss.Department.Id)
    {
        filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary(
                new
                {
                    action = "Login",
                    controller = "Account",
                    returnUrl = controller.Url.Action("NotifyUser", new { id = id })
                }));
    }
    base.OnActionExecuting(filterContext);
}

此属性的想法是验证老板是否仅向其部门的用户发送通知。现在奇怪的部分来了,这只发生在我第一次尝试向用户发送通知时(无论是否属于同一部门),错误抛出是:

[InvalidOperationException: An asynchronous module or handler completed while an asynchronous operation was still pending.]

如果我尝试(在错误之后)相同的请求(即通知用户),它会按照扩展方式工作,或者重定向或发送通知。

根据this post我可能会在异步任务完成之前完成请求(如果我理解得很好),但我一直在使用的所有任务都是 await ed所以我不知道这个错误可能来自哪里。希望你能帮我。提前致谢!

最佳答案

您尝试通过将 OnActionExecuting 转换为 async void 来在过滤器上强制执行异步行为。 asnyc void 方法只能在异步事件处理程序的上下文中使用,因为它们具有特殊的错误处理语义,并且调用进程“无法”等待 (filter-) 内执行的任务方法的主体(要进一步阅读,请考虑 this Stephen Cleary 的精彩文章)。

因此,对于 ASP.NET Core,请考虑使用 IAsyncActionFilter而是接口(interface)。

Filters support both synchronous and asynchronous implementations through different interface definitions. [...] Asynchronous filters define a single OnStageExecutionAsync method. This method takes a FilterTypeExecutionDelegate delegate which executes the filter's pipeline stage. (Filters in ASP.NET Core)

所以而不是...

public override async void OnActionExecuting(ActionExecutingContext filterContext)

...使用:

public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)

有关如何使用此功能的更多说明,请参阅:Async OnActionExecuting in ASP.NET Core's ActionFilterAttribute

关于c# - 异步任务在自定义操作过滤器中挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44339433/

相关文章:

c# - bool 转换问题的枚举

c# - X509CertificateValidationMode 在 Linux 中不起作用?

jquery - 如何插入jQuery代码? Uncaught ReferenceError : $ is not defined in view razor code

c# - Web API 中长期对象的依赖注入(inject)?

ios - 更新数据与更新 UI 的困境

javascript - 如何从异步调用返回响应?

c# - 如何识别点击了哪个按钮? (MVVM)

c# - 使用 ThreadPool.QueueUserWorkItem 和使用 System.Thread 有什么区别?

c# - 如何使用标准 MVC Core 依赖注入(inject)解决未注册的类型

javascript - 在异步函数更新 Node.js 模块后,如何从该模块返回值?