การกำหนดเส้นทางสำหรับหน้าข้อผิดพลาด ASP.NET MVC 404 ที่กำหนดเอง


116

ฉันกำลังพยายามสร้างหน้าข้อผิดพลาด HTTP 404 ที่กำหนดเองเมื่อมีคนพิมพ์ URL ที่ไม่เรียกใช้การดำเนินการหรือตัวควบคุมที่ถูกต้องใน ASP.NET MVC แทนที่จะแสดงข้อผิดพลาด ASP.NET "ทรัพยากรไม่พบ" ทั่วไป

ฉันไม่ต้องการใช้ web.config เพื่อจัดการสิ่งนี้

มีเวทมนตร์การกำหนดเส้นทางประเภทใดบ้างที่ฉันสามารถทำได้เพื่อตรวจจับ URL ที่ไม่ถูกต้อง

อัปเดต:ฉันลองใช้คำตอบที่ได้รับ แต่ยังคงได้รับข้อความ "ไม่พบทรัพยากร" ที่น่าเกลียด

การอัปเดตอื่น:โอเคเห็นได้ชัดว่ามีบางอย่างเปลี่ยนแปลงใน RC1 ฉันได้ลองใช้กับดัก 404 โดยเฉพาะในHttpExceptionและมันก็ยังให้หน้า "ไม่พบทรัพยากร"

ฉันเคยใช้คุณลักษณะทรัพยากรของ MvcContrib แล้ว แต่ก็ไม่มีปัญหาเหมือนกัน ความคิดใด ๆ ?



@Peter นั่นคือวิธีแก้ปัญหาที่ฉันได้เพิ่มเข้าไปพร้อมกับการแทนที่ HandleUnknownAction เพื่อแสดงมุมมองที่ไม่พบเพจเมื่อไม่มีการดำเนินการจากนั้นตัวจัดการข้อผิดพลาดที่กำหนดเองใน ASP.net เพื่อจัดการกับสิ่งอื่นใดที่ผู้ใช้อาจพิมพ์ลงไป .
dswatik

@pete นี่ก็ใช้ได้เหมือนกันstackoverflow.com/questions/619895/…
dswatik

8
ฉันเกลียดมันเมื่อผู้ใช้คนอื่นเกรงใจและพูดในทำนองว่า "ทำไมคุณถึงอยากทำแบบนั้นแค่ทำแบบนี้ ... " แต่ฉันขอแนะนำว่าหากไม่มีอะไรหยุดคุณจากการใช้วิธี web.config และมัน ตอบสนองความต้องการของคุณเป็นแนวทางที่เป็นมาตรฐานและสง่างาม ข้อเสนอแนะใด ๆ เกี่ยวกับแนวทางดังกล่าวเป็นที่ชื่นชมเนื่องจากอาจมีปัญหาบางอย่างที่ฉันไม่รู้
ฌอน

คำตอบ:


10

เพียงเพิ่มการจับเส้นทางทั้งหมดที่ส่วนท้ายของตารางเส้นทางและแสดงหน้าใดก็ได้ที่คุณต้องการด้วย

ดู: ฉันจะตรวจจับเส้นทางทั้งหมดเพื่อจัดการข้อความค้นหา 'ไม่พบหน้า 404' สำหรับ ASP.NET MVC ได้อย่างไร


ฉันลองแล้ว แต่ยังคงได้รับข้อความไม่พบทรัพยากรเริ่มต้นของ ASP.NET ที่น่าเกลียด ..
dswatik

3
ฉันไม่พบวิธีแก้ปัญหาที่ชัดเจน (และยืดหยุ่น !!) สำหรับปัญหานี้ทั้งในคำตอบนี้หรือในลิงค์ที่ให้มา
ปีเตอร์

4
ฉันก็ไม่ ... ดูเหมือนจะเป็นคำตอบที่แฮ็ค ฉันกำลังมองหาวิธีที่จะทำให้ customErrors ทำงานได้เหมือนกับที่ทำใน WebForms ความคิดใด ๆ ?
JC Grubbs

