web-dev-qa-db-ja.com

HttpExceptionをスローすると、常にHTTP 500エラーが返されますか?

クライアントにHTTP403エラーコードを返そうとしています。 HttpExceptionがこれを達成するための最もクリーンな方法であることを読みましたが、それは私にとってはうまくいきません。次のようなページ内から例外をスローします。

throw new HttpException(403,"You must be logged in to access this resource.");

ただし、これは、CustomErrorsがオフの場合にのみ、標準のASP.Netスタックトレース(500エラーあり)を提供します。 CustomErrorsがオンの場合、403エラーが発生したときに表示されるように設定したページにリダイレクトされません。 HttpExceptionを忘れて、代わりにすべてのHTTPコードを自分で設定する必要がありますか?これを修正するにはどうすればよいですか?

私のWeb.Configのカスタムエラー部分は次のとおりです。

<customErrors mode="On" defaultRedirect="GenericErrorPage.html">
      <error statusCode="403" redirect="Forbidden.html" />
</customErrors>

Forbidden.htmlを取得する代わりに、GenericErrorPage.htmlを取得します

14
Earlz

私は実際にこの問題を解決するために自分の気の利いた小さなクラスを作ることになりました。すべてを処理できるわけではなく、MVCでうまく機能するかどうかはわかりませんが、私の使用には使用できます。基本的に、ASP.Netに依存して正しいエラーページとエラーコードを出力する代わりに、エラーをクリアしてからサーバー側の転送を実行し、適切なWeb.Configエラーページを表示します。また、customErrorsモードを認識し、それに応じて反応します。

public static class CustomErrorsFixer
{
    static public void HandleErrors(HttpContext Context)
    {
        if(RunIt(Context)==false){
            return;
        }
        HttpException ex = Context.Error as HttpException;
        if(ex==null){
            try{
                ex=Context.Error.InnerException as HttpException;
            }catch{
                ex=null;
            }
        }

        if (ex != null){
            Context.Response.StatusCode = ex.GetHttpCode();
        }else{
            Context.Response.StatusCode = 500;
        }
        Context.ClearError();

        Context.Server.Transfer(GetCustomError(Context.Response.StatusCode.ToString()));
        HttpContext.Current.Response.End();
    }
    static protected string GetCustomError(string code)
    {
        CustomErrorsSection section = ConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection;

        if (section != null)
        {
            CustomError page = section.Errors[code];

            if (page != null)
            {
                return page.Redirect;
            }
        }
        return section.DefaultRedirect;
    }
    static protected bool RunIt(HttpContext context){
        CustomErrorsSection section = ConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection;
        switch(section.Mode){
            case CustomErrorsMode.Off:
                return false;
            case CustomErrorsMode.On:
                return true;
            case CustomErrorsMode.RemoteOnly:
                return !(context.Request.UserHostAddress=="127.0.0.1");
            default:
                return true;
        }
    }

}

そしてそれをアクティブにするには、Global.asaxに小さなものを追加するだけです

    protected virtual void Application_Error (Object sender, EventArgs e)
    {
        CustomErrorsFixer.HandleErrors(Context);
    }
1
Earlz

次のようなアプリケーションエラーを上書きする必要があります。

    protected void Application_Error()
    {
        var exception = Server.GetLastError();
        var httpException = exception as HttpException;
        Response.Clear();
        Server.ClearError();

        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "General";
        routeData.Values["exception"] = exception;
        Response.StatusCode = 500;

        if (httpException != null)
        {
            Response.StatusCode = httpException.GetHttpCode();
            switch (Response.StatusCode)
            {
                case 403:
                    routeData.Values["action"] = "Http403";
                    break;
                case 404:
                    routeData.Values["action"] = "Http404";
                    break;
            }
        }

        IController errorsController = new ErrorsController();
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        errorsController.Execute(rc);
    }

次に、errorsControllerを追加する必要があります。

public class ErrorsController : Controller
{
    public ActionResult General(Exception exception)
    {
        ViewBag.ErrorCode = Response.StatusCode;
        ViewBag.Message = "Error Happened";

        //you should log your exception here

        return View("Index");
    }

    public ActionResult Http404()
    {
        ViewBag.ErrorCode = Response.StatusCode;
        ViewBag.Message = "Not Found";
        return View("Index");
    }

    public ActionResult Http403()
    {
        ViewBag.Message = Response.StatusCode;
        ViewBag.Message = "Forbidden";
        return View("Index");
    }

}

最後に、errorsControllerのビューを作成します。 Views/Errors /にindexというビューを1つだけ作成しました。

これがお役に立てば幸いです。

よろしく!

6
OscarVGG

このコードがWeb.configファイルの要素configuration/system.webに含まれている場合:

  <customErrors mode="On">
    <error statusCode="403" redirect="~/errors/Forbidden.aspx"/>
  </customErrors>

期待通りに動作しました。

ここで例を含む優れたチュートリアルを見つけることができます(例3が正しいものです): http://aspnetresources.com/articles/CustomErrorPages

または、Response.Statusを使用してこれを行うこともできます: Asp Classicは特定のhttpステータスコードを返します

3
Binus