自定义操作过滤器中有待处理的异步任务? [英] Asynchronous task pending in custom action filter?

查看:70
本文介绍了自定义操作过滤器中有待处理的异步任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要您的帮助!我已经解决了好一阵子了,但我一直无法弄清楚.假设我们有以下控制器:

I need your help! I've been a while around this and I haven't been able to figure it out. Let's suppose we have the following 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
}

DataBase是在MyBaseController中定义的属性,例如:

DataBase is a property defined in MyBaseController like:

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

ApplicationDbContextIdentityDbContext<MyUser>继承,其中MyUserIdentityUser继承.因此,我的问题(我认为)来自自定义操作过滤器CanNotifyUserAttribute,其OnActionExecuting替代定义为(删除所有检查以尽可能减少):

ApplicationDbContext inherits from IdentityDbContext<MyUser> where MyUser inherits from IdentityUser. So, my problem (I think) comes to the custom action filter CanNotifyUserAttribute, whose OnActionExecuting override is defined as (removing all checks to reduce as much as possible):

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);
}

具有此属性的想法是验证老板仅将通知发送给其部门的用户.现在出现了一个奇怪的部分,这仅在我第一次尝试向用户发送通知(无论它是否属于同一部门)时发生,错误提示是:

The idea with this attribute is to verify that a boss sends notifications to the users of his department only. Now comes the strange part, this only happens the first time I try to send a notification to an user (no matter whether it's of the same department or not), the error thronw is:

[InvalidOperationException:异步模块或处理程序在异步操作仍处于挂起状态时完成.]

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

如果我尝试(在错误发生后)相同的请求(即通知用户),则该请求的工作方式如扩展重定向或发送通知.

If I try (after the error) the same request (i.e., notify the user) it works as expexted either redirecting or sending the notification.

根据这篇文章在异步任务完成之前,我可能已经完成了请求(如果我理解得很好),但是我一直在使用的所有任务都被await了,所以我不知道此错误可能来自何处.希望您能够帮助我.预先感谢!

According to this post I might be finishing the request (If I understood well) before an asynchronous task is finished, but all the tasks I've been using are all awaited so I don't know where this error may come from. Hope you can help me. Thanks in advance!

推荐答案

您正试图通过将OnActionExecuting转换为async void来对过滤器实施异步行为. asnyc void方法仅应在异步事件处理程序的上下文中使用,这是由于其特殊的错误处理语义以及调用过程无法"等待(过滤方法)体内执行的任务(以供进一步阅读)的原因. ,请考虑这篇 Stephen Cleary的出色文章).

You are trying to enforce async behaviour on your filter by turning OnActionExecuting into an async void. asnyc void methods should only be used in the context of asynchronous event handlers due to their special error-handling semantics and the "inability" of the calling process to wait for the tasks executed inside your (filter-)method's body (for further reading, consider this great article by Stephen Cleary).

因此,对于ASP.NET Core,请考虑使用

Therefore, with ASP.NET Core, consider using the IAsyncActionFilter interface instead.

过滤器通过不同的接口定义支持同步和异步实现.异步过滤器定义单个OnStageExecutionAsync方法.此方法接受一个FilterTypeExecutionDelegate委托,该委托执行过滤器的管道阶段. ( ASP.NET中的过滤器核心)

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)

有关如何使用此功能的更多说明,请参见:在ASP中执行异步OnActionExecuting. NET Core的ActionFilterAttribute

For further instructions on how to use this see: Async OnActionExecuting in ASP.NET Core's ActionFilterAttribute

这篇关于自定义操作过滤器中有待处理的异步任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