Код ниже был добавлен в недавно созданный проект Visual Studio 2012.NET 4.5 WebAPI.
Я пытаюсь назначить как HttpContext.Current.User
, так и Thread.CurrentPrincipal
в асинхронном методе. Назначение Thread.CurrentPrincipal
выполняется некорректно, если не выполняется await Task.Yield();
(или что-то еще асинхронное) (передача true
в AuthenticateAsync()
приведет к успеху).
Почему это?
using System.Security.Principal;
using System.Threading.Tasks;
using System.Web.Http;
namespace ExampleWebApi.Controllers
{
public class ValuesController : ApiController
{
public async Task GetAsync()
{
await AuthenticateAsync(false);
if (!(User is MyPrincipal))
{
throw new System.Exception("User is incorrect type.");
}
}
private static async Task AuthenticateAsync(bool yield)
{
if (yield)
{
// Why is this required?
await Task.Yield();
}
var principal = new MyPrincipal();
System.Web.HttpContext.Current.User = principal;
System.Threading.Thread.CurrentPrincipal = principal;
}
class MyPrincipal : GenericPrincipal
{
public MyPrincipal()
: base(new GenericIdentity("<name>"), new string[] {})
{
}
}
}
}
Примечания:
-
await Task.Yield();
может отображаться в любом местеAuthenticateAsync()
или его можно переместить вGetAsync()
после вызоваAuthenticateAsync()
, и он все равно будет успешным. -
ApiController.User
возвращаетThread.CurrentPrincipal
. -
HttpContext.Current.User
всегда течет правильно, даже безawait Task.Yield()
. -
Web.config
включает<httpRuntime targetFramework="4.5"/>
который подразумеваетUseTaskFriendlySynchronizationContext
. - Я попросил аналогичный вопрос пару дней назад, но не понял, что этот пример только преуспел, потому что присутствовал
Task.Delay(1000)
.