【发布时间】:2017-06-03 01:37:49
【问题描述】:
我需要你的帮助!我已经有一段时间了,但我一直无法弄清楚。假设我们有以下控制器:
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 覆盖定义为(删除所有检查以尽可能减少):
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:异步模块或处理程序已完成,而异步操作仍处于挂起状态。]
如果我尝试(在错误之后)相同的请求(即通知用户),它会像重定向或发送通知一样工作。
根据this post,我可能会在异步任务完成之前完成请求(如果我理解得很好),但我一直在使用的所有任务都是awaited 所以我不知道这个在哪里错误可能来自。希望您能够帮助我。提前致谢!
【问题讨论】:
-
由于您实现了Fire and forget 模式,因此行为是预期的......现在您实际上期望这段代码会做什么?
-
@AlexeiLevenkov hmmm 那么我应该在
NotifyUser操作中执行task.Wait()吗?我在属性中尝试过,但没有运气。 -
不行。当它死锁时,请务必阅读stackoverflow.com/questions/13140523/…。感觉就像您希望操作过滤器支持异步操作,但事实并非如此(视图也是如此)......我认为如果没有重大的重新设计,您将无法取得任何进展,因为只有 ASP.Net MVC 中支持异步的顶级操作。跨度>
-
是的,根本问题是这个版本的 ASP.NET/MVC 在操作过滤器中的异步操作方面存在可悲的缺陷。 ASP.NET/WebApi 在这方面方式更好,但并不能真正帮助您。
-
另见我的article on async ASP.NET,我注意到这个错误通常是由于
async void(即async void OnActionExecuting),还有一个关于“当前异步支持状态”的部分。跨度>
标签: c# asp.net-mvc asynchronous