FormsAuthentication.SetAuthCookie бросает исключение NullReferenceException в асинхронном действии

Я нахожу, что FormsAuthentication.SetAuthCookie бросает ссылку NullReferenceException - Object, не установленную на экземпляр объекта внутри асинхронного действия на лазурном веб-сайте.

Я нашел следующее:

http://connect.microsoft.com/VisualStudio/feedback/details/743350/formsauthentication-setauthcookie-throws-nullreferenceexception-if-called-in-an-async-action-in-mvc4

Однако у меня уже есть

 <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

и мой код работает нормально локально. Я испытываю только проблему при развертывании на лазурь. Я использую веб-сайты Azure (https://www.windowsazure.com/en-us/home/scenarios/web-sites/), я понял, что это обычно использует web.config? Я также попытался добавить appsetting через панель управления Azure

enter image description here

И добавив .ConfigureAwait(false); к моему ожидаемому методу, но не повезло.

Следующий код генерирует исключение

public class TestController : Controller
    {
        public async Task<ActionResult> Index()
        {
            var httpResponse = await new HttpClient().GetAsync("http://www.google.com");
            FormsAuthentication.SetAuthCookie("test", true);
            return View();
        }
    }

Кто-нибудь знает, как я могу заставить это работать?

ОБНОВЛЕНИЕ:

Трассировка стека:

[NullReferenceException: Object reference not set to an instance of an object.]
   System.Threading.Tasks.<>c__DisplayClass1c.<GetRethrowWithNoStackLossDelegate>b__1b(Task task) +91
   System.Threading.Tasks.TaskHelpersExtensions.ThrowIfFaulted(Task task) +15
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +77
   System.Web.Mvc.Async.<>c__DisplayClass3f.<BeginInvokeAsynchronousActionMethod>b__3e(IAsyncResult asyncResult) +16
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +59
   System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +240
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +12
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +31
   System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +23
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +128
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +26
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +14
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +25
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +41
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +25
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +28
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__4(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +25
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +31
   System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +23
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +59
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +96

UPDATE

Я нашел, что это работает, если вручную настроить Cookie

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "test", DateTime.Now, DateTime.Now.AddMinutes(30), true, null, FormsAuthentication.FormsCookiePath);
            string encTicket = FormsAuthentication.Encrypt(ticket);
            Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

Я не буду отвечать на вопрос, хотя хотел бы знать, почему FormsAuthentication.SetAuthCookie выбрасывает исключение и почему он ведет себя по-разному на сайтах Azure

Ответ 1

Эта проблема не является специфичной для Azure - метод FormsAuthentication.SetAuthCookie будет генерировать исключение нулевой ссылки в асинхронном действии, когда оператор ожидания вызывается до появления FormsAuthentication.SetAuthCookie.

Самое простое решение - использовать следующее:

        Response.Cookies.Add(FormsAuthentication.GetAuthCookie("user-1", true));

Альтернативой будет указание самого создания билета:

        var ticket = new FormsAuthenticationTicket(
            2,
            "user-1",
            DateTime.Now,
            DateTime.Now.AddDays(2),
            true,
            String.Empty,
            "/");

        var encTicket = FormsAuthentication.Encrypt(ticket);

        Response.Cookies.Add(new HttpCookie(".AUTH", encTicket));

Ответ 2

В настоящее время .NET 4.5 не поддерживается на веб-сайтах Windows Azure. Вам нужно будет понизить ваш проект до .NET 4.0, что также означает, что вам нужно будет переписать код, чтобы не использовать async.

Вы можете попытаться развернуть сборки .NET 4.5, необходимые вашему приложению