कस्टम त्रुटि पृष्ठ asp.net MVC3 पर


144

मैं एक MVC3 आधार वेबसाइट विकसित कर रहा हूं और मैं त्रुटियों से निपटने के लिए एक समाधान की तलाश कर रहा हूं और प्रत्येक प्रकार की त्रुटि के लिए रेंडर कस्टम व्यू का उपयोग कर रहा हूं। तो कल्पना कीजिए कि मेरे पास एक "त्रुटि" नियंत्रक है जहां उसकी मुख्य क्रिया "सूचकांक" (सामान्य त्रुटि पृष्ठ) है और इस नियंत्रक के पास उपयोगकर्ता के लिए "हैंडले 500" या "हैंडलेऑशननॉटाउंडाउंड" जैसी त्रुटियों के लिए कुछ और क्रियाएं होंगी।

इसलिए वेबसाइट पर होने वाली प्रत्येक त्रुटि को इस "त्रुटि" नियंत्रक (उदाहरण: "नियंत्रक" या "कार्रवाई" द्वारा नहीं पाया जा सकता है, 500, 404, dbException, आदि)।

मैं वेबसाइट पथ (और मार्ग नहीं) को परिभाषित करने के लिए साइटमैप फ़ाइल का उपयोग कर रहा हूं।

यह प्रश्न पहले से ही उत्तर दिया गया था, यह गेबवेज का उत्तर है

मेरी अंतिम 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");
    }
}
}

इसका समर्थन करने के लिए web.config में सेटिंग्स क्या होनी चाहिए? संभवतः आप किसी भी प्रकार की कैंटरर सेटिंग्स शामिल नहीं करेंगे?
फिलबर्ड

forum.asp.net/p/1782402/4894514.aspx/… आईई जैसे कुछ अच्छे सुझाव आपके त्रुटि पृष्ठ नहीं दिखाएंगे यदि यह 512 बाइट्स के तहत है
रिकंडएमएसएफटी

जवाबों:


201

मैं कस्टम त्रुटियों को कैसे संभालता हूं इसका एक उदाहरण है। मैं 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में 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);
}

4
जरा ध्यान दें। चूँकि मैं प्रत्येक ActionResult पर प्रत्येक मामले (404, 500, आदि) में एक दृश्य प्रस्तुत करना चाहता था। हालाँकि, मैंने Application_Error सामग्री के आसपास एक प्रयास किया था और मुझे विफलता का मामला एक स्थिर HTML पृष्ठ वापस आ गया है। (यदि कोई इच्छा हो तो मैं कोड पोस्ट कर सकता हूं)
जॉन लौरोस

4
मुझे MVC3 पर इस समाधान का उपयोग करके रेजर के विचार नहीं मिल सकते हैं। उदाहरण के लिए रिटर्न व्यू (मॉडल) को केवल एक खाली स्क्रीन मिलती है।
एक्सट्रैकन

2
एकीकृत IIS7 के लिए इसे ठीक करने के लिए TrySkipIisCustomErrors जोड़ा गया। देखें stackoverflow.com/questions/1706934/…
Pavel Savara

1
@ajbeaven, इंटरफ़ेस Executeमें परिभाषित एक विधि IControllerहै। यह संभवतः संरक्षित नहीं किया जा सकता है। मेरे कोड को और अधिक ध्यान से देखें: IController errorsController = new ErrorsController();और errorsControllerचर के प्रकार पर ध्यान दें, जिस पर मैं Executeविधि का आह्वान कर रहा हूं । यह प्रकार है IControllerइसलिए इस पद्धति को कॉल करने से रोकने के लिए कुछ भी नहीं है। और वैसे Executeभी नियंत्रक वर्ग के साथ-साथ MVC 3 में भी संरक्षित किया गया था, इसलिए इस संबंध में कोई बदलाव नहीं हुआ है।
डारिन दिमित्रोव

2
स्पष्ट रूप से प्रतिक्रिया की सामग्री के प्रकार को निर्दिष्ट करके निर्धारित किया गया है:Response.ContentType = "text/html";
ajbeaven


6

आप इसे 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

मैं देखता हूं कि आपने के लिए एक कॉन्फ़िगरेशन मान जोड़ा है 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

आप जेफ एटवुड के यूजर फ्रेंडली एक्सेप्शन हैंडलिंग मॉड्यूल को HTTP स्टेटस कोड के लिए थोड़ा संशोधन करके सही http स्थिति कोड के साथ एक उपयोगकर्ता के अनुकूल त्रुटि पृष्ठ प्रदर्शित कर सकते हैं । यह बिना किसी रीडायरेक्ट के काम करता है। हालाँकि यह कोड 2004 (!) का है, लेकिन यह MVC के साथ अच्छा काम करता है। यह पूरी तरह से आपके web.config में कॉन्फ़िगर किया जा सकता है, जिसमें कोई MVC प्रोजेक्ट स्रोत कोड बिल्कुल भी नहीं बदलता है।

किसी 200स्टेटस के बजाय मूल HTTP स्टेटस को लौटाने के लिए आवश्यक संशोधन इस संबंधित फोरम पोस्ट में वर्णित है ।

मूल रूप से, 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

मैं एमवीसी 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);
    }
}
}

2
डारिन के समाधान के साथ आपके पास क्या मुद्दे थे?
केनी एविट

आपने उस समस्या का वर्णन नहीं किया जिसे आपने अनुभव किया था जो प्रतिस्पर्धा का जवाब देती थी।
ivanjonas
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.