Asp.net

發送 HTTP 標頭後伺服器無法設置狀態 - web api CORS

  • July 16, 2015

好吧好吧,我一直在為這個而頭疼……

設置:

  • 我有一個設置了基本身份驗證的 Web Api 2.0 項目。
  • 我在 web.config 中啟用了 CORS
  • 我有 ELMAH 記錄錯誤
  • 我有一個 DelegatingHandler 處理傳入的請求 - (下面的程式碼)
  • 我有一個非常具體的資料結構,所以我沒有使用 Microsoft 的 Membership 或 Identity。
  • 我正在刷新每個使用 OPTIONS 動詞的請求

問題:

我在每個經過身份驗證的請求上都收到以下錯誤:

System.Web.HttpException (0x80004005): Server cannot set status after HTTP headers have been sent.
  at System.Web.HttpResponse.set_StatusCode(Int32 value)
  at System.Web.HttpResponseWrapper.set_StatusCode(Int32 value)
  at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseStatusAndHeadersAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
  at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
  at System.Web.Http.WebHost.HttpControllerHandler.<ProcessRequestAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
  at System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar)
  at System.Web.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
  at System.Web.HttpApplication.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar)

到目前為止所做的調查:

上面列出的錯誤僅發生在 OPTIONS 動詞上。

該錯誤表明在要求設置其狀態程式碼之前已經發送了標頭。

僅出現 1 條錯誤記錄 - 在 elmah 中,“SendAsync”方法被命中兩次 - 一次用於 OPTIONS 飛行前,一次用於 GET 或 POST。這告訴我,這只發生在一個請求上——OPTIONS 請求。

為了通過飛行前,我使用這個:(global.asax)

protected void Application_BeginRequest()
{
 if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
   {
       Response.Flush();
   }
}

這會將響應傳遞給我的處理程序,但它也將 OPTIONS 動詞傳遞到此程式碼中,我認為它應該:

//Capture incoming request by overriding SendAsync method

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
   //validate credentials, set CurrentPrincipal and Current.User if valid
   if (ValidateCredentials(request.Headers.Authorization))
   {
       Thread.CurrentPrincipal = new MyPrincipal(_userName);
       HttpContext.Current.User = new MyPrincipal(_userName);
   }


   // Execute base.SendAsync to execute default actions
   // and once it is completed, capture the response object and add
   // WWW-Authenticate header if the request was marked as (401) unauthorized.

   return base.SendAsync(request, cancellationToken).ContinueWith(task =>
   {
       HttpResponseMessage response = task.Result;
       if (response.StatusCode == HttpStatusCode.Unauthorized && !response.Headers.Contains("WWW-Authenticate"))
       {
           response.Headers.Add("WWW-Authenticate", "Basic");
       }
       return response;
   });

}

現在在調試器中,我看到 OPTIONS 通過並觸發 405 - 不允許的方法,但是當它通過 elmah 時出現 500 錯誤 - 在發送 HTTP 標頭後伺服器無法設置狀態。

我沒有將 OPTIONS 放在我的任何控制器上,所以這可以解釋 405 - 但請求不應該那麼遠。

所以 - 這聽起來像一個配置的東西?使困惑。

我的cors配置是:

<!-- BEGIN: Enable CORS -->
<httpProtocol>
 &lt;customHeaders&gt;
   &lt;add name="Access-Control-Allow-Origin" value="*" /&gt;
   &lt;add name="Access-Control-Allow-Headers" value="accept, authorization, origin, content-type" /&gt;
   &lt;add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /&gt;
 &lt;/customHeaders&gt;
&lt;/httpProtocol&gt;

&lt;handlers&gt;
 &lt;remove name="ExtensionlessUrlHandler-Integrated-4.0" /&gt;
 &lt;remove name="OPTIONSVerbHandler" /&gt;
 &lt;remove name="TRACEVerbHandler" /&gt;
 &lt;remove name="WebDAV"/&gt;
 &lt;add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /&gt;
&lt;/handlers&gt;
&lt;!-- END: Enable CORS --&gt;

到目前為止我的想法

該錯誤不是“FatalError”並且程序仍然會觸發,因為預檢請求不會影響我所知道的任何事情 - 那麼可以忽略錯誤嗎?嗯,不!這是一個錯誤!

現在 - 根據我所做的研究,這似乎是一個 IIS 洩漏到我的應用程序中的東西,我可以通過配置停止 - 但是如何?

如果不是這樣,那到底是什麼原因造成的?它來自哪裡?我該如何解決?不知道…

所以我依靠 Stack Overflow 上的書呆子們的英勇智慧……

幫助!!!!!!!

Response.End();_Response.Flush();

所以你應該對預檢請求有一個空的響應。

至少這為我解決了這個問題。

引用自:https://stackoverflow.com/questions/29709477