Код ниже был добавлен в недавно созданный проект 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).