是否可以在 MVC 4 AuthorizeAttribute 中使用异步/等待?

Posted

技术标签:

【中文标题】是否可以在 MVC 4 AuthorizeAttribute 中使用异步/等待?【英文标题】:Is it possible to use async/await in MVC 4 AuthorizeAttribute? 【发布时间】:2014-07-04 13:41:47 【问题描述】:

我在 MVC 的 AuthorizeAttribute 上看到的唯一覆盖是 public override void OnAuthorization( AuthorizationContext filterContext ),它不适合与 async/await 一起使用,因为它不返回 Task。是否有另一种方法可以在 MVC 中创建允许使用 async/await 的 AuthorizeAttribute

【问题讨论】:

您始终可以创建自己的属性。为什么你甚至需要它? 我支持 Santhos 的问题。为什么需要它? 我对您打算如何使用此异步属性感到有些困惑。 OnAuthorization 在管道处理期间由框架调用。它不是由您自己的代码调用的。那么这到底该怎么称呼呢? Stijn,就像 Stephen 所说的,我们在 MVC vNext 中实现了这些功能。 在我的授权检查通过后,我需要它能够向另一个服务发出异步 WebRequest 以回填一些用户信息。 【参考方案1】:

今天的 ASP.NET MVC 不支持异步过滤器。 Please vote.

不过,本周在 TechEd 上宣布的 ASP.NET "vNext" 将支持 MVC 的异步过滤器。

【讨论】:

有没有一种安全的方法来调用异步方法并等待它完成?我知道调用 Wait() 会出现死锁问题。 没有。 Wait/Result会导致死锁;当 ASP.NET 类型假定 ASP.NET 同步上下文时,嵌套消息循环可能会失败;推送到后台线程并等待会丢失请求上下文。今天没有好的解决方案;最干净的解决方案是使用同步 API。 :( 如果您必须在过滤器中使用异步 API,您只需找到一种适用于您的特定代码的解决方案。【参考方案2】:

随着 asp.net core 的发布,Stephen Cleary 的回答是正确的,如果您正在运行最新的 asp.net core,这是理想的选择。

对于尚未更新的用户,我可以使用异步 HttpModule 解决我的问题,该模块通过 HttpContext.Items 将状态传递到 AuthorizationFilter。我在这里添加了有关我的解决方案的更多详细信息 - http://evandontje.com/2017/08/15/solutions-for-async-await-in-mvc-action-filters/

【讨论】:

【参考方案3】:

对于那些还没有享受到使用 .net core 的乐趣的人,但是您可以使用 ASP.NET Web API 2 中的这种方法:

OnAuthorizationAsync 覆盖:

public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellation)

例如,您可以像这样调用 async webapi 服务:

 public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellation)
    
        await base.OnAuthorizationAsync(actionContext, cancellation);

        if (await IsUserAdminAsync()) /* call any async service */
            return;
        this.HandleUnauthorizedRequest(actionContext);
    

【讨论】:

以上是关于是否可以在 MVC 4 AuthorizeAttribute 中使用异步/等待?的主要内容,如果未能解决你的问题,请参考以下文章

MVC 4 - 在哪里保留业务逻辑

MVC 4,复选框列表和我

在 ASP.NET MVC 4 中开发大型项目是不是合理?

.NET 4 MVC 2 验证,带有注释警告而不是错误

MVC 4 Web API 发布

Play 2.4.x 中是不是有一个方便的助手可以从 play.api.mvc.Request.queryString 构建一个 uri