Asp.net MVC3'teki özel hata sayfaları


144

Ben bir MVC3 temel web sitesi geliştiriyorum ve ben hataları ve hata her türlü özel Görünümler işleme için bir çözüm arıyorum. Bu yüzden, ana eyleminin "Dizin" (genel hata sayfası) olduğu bir "Hata" Denetleyicisine sahip olduğumu ve bu denetleyicinin kullanıcıya "Handle500" veya "HandleActionNotFound" gibi görünebilecek hatalar için birkaç eylemi daha olacağını düşünün.

Bu nedenle, web sitesinde olabilecek her hata bu "Hata" Denetleyicisi tarafından ele alınabilir (örnekler: "Denetleyici" veya "Eylem" bulunamadı, 500, 404, dbException, vb.).

Web sitesi yollarını tanımlamak için Site Haritası dosyası kullanıyorum (rota değil).

Bu soru zaten cevaplandı, bu Gweebz için bir cevap

Son applicaiton_error yöntemim şu şekildedir:

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

Bunu desteklemek için web.config dosyasındaki ayarlar ne olmalıdır? Kuşkusuz herhangi bir httperrors ayarı eklemez miydiniz?
13'de philbird

forums.asp.net/p/1782402/4894514.aspx/… , 512 baytın altındaysa IE hata sayfanızı göstermez gibi bazı güzel ipuçlarına sahiptir
RickAndMSFT 23:01

Yanıtlar:


201

İşte özel hataları nasıl ele aldığımın bir örneği. Ben tanımlamak bir ErrorsControllereylemleri ile farklı HTTP hataları işleme:

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

ve sonra Application_Errorin için abone olun Global.asaxve bu denetleyiciyi çağırmak:

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

4
Sadece küçük bir not. Her ActionResult üzerinde her durumda (404, 500 vb.) Bir Görünüm oluşturmak istediğimden bir Görünüm döndürdüm. Ancak ben Application_Error içeriği etrafında bir try catch yaptım ve başarısızlık durumunda statik bir HTML sayfası döndürülür. (Birisi isterse kodu gönderebilirim)
John Louros

4
MVC3 üzerinde bu çözümü kullanarak render için jilet görünümleri alamıyorum. dönüş Görünümü (model) örneğin yalnızca boş bir ekran alır.
Extrakun

2
Tümleşik IIS7 için düzeltmek için TrySkipIisCustomErrors eklendi. Bkz. Stackoverflow.com/questions/1706934/…
Pavel Savara

1
@ajbeaven, arayüzde Executetanımlanan bir yöntemdir IController. Bu muhtemelen korunamaz. Kodumu daha dikkatli bir şekilde bakın: IController errorsController = new ErrorsController();ve yöntemi errorsControllerçağırdığım değişkenin türüne dikkat edin Execute. Bu tiptir, IControllerbu yüzden bu yöntemi çağırmanızı engelleyen hiçbir şey yoktur. Bu arada Execute, MVC 3'te Controller sınıfında da korundu, bu nedenle bu konuda bir değişiklik yok.
Darin Dimitrov

2
Yanıtın içerik türünü açıkça belirterek düzeltildi:Response.ContentType = "text/html";
ajbeaven


6

Bunu Web.Config Dosyasında da yapabilirsiniz. İşte IIS 7.5'te çalışan bir örnek.

     <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

İçin bir yapılandırma değeri eklediğinizi görüyorsunuz EnableCustomErrorPageve ayrıca IsDebuggingEnabledhata işlemeyi çalıştırıp çalıştırmayacağınızı da kontrol ediyorsunuz.

<customErrors/>ASP.NET'te zaten bir yapılandırma olduğundan (tam olarak bu amaç için tasarlanmıştır) söylemek en kolayı:

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

Daha sonra, bu <customErrors mode="RemoteOnly" />şekilde konuşlandırılması güvenli olan yapılandırmada ve özel hata sayfanızı test etmeniz gerektiğinde, <customErrors mode="On" />çalıştığını doğrulayabilmeniz için ayarlayın .

Ayrıca HttpContext.Current, null olup olmadığını da kontrol etmeniz gerektiğini unutmayın , çünkü Application_Startetkin bir bağlam olmayacak olsa da, bir istisna hala bu yöntem olacaktır.


2

Jeff Atwood'un Kullanıcı Dostu İstisna İşleme modülünü http durum kodu için küçük bir değişiklikle uygulayarak doğru http durum koduna sahip kullanıcı dostu bir hata sayfası görüntüleyebilirsiniz . Yönlendirme olmadan çalışır. Kod 2004'ten (!) Olmasına rağmen, MVC ile iyi çalışır. Tamamen web.config dosyasında, hiçbir MVC proje kaynak kodu değişikliği olmadan yapılandırılabilir.

Modifikasyon bir yerine orijinal HTTP durumunu dönmek için gerekli 200statü açıklanan bu ilgili forum sonrası .

Temel olarak, Handler.vb'de şöyle bir şey ekleyebilirsiniz:

' 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

MVC 4.5 kullanıyorum ve Darin'in çözümü ile ilgili sorunlar yaşıyordum. Not: Darin'in çözümü mükemmel ve çözümümü bulmak için kullandım. İşte değiştirilmiş çözümüm:

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

2
Darin'in çözümü ile ilgili ne gibi sorunlar yaşıyordunuz?
Kenny Evitt

Rakip bir yanıta neden olan sorunu tarif etmediniz.
ivanjonas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.