Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.. )

like image 511
ay.metallo Avatar asked Oct 19 '12 17:10

ay.metallo


2 Answers

Use IAsyncAuthorizationFilter and implement the interface asynchronously.

public async Task OnAuthorizationAsync(AuthorizationFilterContext actionContext)

like image 61
Guo Huang Avatar answered Sep 22 '22 14:09

Guo Huang


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?

like image 37
ay.metallo Avatar answered Sep 20 '22 14:09

ay.metallo