我的WebApi方法或多或少看起来像这样:
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
}
这似乎在实际应用程序中正常工作,其中自定义IHttpModule
设置HttpContext.User
和Thread.CurrentPrincipal
中的主体。
但是,从单元测试中调用时:
Thread.CurrentPrincipal = principal;
var response = controller.Get(id).Result;
{p} User
在await
之后重置(即继续),因此测试失败。在R#8下运行时会发生这种情况,R#7没有发生这种情况。
我的解决方法是在第一次等待之前保存当前主体,但这只是满足测试运行者需求的黑客攻击。
如何调用我的控制器方法并确保continuation与原始调用具有相同的主体?
答案 0 :(得分:1)
我通过升级MVC包修复了这个问题。新版本将主体保留在ApiController.RequestContext.Principal
中,与Thread.CurrentPrincipal
分开,完全避免了问题。
我的新测试代码以:
开头controller.RequestContext.Principal = principal;
答案 1 :(得分:0)
简短版本是,使用HttpContext.Current.Use而不是Thread.Principal。
简短版本是,使用Request.LogonUserIdentity或Request.RequestContext。HttpContext.User。
async/await
保留原始请求上下文,而不是启动该方法的线程。这会产生感觉,否则ASP.NET必须冻结线程并在await
返回时使其可用。在await
之后运行的线程是来自ThreadPool的线程,因此修改其CurrentPrincipal是一个非常糟糕的主意。
查看Scott Hanselman的播客“transcript”中的Everything .NET programmers know about Asynchronous Programming is wrong了解详情。