1
ทั้งสองอย่างนี้ใช้ไม่ได้และไม่ดีตามหลักการ ใช้งานไม่ได้เนื่องจากไม่พบ URL ที่ไม่ถูกต้องซึ่งตรงกับรูปแบบการกำหนดเส้นทางก่อนหน้านี้ ผิดหลักการเพราะมันแปลงสิ่งที่ควรเป็นข้อผิดพลาดให้ไม่ใช่ข้อผิดพลาด การเปลี่ยนเส้นทางไปยังหน้าที่คุณตั้งชื่อว่า "ข้อผิดพลาด" แตกต่างจากการเปลี่ยนเส้นทางไปยังหน้าข้อผิดพลาด คุณต้องการเก็บเป็นข้อผิดพลาดบันทึกข้อผิดพลาดจากนั้นจัดการเป็นข้อผิดพลาด ข้อผิดพลาดเป็นข้อมูลที่มีค่า
Matthew

105

ฉันพยายามเปิดใช้งานข้อผิดพลาดที่กำหนดเองบนเซิร์ฟเวอร์ที่ใช้งานจริงเป็นเวลา 3 ชั่วโมงดูเหมือนว่าฉันจะพบทางออกสุดท้ายในการทำสิ่งนี้ใน ASP.NET MVC โดยไม่มีเส้นทางใด ๆ

ในการเปิดใช้งานข้อผิดพลาดที่กำหนดเองในแอปพลิเคชัน ASP.NET MVC เราต้องการ (IIS 7+):

  1. กำหนดค่าเพจที่กำหนดเองในการกำหนดค่าเว็บภายใต้system.webส่วน:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>

    RemoteOnlyหมายความว่าบนเครือข่ายท้องถิ่นคุณจะเห็นข้อผิดพลาดจริง (มีประโยชน์มากในระหว่างการพัฒนา) นอกจากนี้เรายังสามารถเขียนหน้าข้อผิดพลาดใหม่สำหรับรหัสข้อผิดพลาดใด ๆ

  2. ตั้งค่าพารามิเตอร์การตอบกลับมายากลและรหัสสถานะการตอบสนอง (ในโมดูลการจัดการข้อผิดพลาดหรือในแอตทริบิวต์การจัดการข้อผิดพลาด)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
  3. ตั้งค่ามายากลอื่นในการกำหนดค่าเว็บในsystem.webServerส่วน:

    <httpErrors errorMode="Detailed" />

นี่เป็นสิ่งสุดท้ายที่ฉันพบและหลังจากนี้ฉันสามารถเห็นข้อผิดพลาดที่กำหนดเองบนเซิร์ฟเวอร์การผลิต


8
นี่ยังไม่ใช่ทางออกที่ดี ไม่ได้รับรหัสตอบกลับ HTTP ที่ถูกต้อง การใช้customErrorsผลลัพธ์ในการเปลี่ยนเส้นทาง 302 เพียงเพื่อโหลดหน้าข้อผิดพลาดของคุณ
Justin Helgerson

@ Ek0nomik ฉันไม่เคยเห็นโซลูชันที่ดีที่สุด :)
Andrew Orsich

2
@JustinHelgerson ฉันตั้งค่า ErrorController สำหรับแต่ละรหัสสถานะและตั้งรหัสตอบกลับภายในการดำเนินการเหล่านั้นและตั้งรหัสการตอบกลับที่ดี .. ฉันทดสอบด้วย Fiddler และรหัสสถานะ 404 ตอบสนองด้วย 404 และหน้าที่มีข้อผิดพลาด 500 ข้อตอบสนองด้วย 500 และ ในทั้งสองกรณีมุมมองข้อผิดพลาดที่กำหนดเองของฉันแสดงขึ้น
Shane Neuville

เพื่อนร่วมทีมของฉันเพียงแค่ลบมุมมองข้อผิดพลาดภายใต้การแชร์โฟลเดอร์ที่จะทำให้ข้อผิดพลาด runtime 500 รหัสสถานะจะเปลี่ยนเส้นทางไปยังที่กำหนดเองข้อผิดพลาดหน้าเป็นที่กล่าวถึงที่นี่และที่นี่ ความหวังช่วยใครบางคน
shaijut

41

