Пользовательские страницы ошибок на asp.net MVC3 - PullRequest
144 голосов
/ 08 марта 2011

Я занимаюсь разработкой базового веб-сайта MVC3 и ищу решение для обработки ошибок и визуализации пользовательских представлений для каждого вида ошибок.Итак, представьте, что у меня есть контроллер «Ошибка», в котором его основное действие - «Индекс» (общая страница ошибок), и этот контроллер будет иметь еще пару действий для ошибок, которые могут отображаться пользователю, например «Handle500» или «HandleActionNotFound».

Таким образом, каждая ошибка, которая может произойти на веб-сайте, может обрабатываться этим контроллером «Ошибка» (примеры: «Контроллер» или «Действие» не найдены, 500, 404, dbException и т. Д.).

Я использую файл Sitemap для определения путей веб-сайтов (а не маршрутов).

На этот вопрос уже был дан ответ, это ответ на Gweebz

Мой последний applicationaiton_errorМетод заключается в следующем:

protected void Application_Error() {
//while my project is running in debug mode
if (HttpContext.Current.IsDebuggingEnabled && WebConfigurationManager.AppSettings["EnableCustomErrorPage"].Equals("false"))
{
    Log.Logger.Error("unhandled exception: ", Server.GetLastError());
}
else
{
    try
    {
        var exception = Server.GetLastError();

        Log.Logger.Error("unhandled exception: ", exception);

        Response.Clear();
        Server.ClearError();
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "General";
        routeData.Values["exception"] = exception;

        IController errorsController = new ErrorsController();
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        errorsController.Execute(rc);
    }
    catch (Exception e)
    {
        //if Error controller failed for same reason, we will display static HTML error page
        Log.Logger.Fatal("failed to display error page, fallback to HTML error: ", e);
        Response.TransmitFile("~/error.html");
    }
}
}

Ответы [ 6 ]

201 голосов
/ 08 марта 2011

Вот пример того, как я обрабатываю пользовательские ошибки.Я определяю ErrorsController с действиями, обрабатывающими разные ошибки HTTP:

public class ErrorsController : Controller
{
    public ActionResult General(Exception exception)
    {
        return Content("General failure", "text/plain");
    }

    public ActionResult Http404()
    {
        return Content("Not found", "text/plain");
    }

    public ActionResult Http403()
    {
        return Content("Forbidden", "text/plain");
    }
}

, а затем я подписываюсь на Application_Error in Global.asax и вызываю этот контроллер:

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);
}
18 голосов
/ 29 ноября 2011

Вот еще статьи Как создать пользовательские страницы ошибок с MVC http://kitsula.com/Article/MVC-Custom-Error-Pages.

6 голосов
/ 09 января 2013

Вы также можете сделать это в файле Web.Config. Вот пример, который работает в IIS 7.5.

     <system.webServer>
          <httpErrors errorMode="DetailedLocalOnly" defaultResponseMode="File">
                <remove statusCode="502" subStatusCode="-1" />
                <remove statusCode="501" subStatusCode="-1" />
                <remove statusCode="412" subStatusCode="-1" />
                <remove statusCode="406" subStatusCode="-1" />
                <remove statusCode="405" subStatusCode="-1" />
                <remove statusCode="404" subStatusCode="-1" />
                <remove statusCode="403" subStatusCode="-1" />
                <remove statusCode="401" subStatusCode="-1" />
                <remove statusCode="500" subStatusCode="-1" />
                <error statusCode="500" path="/notfound.html" responseMode="ExecuteURL" />
                <error statusCode="401" prefixLanguageFilePath="" path="/500.html" responseMode="ExecuteURL" />
                <error statusCode="403" prefixLanguageFilePath="" path="/403.html" responseMode="ExecuteURL" />
                <error statusCode="404" prefixLanguageFilePath="" path="/404.html" responseMode="ExecuteURL" />
                <error statusCode="405" prefixLanguageFilePath="" path="/405.html" responseMode="ExecuteURL" />
                <error statusCode="406" prefixLanguageFilePath="" path="/406.html" responseMode="ExecuteURL" />
                <error statusCode="412" prefixLanguageFilePath="" path="/412.html" responseMode="ExecuteURL" />
                <error statusCode="501" prefixLanguageFilePath="" path="/501.html" responseMode="ExecuteURL" />
                <error statusCode="502" prefixLanguageFilePath="" path="/genericerror.html" responseMode="ExecuteURL" />
           </httpErrors>
