ASP.NET 2.0: najlepsza praktyka pisania Strony błędów

W asp.net 2.0 strona internetowa, jaki jest najlepszy sposób pisania strony błędu. Widziałem następującą sekcję w następującej lokalizacji:

  • www.Config
    <customErrors mode="RemoteOnly" defaultRedirect="~/Pages/Common/DefaultRedirectErrorPage.aspx">
    

  • Globalny.asax
    void Application_Error(object sender, EventArgs e) 
    { 
    }
    

  • Nie rozumiem, jak używać obu z nich w najlepszy sposób do obsługi błędów.

    Proszę poprowadź mnie najlepiej.

    Author: BigBlondeViking, 2009-08-04

    2 answers

    W moim globalnym asax zawsze sprawdzam, jaki jest typ błędu http...

    Następnie przenieś do poprawnej strony błędu określonej w web.config Lubię obsługiwać zwykłych podejrzanych, 404 (utracona strona ) i 500 (błąd serwera)

    Niektóre tło w kodzie statusu http jest importaint, aby wiedzieć, dlaczego są obsługiwane:

    Http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

    Moja sieć.config wygląda mniej więcej tak
    <customErrors mode="On"  defaultRedirect="~/error.aspx"  >
      <error statusCode="404" redirect="~/lost.aspx"  />
      <error statusCode="500" redirect="~/error.aspx"  />
    </customErrors>
    

    Moja zagubiona strona ma logikę w aby spróbować znaleźć link do strony, której mogli szukać, a także inne formatowanie.

    Moja strona błędu jest nieco inna, pokazuje kilka komunikatów o błędach,

    Więc radzę sobie z obydwoma inaczej.

    W zależności od tego, czy masz zabezpieczone obszary swojej witryny, możesz chcieć obsłużyć 401/403 ?

    protected void Application_Error(object sender, EventArgs e)
    {
        var context = Context;
    
    
        var error = context.Server.GetLastError() as HttpException;
        var statusCode = error.GetHttpCode().ToString();
    
        // we can still use the web.config custom errors information to
        // decide whether to redirect
        var config = (CustomErrorsSection)WebConfigurationManager.GetSection("system.web/customErrors");
        if (config.Mode == CustomErrorsMode.On ||
            (config.Mode == CustomErrorsMode.RemoteOnly && context.Request.Url.Host != "localhost"))
        {
            // set the response status code
            context.Response.StatusCode = error.GetHttpCode();
    
            // Server.Transfer to correct ASPX file for error
            if (config.Errors[statusCode] != null)
            {
    
                HttpContext.Current.Server.Transfer(config.Errors[statusCode].Redirect);
            }
            else
                HttpContext.Current.Server.Transfer(config.DefaultRedirect);
        }
    }
    

    Powodem, dla którego przenoszę serwer, jest to, aby Wyszukiwarki nie pomyliły się i aby moje dzienniki webmastera były sensowne... jeśli przekierujesz, zwracasz http status 302, który mówi przeglądarce, aby przejść do strony przekierowanej... następnie ta Następna strona zwraca kod stanu 200 (ok ).

    302 --> 200 , albo nawet 302 -- > 404 ma inne znaczenie, że tylko 404...

    Następnie na stronie powiedz mój błąd 404 upewniam się, że ustawiam kod statusu błędu http:

    protected void Page_PreRender(object sender, EventArgs e)
    {
        Response.Status = "404 Lost";
        Response.StatusCode = 404;
    
    }
    

    Ten artykuł był dla mnie pomocny, wiedziałem, co chcę zrobić, ale podoba mi się, jak ten kod wygląda w sieci.ustawienia konfiguracji... http://helephant.com/2009/02/improving-the-way-aspnet-handles-404-requests/

    Return the right status code

    Domyślnie strona obsługująca 404 strona błędu nie zwraca statusu 404 kod do przeglądarki. Wyświetla komunikat o błędzie, który został dostarczony do użytkownik ale nie ma żadnych dodatkowych informacje o oznaczaniu strony jako strona błędu.

    To się nazywa miękka 404. Soft 404 strony nie są tak dobre jak te, które zwróć kod statusu 404, ponieważ zwracanie kodu stanu 404 pozwala wszystko dostęp do pliku, który strona jest stroną błędu, a nie prawdziwa strona twojej strony. Jest to głównie przydatne dla wyszukiwarek, ponieważ wtedy wiedzą, że powinni usuwać zmarłych stron z ich indeksu, dzięki czemu użytkownicy nie będą śledź martwe linki do swojej witryny z strony wyników.

    Strony zwracające 404 kody statusu są przydatne również do wykrywania błędów ponieważ będą one zapisane w Twoim serwer dzienniki więc jeśli masz nieoczekiwane 404 błędy, łatwo je znaleźć. Oto przykład błędu 404 raport w Google Webmaster tools:

    Edycje

    Czy wymagane jest napisanie serwer.clearerror () w trybie globalnym.asax? Co to ma wpływ

    • nie, możesz to zrobić na stronach błędów, nie jesteś pewien wpływu? jeśli zrobisz transfer non, jeśli przekierować, tam może być możliwość innego błąd wystąpił między żądaniami? Nie wiem. wiedzieć

    Dlaczego w sieci.config powinniśmy napisać błąd.aspx dwa razy jeden z kodem stanu 500 a drugi jest defaultredirect

    • używam 2, ponieważ utracona strona powinna Pokaż/i rób inne rzeczy niż błąd serwera. strona błędu pokazuje użytkownik wystąpił błąd, który my nie można odzyskać... i jego to pewnie nasza wina. Zostawiam a domyślne przekierowanie dla dowolnego innego również kody błędów. 403,401, 400 ( są rzadsze, ale powinny być obsługiwane )
    Możesz mi też podać kod błędu?aspx I lost.aspx.
    • To zależy od rodzaju strony internetowej tak. otrzymujesz ten sam błąd sposób, ale to, co z nim zrobisz, zależy od ty. na mojej zagubionej stronie Szukam niektóre treści, które użytkownik mógł Szukam. strony błędów, które rejestruję błąd i tak przyjazny dla użytkownika oops strona... będziesz musiał dowiedzieć się co jest potrzebne.
     9
    Author: BigBlondeViking,
    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
    2009-08-10 13:40:33

    Odpowiedź BigBlondeViking zadziałała świetnie dla mnie z tym wyjątkiem, że okazało się, że nie przetwarza 403 (które ASP generuje, gdy próbujesz uzyskać bezpośredni dostęp do katalogów/ Scripts /lub/ Content/.) Wygląda na to, że nie jest to propegowane jako wyjątek i dlatego nie można go trappować w obsłudze Application_Error. (to zostało zidentyfikowane jako "luka w zabezpieczeniach" przez zewnętrzną firmę - nie każ mi na tym zaczynać!)

    protected void Application_PostRequestHandlerExecute(object sender, EventArgs e)
    {
        if (!Context.Items.Contains("HasHandledAnError")) // have we alread processed?
        {
            if (Response.StatusCode > 400 &&  // any error
                Response.StatusCode != 401)   // raised when login is required
            {
                Exception exception = Server.GetLastError();    // this is null if an ASP error
                if (exception == null)
                {
                    exception = new HttpException((int)Response.StatusCode, HttpWorkerRequest.GetStatusDescription(Response.StatusCode));
                }
                HandleRequestError(exception); // code shared with Application_Error
            }
        }
    }
    

    Dokonałem także drobnej zmiany w moim powszechnym obchodzeniu się z błędami. As we are za pomocą ASP.NET MVC, chciałem jawnie wywołać do kontrolera, a także przekazać obiekt exception. To pozwoliło mi uzyskać dostęp do samego wyjątku, dzięki czemu mogę zalogować się / wysłać szczegółowy e-mail w zależności od kodu; {]}

    public ActionResult ServerError(Exception exception)
    {
        HttpException httpException = exception as HttpException;
        if(httpException != null)
        {
            switch (httpException.GetHttpCode())
            {
                case 403:
                case 404:
                    Response.StatusCode = 404;
                    break;
            }
            // no email...
            return View("HttpError", httpException);
        }
        SendExceptionMail(exception);
        Response.StatusCode = 500;
        return View("ServerError", exception);
    }
    

    W celu przekazania obiektu exception (nie tylko wiadomości i kodu) jawnie wywołałem Kontroler:

    protected void HandleRequestError(Exception exception)
    {
        if (Context.Items.Contains("HasHandledAnError"))
        {
            // already processed
            return;
        }
        // mark as processed.
        this.Context.Items.Add("HasHandledAnError", true);
    
        CustomErrorsSection customErrorsSection = WebConfigurationManager.GetWebApplicationSection("system.web/customErrors") as CustomErrorsSection;
    
        // Do not show the custom errors if
        // a) CustomErrors mode == "off" or not set.
        // b) Mode == RemoteOnly and we are on our local development machine.
        if (customErrorsSection == null || !Context.IsCustomErrorEnabled ||
            (customErrorsSection.Mode == CustomErrorsMode.RemoteOnly && Request.IsLocal))
        {
            return;
        }
    
        int httpStatusCode = 500;   // by default.
        HttpException httpException = exception as HttpException;
        if (httpException != null)
        {
            httpStatusCode = httpException.GetHttpCode();
        }
    
        string viewPath = customErrorsSection.DefaultRedirect;
        if (customErrorsSection.Errors != null)
        {
            CustomError customError = customErrorsSection.Errors[((int)httpStatusCode).ToString()];
            if (customError != null && string.IsNullOrEmpty(customError.Redirect))
            {
                viewPath = customError.Redirect;
            }
        }
    
        if (string.IsNullOrEmpty(viewPath))
        {
            return;
        }
    
        Response.Clear();
        Server.ClearError();
    
        var httpContextMock = new HttpContextWrapper(Context);
        httpContextMock.RewritePath(viewPath);
        RouteData routeData = RouteTable.Routes.GetRouteData(httpContextMock);
        if (routeData == null)
        {
            throw new InvalidOperationException(String.Format("Did not find custom view with the name '{0}'", viewPath));
        }
        string controllerName = routeData.Values["controller"] as string;
        if (String.IsNullOrEmpty(controllerName))
        {
            throw new InvalidOperationException(String.Format("No Controller was found for route '{0}'", viewPath));
        }
        routeData.Values["exception"] = exception;
    
        Response.TrySkipIisCustomErrors = true;
        RequestContext requestContext = new RequestContext(httpContextMock, routeData);
        IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
        IController errorsController = factory.CreateController(requestContext, controllerName);
        errorsController.Execute(requestContext);
    }
    
     3
    Author: AcidPAT,
    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-09-21 20:39:02