ฉันได้รับการจัดการข้อผิดพลาดในการทำงานโดยสร้าง ErrorController ที่ส่งคืนมุมมองในบทความนี้ ฉันยังต้องเพิ่ม "Catch All" ในเส้นทางใน global.asax

ฉันไม่เห็นว่ามันจะไปยังหน้าแสดงข้อผิดพลาดเหล่านี้ได้อย่างไรหากไม่ได้อยู่ใน Web.config .. ? Web.config ของฉันต้องระบุ:

customErrors mode="On" defaultRedirect="~/Error/Unknown"

จากนั้นฉันก็เพิ่ม:

error statusCode="404" redirect="~/Error/NotFound"

2
ขอบคุณ - ที่ช่วยฉันออกมา 2 ปีต่อมา! คุณจะทำอย่างไรถ้าคุณต้องการเฉพาะข้อผิดพลาดที่กำหนดเองสำหรับ 404 ไม่มีอะไรอื่นอีก
Shaul Behr

1
@Shaul อีกหนึ่งปีต่อมา ... อย่าตั้งค่า defaultRedirect ไม่รวมแอตทริบิวต์ทั้งหมด
NJE

27

แหล่ง

NotFoundMVC - จัดเตรียมเพจ 404 ที่ใช้งานง่ายเมื่อใดก็ตามที่ไม่พบคอนโทรลเลอร์การกระทำหรือเส้นทางในแอปพลิเคชัน ASP.NET MVC3 ของคุณ มุมมองที่เรียกว่า NotFound จะแสดงผลแทนหน้าข้อผิดพลาด ASP.NET เริ่มต้น

คุณสามารถเพิ่มปลั๊กอินนี้ผ่านทาง nuget โดยใช้: Install-Package NotFoundMvc

NotFoundMvc จะติดตั้งตัวเองโดยอัตโนมัติในระหว่างการเริ่มต้นโปรแกรมประยุกต์บนเว็บ จัดการทุกวิธีที่แตกต่างกัน 404 HttpException มักจะถูกส่งโดย ASP.NET MVC ซึ่งรวมถึงตัวควบคุมการดำเนินการและเส้นทางที่ขาดหายไป

คู่มือการติดตั้งทีละขั้นตอน:

1 - คลิกขวาที่โครงการของคุณและเลือกจัดการแพ็คเกจ Nuget ...

2 - ค้นหาNotFoundMvcและติดตั้ง ใส่คำอธิบายภาพที่นี่

3 - เมื่อการติดตั้งเสร็จสมบูรณ์ไฟล์สองไฟล์จะถูกเพิ่มลงในโปรเจ็กต์ของคุณ ดังที่แสดงในภาพหน้าจอด้านล่าง

ใส่คำอธิบายภาพที่นี่

4 - เปิด NotFound.cshtml ที่เพิ่มใหม่ที่มีอยู่ใน Views / Shared และแก้ไขตามที่คุณต้องการ ตอนนี้เรียกใช้แอปพลิเคชันและพิมพ์ url ที่ไม่ถูกต้องและคุณจะได้รับการต้อนรับด้วยหน้า 404 ที่ใช้งานง่าย

ใส่คำอธิบายภาพที่นี่

ไม่มีอีกแล้วผู้ใช้จะได้รับข้อความแสดงข้อผิดพลาดเช่น Server Error in '/' Application. The resource cannot be found.

หวังว่านี่จะช่วยได้ :)

PS: ขอชื่นชมAndrew Daveyในการสร้างปลั๊กอินที่ยอดเยี่ยมเช่นนี้


@niico จากการดูซอร์สโค้ดดูเหมือนว่าจะตั้งค่ารหัสตอบกลับเป็น 404 ใช่
Will Dean

20

ลองใช้ใน web.config เพื่อแทนที่หน้าข้อผิดพลาด IIS นี่เป็นทางออกที่ดีที่สุดที่ฉันเดาและจะส่งรหัสสถานะที่ถูกต้องด้วย

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

ข้อมูลเพิ่มเติมจากTipila - ใช้ Custom Error Pages ASP.NET MVC


1
+1 นี่เป็นสิ่งเดียวที่ดูเหมือนจะใช้ได้ผลอย่างสม่ำเสมอสำหรับฉันใน MVC5 ที่มีหลายพื้นที่
hawkke