</system.webServer>
3 голосов
/ 16 февраля 2013

Я вижу, вы добавили значение конфигурации для EnableCustomErrorPage, и вы также проверяете IsDebuggingEnabled, чтобы определить, следует ли запускать обработку ошибок.

Поскольку уже есть <customErrors/>Конфигурация в ASP.NET (предназначенная именно для этой цели) проще всего сказать:

    protected void Application_Error()
    {
        if (HttpContext.Current == null) 
        {
                // errors in Application_Start will end up here                
        }
        else if (HttpContext.Current.IsCustomErrorEnabled)
        {
                // custom exception handling
        }
    }

Затем в конфигурации вы должны указать <customErrors mode="RemoteOnly" />, который безопасен для развертывания подобным образом.и когда вам нужно протестировать свою пользовательскую страницу ошибки, вы должны установить ее на <customErrors mode="On" />, чтобы вы могли убедиться, что она работает.

Обратите внимание, что вам также необходимо проверить, является ли HttpContext.Current нулевым, поскольку исключениеApplication_Start по-прежнему будет использовать этот метод, хотя активного контекста не будет.

2 голосов
/ 23 апреля 2012

Вы можете отобразить удобную страницу ошибок с правильным кодом статуса http, внедрив Джефф Этвуд * Дружественный для пользователя модуль обработки исключений с небольшим изменением кода статуса http.Работает без перенаправлений.Хотя код 2004 года (!), Он хорошо работает с MVC.Он может быть полностью настроен в вашем файле web.config без каких-либо изменений исходного кода проекта MVC.

Модификация, необходимая для возврата исходного статуса HTTP, а не статуса 200, описана в этом связанном сообщении на форуме .

По сути, в Handler.vb выможно добавить что-то вроде:

' In the header...
Private _exHttpEx As HttpException = Nothing

' At the top of Public Sub HandleException(ByVal ex As Exception)...
HttpContext.Current.Response.StatusCode = 500
If TypeOf ex Is HttpException Then
    _exHttpEx = CType(ex, HttpException)
    HttpContext.Current.Response.StatusCode = _exHttpEx.GetHttpCode()
End If
0 голосов
/ 31 октября 2013

Я использую MVC 4.5, и у меня были проблемы с решением Дарина. Примечание: решение Дарина превосходно, и я использовал его, чтобы придумать свое решение. Вот мое модифицированное решение:

protected void Application_Error(object sender, EventArgs e)
{           
var exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.StatusCode = httpException.GetHttpCode();

Response.Clear();
Server.ClearError();


if (httpException != null)
{
    var httpContext = HttpContext.Current;

    httpContext.RewritePath("/Errors/InternalError", false);

    // MVC 3 running on IIS 7+
    if (HttpRuntime.UsingIntegratedPipeline)
    {
        switch (Response.StatusCode)
        {
            case 403:
                httpContext.Server.TransferRequest("/Errors/Http403", true);
                break;
            case 404:
                httpContext.Server.TransferRequest("/Errors/Http404", true);
                break;
            default:
                httpContext.Server.TransferRequest("/Errors/InternalError", true);
                break;
        }
    }
    else
    {
        switch (Response.StatusCode)
        {
            case 403:
                httpContext.RewritePath(string.Format("/Errors/Http403", true));
                break;
            case 404:
                httpContext.RewritePath(string.Format("/Errors/Http404", true));
                break;
            default:
                httpContext.RewritePath(string.Format("/Errors/InternalError", true));
                break;
        }

        IHttpHandler httpHandler = new MvcHttpHandler();
        httpHandler.ProcessRequest(httpContext);
    }
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...