async action filter: Async & AuthorizeAttribute in ASP.NET WEB API
Asked Answered
R

2

24

I have my authentication logic in a class, derived from System.Web.Http.AuthorizeAttribute (overridden OnAuthorization method). I make a call to a DB from that method and I want that call to be asynchronous (luckily, the new ADO.NET async API allows that).

Then I apply this attribute to a controller to have all calls to it go thru the authentication filter. So far so good.

But doing so I run into the following problem. The framework (ASP.NET Web API) doesn't seem to be aware of what my intentions are :) It looks like it proceeds with the controller's action execution before my filter's OnAuthorizaion methods finishes (returns from the async call).. Hence the exception from the framework a la "request processing finished before all the outstanding async operations are complete.."

Is there any out-of-the-box way to deal with that?

P.S. My gut feeling says that I'm in for a custom action filter creation.. Then I'll need to override ExecuteActionFilterAsync and do my authentication there handling all the Task-related stuff myself with no help from the framework side.. )

Rondure answered 19/10, 2012 at 17:3 Comment(1)
All filter interfaces, which the Framework gives you, are asynchrony-aware. I assume you are working with default implementations of those which expos synchronous APIs. work with IAuthorizationFilter as suggested on the below answer.Aultman
C
59

Use IAsyncAuthorizationFilter and implement the interface asynchronously.

public async Task OnAuthorizationAsync(AuthorizationFilterContext actionContext)

Cadelle answered 18/10, 2018 at 18:26 Comment(1)
I believe this is for .NET Core only. Since the OP mentions System.Web.Http.AuthorizeAttribute I guess he's talking about Web API or MVC.Longcloth
R
8

Ok, here is what I came up with (after taking a peek under the hood with reflector):

public class SecurityFilterAttribute : FilterAttribute, IAuthorizationFilter
{
    public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
    { 
        await OnAuthentication(actionContext);

        return actionContext.Response ?? await continuation();
    }

    private async Task OnAuthentication(HttpActionContext actionContext)
    {
         //some lengthy I/O operations (XXXAsync/await)
    }
}

This way, being applied to a controller/action, all the logic will be executed in proper order while keeping the thread unblocked during I/O. Not very respectful to cancellation, though. But should be okay for my purposes..

Anyway, I really wonder what made Web API creators not to go similar way... Ideas?

Rondure answered 19/10, 2012 at 21:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.