Asp.net
發送 HTTP 標頭後伺服器無法設置狀態 - web api CORS
好吧好吧,我一直在為這個而頭疼……
設置:
- 我有一個設置了基本身份驗證的 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> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Headers" value="accept, authorization, origin, content-type" /> <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> </customHeaders> </httpProtocol> <handlers> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="OPTIONSVerbHandler" /> <remove name="TRACEVerbHandler" /> <remove name="WebDAV"/> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> <!-- END: Enable CORS -->到目前為止我的想法
該錯誤不是“FatalError”並且程序仍然會觸發,因為預檢請求不會影響我所知道的任何事情 - 那麼可以忽略錯誤嗎?嗯,不!這是一個錯誤!
現在 - 根據我所做的研究,這似乎是一個 IIS 洩漏到我的應用程序中的東西,我可以通過配置停止 - 但是如何?
如果不是這樣,那到底是什麼原因造成的?它來自哪裡?我該如何解決?不知道…
所以我依靠 Stack Overflow 上的書呆子們的英勇智慧……
幫助!!!!!!!
在
Response.End();_Response.Flush();所以你應該對預檢請求有一個空的響應。
至少這為我解決了這個問題。