Własne strony błędów na asp.net MVC3

Rozwijam stronę bazową MVC3 i szukam rozwiązania do obsługi błędów i renderowania niestandardowych widoków dla każdego rodzaju błędu. Wyobraź sobie więc, że mam Kontroler "Error", w którym jego główną akcją jest "Index" (generic error page), a ten kontroler będzie miał jeszcze kilka akcji dla błędów, które mogą pojawić się użytkownikowi, takich jak" Handle500 "lub"HandleActionNotFound".

Więc każdy błąd, który może wystąpić na stronie internetowej, może być obsługiwany przez ten kontroler "błędów" (przykłady: "Controller "lub" Action " not found, 500, 404, dbException, etc).

Używam pliku Sitemap do definiowania ścieżek witryny (a nie trasy).

To pytanie zostało już udzielone, to jest odpowiedź na Gweebz

Moja ostateczna metoda applicaiton_error jest następująca:

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");
    }
}
}
Author: Chris, 2011-03-08

6 answers

Oto przykład, jak radzę sobie z niestandardowymi błędami. Definiuję ErrorsController z działaniami obsługującymi różne błędy 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");
    }
}

A potem subskrybuję Application_Error w Global.asax i wywołuję ten kontroler:

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);
}
 201
Author: Darin Dimitrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-28 19:34:38

Oto więcej artykułów jak tworzyć własne strony błędów za pomocą MVC http://kitsula.com/Article/MVC-Custom-Error-Pages .

 18
Author: Shaman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-29 03:05:50

Można to również zrobić w Internecie.Plik Konfiguracyjny. Oto przykład, który działa w 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>
 6
Author: Brett Allred,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-09 14:18:54

Widzę, że dodałeś wartość konfiguracyjną dla EnableCustomErrorPage i sprawdzasz również IsDebuggingEnabled, aby określić, czy uruchomić obsługę błędów.

Ponieważ jest już <customErrors/> konfiguracja w ASP.NET (co jest przeznaczone dokładnie do tego celu) najłatwiej jest powiedzieć:

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

Następnie w konfiguracji umieścisz <customErrors mode="RemoteOnly" />, która jest Bezpieczna do wdrożenia w ten sposób, a kiedy musisz przetestować swoją niestandardową stronę błędu, ustawisz ją na <customErrors mode="On" />, abyś mógł sprawdzić, czy działa.

Zauważ także trzeba sprawdzić, czy HttpContext.Current jest null, ponieważ wyjątek w {[7] } nadal będzie jego tą metodą, chociaż nie będzie aktywnego kontekstu.

 3
Author: Simon_Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-16 04:57:45

Możesz wyświetlić przyjazną dla użytkownika stronę błędu z prawidłowym kodem statusu http, implementując Przyjazny dla użytkownika moduł obsługi wyjątków Jeffa Atwooda z niewielką modyfikacją kodu statusu http. Działa bez żadnych przekierowań. Chociaż kod pochodzi z 2004 roku(!), działa dobrze z MVC. Można go skonfigurować w całości w sieci.config, bez żadnych zmian kodu źródłowego projektu MVC.

Modyfikacja wymagała zwrócenia oryginalnego statusu HTTP, a nie 200 status jest opisany w ten powiązany post na forum .

/ Align = "left" / vb, możesz dodać coś w stylu:
' 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
 2
Author: Martin_ATS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-23 19:48:53

Używam MVC 4.5 i miałem problemy z rozwiązaniem Darina. Uwaga: rozwiązanie Darina jest doskonałe i użyłem go, aby wymyślić moje rozwiązanie. Oto moje zmodyfikowane rozwiązanie:

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);
    }
}
}
 0
Author: MVCdragon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-31 02:33:49