นี่เป็นวิธีแก้ปัญหาที่ง่ายที่สุด คุณไม่สามารถใช้ไวยากรณ์มีดโกนในหน้าข้อผิดพลาดของคุณได้
Highace

15

โซลูชันนี้ไม่จำเป็นต้องมีการเปลี่ยนแปลงไฟล์ web.config หรือรับเส้นทางทั้งหมด

ขั้นแรกให้สร้างตัวควบคุมเช่นนี้

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Regular Error";
        return View();
    }

    public ActionResult NotFound404()
    {
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    }
}

จากนั้นสร้างมุมมองภายใต้ "Views / Error / Index.cshtml" เป็น;

 @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }                     
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

จากนั้นเพิ่มสิ่งต่อไปนี้ในไฟล์ Global asax ด้านล่าง:

protected void Application_Error(object sender, EventArgs e)
{
        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        {
            routeData.Values["action"] = "Index";
        }
        else
        {
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
        } 
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();
}

หากคุณยังคงได้รับหน้าข้อผิดพลาด IIS ที่กำหนดเองหลังจากทำสิ่งนี้ตรวจสอบให้แน่ใจว่ามีการแสดงความคิดเห็นในส่วนต่อไปนี้ (หรือว่างเปล่า) ในไฟล์กำหนดค่าของเว็บ:

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>

ฉันไม่คิดว่าวิธีนี้จะใช้ได้ผลในทุกกรณีเนื่องจากเว็บเซิร์ฟเวอร์มักจะดัก 404 ดังนั้นจึงไม่ได้รับการจัดการในระดับแอปพลิเคชัน
Chris Halcrow

ฉันต้องการเพิ่มว่าหากคุณใช้แนวทางนี้ฉันขอแนะนำให้เพิ่มResponse.End();ส่วนท้ายของตัวจัดการ Application_Error ของคุณ หากไม่มีสิ่งนี้ข้อผิดพลาดที่เกิดขึ้นครั้งแรกเท่านั้นที่จะถูกทริกเกอร์สำหรับเซสชันที่กำหนดซึ่งเป็นปัญหาเมื่อคุณมีตัวอย่างเช่นการบันทึกข้อผิดพลาดแบบกำหนดเองในตัวจัดการ Application_Error
Keith

6

หากคุณทำงานใน MVC 4 คุณสามารถดูสิ่งนี้ได้วิธีซึ่งใช้ได้กับฉัน

เพิ่มวิธี Application_Error ต่อไปนี้ใน my Global.asax:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Error");
    routeData.Values.Add("action", "Index");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

ตัวควบคุมนั้นง่ายมาก:

public class ErrorController : Controller
{
    public ActionResult Index(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        return View();
    }
}

ตรวจสอบรหัสที่มาเต็มรูปแบบของMvc4CustomErrorPage ที่ GitHub


0

ฉันมีปัญหาเดียวกันสิ่งที่คุณต้องทำคือแทนที่จะเพิ่มแอตทริบิวต์ customErrors ในไฟล์ web.config ในโฟลเดอร์ Views ของคุณคุณต้องเพิ่มในไฟล์ web.config ในโฟลเดอร์รูทโปรเจ็กต์ของคุณ


0

นี่คือคำตอบที่แท้จริงซึ่งช่วยให้สามารถปรับแต่งหน้าข้อผิดพลาดได้อย่างสมบูรณ์ในที่เดียว ไม่จำเป็นต้องแก้ไข web.config หรือสร้างโค้ดแยก

ใช้งานได้ใน MVC 5

เพิ่มรหัสนี้ในตัวควบคุม:

        if (bad) {
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        }

อ้างอิงจากhttp://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages


0

ฉันจะพูดถึงบางกรณี

หากคุณใช้ 'PageNotFound method' ใน HomeController ดังด้านล่าง

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

มันจะไม่ทำงานนี้ แต่คุณต้องล้างแท็กเส้นทางดังต่อไปนี้

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

และถ้าคุณเปลี่ยนเป็นชื่อวิธีการใน web.config มันก็ใช้ได้ อย่างไรก็ตามอย่าลืมทำโค้ดด้านล่างใน web.config

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.