2009-02-19 23 views
13

我有一個aspx頁面,允許用戶上傳文件,並且我想限制最大文件上傳大小爲10MB。 IIS7,.NET 3.5。我有以下的在我的web.config文件中配置:我在哪裏可以捕獲並處理IIS7中超出的maxAllowedContentLength?

<location path="foo.aspx"> 
    <system.web> 
     <!-- maxRequestLength: kbytes, executionTimeout:seconds --> 
     <httpRuntime maxRequestLength="10240" executionTimeout="120" /> 
     <authorization> 
      <allow roles="customRole"/> 
      <!-- Deny everyone else --> 
      <deny users="*"/> 
     </authorization> 
    </system.web> 
    <system.webServer> 
     <security> 
      <requestFiltering> 
       <!-- maxAllowedContentLength: bytes --> 
       <requestLimits maxAllowedContentLength="10240000"/> 
      </requestFiltering> 
     </security> 
     <handlers accessPolicy="Read, Script"> 
      <add name="foo" path="foo.aspx" verb="POST" 
       type="System.Web.UI.PageHandlerFactory" 
       preCondition="integratedMode" /> 
     </handlers>  
    </system.webServer> 
</location> 

我有一個自定義錯誤處理,實現IHttpModule模塊。我發現當超過maxRequestLength時,HttpApplication.Error確實得到提升。但是,當我玩maxAllowedContentLength時,HttpApplication.Error事件沒有被引發,用戶被重定向到404.13頁面。我附加了Visual Studio,第一次機會異常處於開啓狀態,沒有任何內容被拋出。

我的第一個想法是在早期事件中檢查標題內容的長度 - 是否有建議/最佳做法,我在哪裏做這件事? PostLogRequest? EndRequest?

回答

14

在看了ASP.NET Application Life Cycle Overview for IIS 7.0並做了我自己的實驗之後,我假設請求驗證在引發任何事件之前由IIS內部完成。

看起來好像只有LogRequest,PostLogRequest,EndRequest,PreSendRequestContent和PreSendRequestHeaders在內部驗證後引發此錯誤。

我決定在我的自定義錯誤處理程序中附加一個事件處理程序給HttpApplication.EndRequest事件,並檢查POST上的404.13狀態碼並處理,因爲我需要處理它,在我的情況下是重定向到呼叫頁面將檢查Server.GetLastError()並向最終用戶顯示友好的錯誤。

private void application_EndRequest(object sender, EventArgs e) 
{ 
    HttpRequest request = HttpContext.Current.Request; 
    HttpResponse response = HttpContext.Current.Response; 

    if ((request.HttpMethod == "POST") && 
     (response.StatusCode == 404 && response.SubStatusCode == 13)) 
    { 
     // Clear the response header but do not clear errors and 
     // transfer back to requesting page to handle error 
     response.ClearHeaders(); 
     HttpContext.Current.Server.Transfer(
      request.AppRelativeCurrentExecutionFilePath); 
    } 
} 

我很歡迎有關這種方法和替代方法的反饋意見。

+0

請注意,如果託管管道模式設置爲Integrated,sunflowerpower的答案纔有效。至少這就是我經歷過的原因 – Marvin 2010-10-27 12:34:50

+0

我注意到這個解決方案無法正確處理身份驗證。當我調用Server.Transfer時,目標頁面的身份驗證例程失敗,因爲HttpContext.Current.User屬性爲NULL。它似乎不是由清除標題引起的,因爲刪除該行仍然會導致問題。有沒有辦法解決?否則這不是一個解決方案。 – Triynko 2011-04-14 22:00:54

3

最簡單的方法是在頁面本身的OnError方法中處理它。

我認爲這隻適用於.NET 4.0,因爲WebEventCode屬性在.NET 4.0中記錄爲NEW。

protected override void OnError(EventArgs e) 
{ 
    Exception err = Server.GetLastError(); 
    if (err is HttpException) 
    { 
     if ((err as HttpException).WebEventCode == 3004) 
     { 
      Context.Items["error"] = "File exceeded maximum allowed length."; 
      Server.Transfer(Context.Request.Url.LocalPath); 
      return; 
     } 
    } 
    base.OnError(e); 
} 

protected override void OnLoad(EventArgs e) 
{ 
    base.OnLoad(e); 
    if (!IsPostBack) 
    { 
     string error = Context.Items["error"] as string; 
     if (!string.IsNullOrEmpty(error)) 
      showErrorMessage(error); 
    } 
} 

我所做的是:

  • 獲得最後的錯誤與Server.GetLastError
  • 檢查,這是一個 「超過最大請求長度。」錯誤(WebEventCode == 3004)。
  • 加入一個值Context.Items集合來標記該請求作爲錯誤
  • 轉移請求回到頁本身具有的Server.Transfer(Context.Request.Url.LocalPath)
  • 頁面的OnLoad方法檢查爲錯誤標誌並顯示一條消息(如果存在)

這確保錯誤完全在請求的頁面上處理,並且頁面能夠報告錯誤。

另請注意,雖然瀏覽器最終會收到適當的響應,但瀏覽器在處理服務器響應並顯示它之前可能需要上載整個請求。這種行爲可能被定義爲HTTP協議中服務器/瀏覽器交互的一部分,因此可能不會做太多的工作。

相關問題