Diego Mijelshon
Diego Mijelshon

Reputation: 52745

Testing async web api methods with custom authorization

I have a WebApi method looking more or less like this:

public async Task<HttpResponseMessage> Get(Guid id)
{
    var foo = await Store.GetFooAsync(id);
    if (foo.BelongsTo != User.Identity.Name)
        throw new HttpResponseException(HttpStatusCode.Forbidden);
    //return foo here
}

This seems to work fine in the actual application, where a custom IHttpModule sets the principal in both HttpContext.User and Thread.CurrentPrincipal.

However, when calling from a unit test:

Thread.CurrentPrincipal = principal;
var response = controller.Get(id).Result;

User is reset after await (i.e. on the continuation), so the test fails. This happens when running under R#8, and it wasn't happening with R#7.

My workaround was to save the current principal before the first await, but it's just a hack to satisfy the test runner needs.

How can I call my controller method and make sure continuations have the same principal as the original call?

Upvotes: 4

Views: 920

Answers (2)

Diego Mijelshon
Diego Mijelshon

Reputation: 52745

I fixed this by upgrading the MVC packages. The new version keeps the principal in ApiController.RequestContext.Principal, separate from Thread.CurrentPrincipal, avoiding the problem completely.

My new test code starts with:

controller.RequestContext.Principal = principal;

Upvotes: 1

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131180

The short version is, use HttpContext.Current.Use instead of Thread.Principal.

The short version is, use Request.LogonUserIdentity or Request.RequestContext.HttpContext.User.

async/await preserves the original request context, not the thread that started the method. This makes senses, otherwise ASP.NET would have to freeze the thread and have it available for when await returns. The thread you run after await is a thread from the ThreadPool, so modifying its CurrentPrincipal is a very bad idea.

Check the transcript from Scott Hanselman's podcast "Everything .NET programmers know about Asynchronous Programming is wrong" for more.

Upvotes: 0

Related Questions