2009-02-19 26 views
13

私はユーザーがファイルをアップロードできるようにするaspxページを持っており、最大ファイルサイズを10MBに制限したいと考えています。 IIS7、.NET 3.5。私はIHttpModuleを実装するカスタムエラー処理モジュールを持っているmaxAllowedContentLengthを捕まえて処理する場所は、IIS7で超過していますか?

<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> 

:私は私のweb.configファイルに次のように設定しています。私は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

sunflowerpowerの回答は、管理パイプラインモードがIntegratedに設定されている場合にのみ有効です。少なくともそれが私が経験した理由です – Marvin

+0

私はこのソリューションが認証を適切に処理しないことに気付いています。 Server.Transferを呼び出すと、HttpContext.Current.UserプロパティがNULLであるため、ターゲットページの認証チェックルーチンが失敗します。その行を引き出すことで問題が発生するため、ヘッダーをクリアすることによって発生したようには見えません。これを回避する方法はありますか?そうでなければ解決策ではありません。 – Triynko

+0

イベントハンドラに@Triynkoのエラーコードを入れます。私はUmbracoを使用しています - それが重要であるかどうかはわかりませんが、これは「Maximum request length exceeded」例外をまだ捕まえていた唯一の場所です。私はまた、 'Response.ClearContent();' YSODを取り除く。 'Application_Error'はこの例外では発生しませんが(RequestValidationの場合も同じですが)、UserControlまたはMasterpageで 'OnError'を起動できませんでした。実際のページを見つけることができませんでした。 ;) –

3

最も簡単な方法は、ページ自体のOnErrorメソッドで処理することです。

.NET 4.0ではWebEventCodeプロパティがNEWとしてドキュメント化されているため、これは.NET 4.0でのみ機能すると思います。私が何をしたか

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)。
  • エラー
  • として要求Server.Transferを(Context.Request.Url.LocalPath)
  • バックページ自体にページのOnLoadメソッドチェックを要求を転送フラグをContext.Itemsコレクションに付加価値をエラーフラグが存在する場合はメッセージを表示します。

これにより、エラーが要求されたページで完全に処理され、エラーを報告することができます。

ブラウザは最終的に適切な応答を受信しますが、ブラウザーはサーバーの応答を処理して表示する前に要求全体をアップロードする時間がかかることにも注意してください。この動作は、おそらくHTTPプロトコルのサーバーとブラウザとのやりとりの一部として定義されていると思われますので、それについては多分そうではありません。

+0

時にはコード '0'を返します。 –

+0

私はチェックのためにこれを使用... http://stackoverflow.com/a/665591/221683 –

関連する問題