Бросок исключения HttpException всегда возвращает ошибку HTTP 500? - PullRequest
14 голосов
/ 10 апреля 2011

Я пытаюсь сбросить код ошибки HTTP 403 обратно на клиент.Я читал, что HttpException - самый чистый способ сделать это, но он не работает для меня.Я выкидываю исключение изнутри страницы, подобной этой:

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

Однако, это даст только стандартную трассировку стека ASP.Net (с ошибкой 500), когда CustomErrors выключен.Если CustomErrors включен, то он не будет перенаправлен на страницу, которую я настроил, чтобы отображаться при возникновении ошибки 403.Должен ли я забыть о HttpException и вместо этого установить все коды HTTP самостоятельно?Как мне это исправить?

Пользовательская часть ошибок моего Web.Config:

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

Вместо того, чтобы получать Forbidden.html, я получу GenericErrorPage.html

Ответы [ 3 ]

6 голосов
/ 04 мая 2011

Вам необходимо переопределить ошибку приложения следующим образом:

    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);
    }

Затем вы должны добавить ошибки контроллера:

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");
    }

}

И последнее создайте представление для ошибок контроллера. Я создал только одно представление с именем index в Views / Errors /.

Надеюсь, это было полезно.

Привет!

3 голосов
/ 10 апреля 2011

С этим кодом, включенным в элемент configuration / system.web из Web.config файл:

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

Мне удалось, чтобы он работал как положено.

Вы можете найти хороший учебник с примерами (пример 3 - правильный) здесь: http://aspnetresources.com/articles/CustomErrorPages

Или вы можете использовать Response.Status для этого: Asp Classic возвращает определенный код статуса http

1 голос
/ 11 апреля 2011

Я на самом деле закончил создавать свой собственный маленький классный класс, чтобы решить эту проблему. Это не обрабатывает все, и я не уверен, что это хорошо работает с 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);
    }
...