我需要你的帮助!我已经研究这个问题有一段时间了,但一直无法弄清楚。假设我们有以下 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
中定义的属性像:
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/