Định tuyến cho trang Lỗi ASP.NET MVC 404 tùy chỉnh


116

Tôi đang cố tạo trang lỗi HTTP 404 tùy chỉnh khi ai đó nhập URL không gọi hành động hoặc bộ điều khiển hợp lệ trong ASP.NET MVC, thay vì nó hiển thị lỗi ASP.NET chung chung "Không tìm thấy tài nguyên".

Tôi không muốn sử dụng web.config để xử lý việc này.

Có bất kỳ loại phép thuật định tuyến nào tôi có thể làm để bắt bất kỳ URL không hợp lệ nào không?

Cập nhật: Tôi đã thử câu trả lời được đưa ra, tuy nhiên tôi vẫn nhận được thông báo xấu xí "Không tìm thấy tài nguyên".

Một bản cập nhật khác: Ok, dường như có gì đó đã thay đổi trong RC1. Tôi thậm chí đã thử đặt bẫy cụ thể 404 trên một HttpExceptionvà nó vẫn chỉ cung cấp cho tôi trang "Không tìm thấy tài nguyên".

Tôi thậm chí đã sử dụng tính năng tài nguyên của MvcContrib và không có gì - cùng một vấn đề. Có ý kiến ​​gì không?



@Peter Đó là giải pháp mà tôi đã thêm cùng với việc ghi đè HandleUnknownAction để hiển thị chế độ xem không tìm thấy trang khi một hành động không tồn tại và sau đó trình xử lý lỗi tùy chỉnh ASP.net được tích hợp sẵn để xử lý bất kỳ điều gì khác mà người dùng có thể nhập vào .
dswatik

@pete Điều này hoạt động tốt như stackoverflow.com/questions/619895/…
dswatik

8
Tôi ghét điều đó khi những người dùng khác tự phụ và nói những thứ như "tại sao bạn muốn làm điều đó? Chỉ cần làm điều này ..." Nhưng tôi khuyên rằng nếu không có gì ngăn cản bạn sử dụng phương pháp tiếp cận web.config và nó đáp ứng nhu cầu của bạn, đó là một cách tiếp cận tiêu chuẩn và thanh lịch. Mọi phản hồi về cách tiếp cận đó đều được đánh giá cao, vì rất có thể có một số vấn đề với nó mà tôi không biết.
Sean

Câu trả lời:


10

Chỉ cần thêm bắt tất cả tuyến đường vào cuối bảng tuyến đường và hiển thị bất kỳ trang nào bạn muốn với nó.

Hãy xem: Làm cách nào để tôi có thể bắt tất cả các tuyến để xử lý các truy vấn 'không tìm thấy trang 404' cho ASP.NET MVC?


Tuy nhiên, tôi đã thử điều này, tôi vẫn nhận được Thông báo không tìm thấy tài nguyên mặc định của ASP.NET xấu xí ..
dswatik

3
Tôi không tìm thấy giải pháp dứt khoát (và linh hoạt !!) cho vấn đề này cả trong câu trả lời này cũng như trên liên kết được cung cấp.
Peter

4
Tôi cũng không ... đây có vẻ như là một câu trả lời khó hiểu. Tôi đang tìm kiếm thêm một cách để làm cho các customErrors hoạt động giống như trong WebForms. Có ý kiến ​​gì không?
JC Grubbs

1
Cả hai điều này đều không hoạt động và không tốt về nguyên tắc. Không hoạt động vì nó sẽ không bắt các URL xấu khớp với một trong các mẫu định tuyến trước đó. Không tốt về nguyên tắc vì nó chuyển đổi những gì nên là một lỗi thành một lỗi. Chuyển hướng đến trang bạn đã đặt tên là "Lỗi" khác với chuyển hướng đến một trang lỗi. Bạn muốn giữ nó như một lỗi, ghi lại lỗi, sau đó xử lý nó như một lỗi. Sai sót là thông tin có giá trị.
Matthew

105

Tôi đã cố gắng kích hoạt lỗi tùy chỉnh trên máy chủ sản xuất trong 3 giờ, có vẻ như tôi đã tìm thấy giải pháp cuối cùng để thực hiện việc này trong ASP.NET MVC mà không có bất kỳ tuyến nào.

Để kích hoạt lỗi tùy chỉnh trong ứng dụng ASP.NET MVC, chúng tôi cần (IIS 7+):

  1. Định cấu hình các trang tùy chỉnh trong cấu hình web trong system.webphần:

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

    RemoteOnlycó nghĩa là trên mạng cục bộ, bạn sẽ thấy các lỗi thực sự (rất hữu ích trong quá trình phát triển). Chúng tôi cũng có thể viết lại trang lỗi cho bất kỳ mã lỗi nào.

  2. Đặt thông số Phản hồi ma thuật và mã trạng thái phản hồi (trong mô-đun xử lý lỗi hoặc trong thuộc tính xử lý lỗi)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
  3. Đặt một cài đặt kỳ diệu khác trong cấu hình web trong system.webServerphần:

    <httpErrors errorMode="Detailed" />

Đây là điều cuối cùng mà tôi đã tìm thấy và sau đó, tôi có thể thấy các lỗi tùy chỉnh trên máy chủ sản xuất.


8
Đây vẫn không phải là một giải pháp lý tưởng. Nó không giúp bạn nhận được mã phản hồi HTTP thích hợp. Sử dụng customErrorskết quả trong chuyển hướng 302 chỉ để tải trang lỗi của bạn.
Justin Helgerson

@ Ek0nomik Tôi chưa từng thấy giải pháp lý tưởng :)
Andrew Orsich

2
@JustinHelgerson Tôi thiết lập ErrorController cho mỗi mã trạng thái và đặt Mã phản hồi bên trong các hành động đó và nó đặt mã phản hồi tốt .. Tôi đã thử nghiệm với Fiddler và mã trạng thái 404 phản hồi với 404 và các trang có 500 lỗi phản hồi với 500. Và trong cả hai trường hợp quan điểm lỗi tùy chỉnh của tôi được phục vụ lên
Shane Neuville

người bạn trong nhóm của tôi vừa xóa Chế độ xem lỗi trong Thư mục được chia sẻ , để tạo lỗi thời gian chạy với mã trạng thái 500 chuyển hướng đến Trang lỗi tùy chỉnh như đã đề cập ở đâyở đây . Hy vọng sẽ giúp ai đó.
shaijut

41

Tôi đã xử lý lỗi hoạt động bằng cách tạo ErrorController trả về các dạng xem trong bài viết này. Tôi cũng phải thêm "Catch All" vào tuyến đường trong global.asax.

Tôi không thể biết nó sẽ đi đến bất kỳ trang lỗi nào trong số này nếu nó không có trong Web.config ..? Web.config của tôi phải chỉ định:

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

và sau đó tôi cũng thêm:

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

2
Cảm ơn - điều đó đã giúp tôi, 2 năm sau! Bạn phải làm gì nếu bạn chỉ muốn có lỗi tùy chỉnh cho 404, không có gì khác?
Shaul Behr

1
@Shaul một năm sau ... không đặt defaultRedirect, loại trừ hoàn toàn thuộc tính.
NJE

27

Nguồn

NotFoundMVC - Cung cấp trang 404 thân thiện với người dùng bất cứ khi nào bộ điều khiển, hành động hoặc tuyến đường không được tìm thấy trong ứng dụng ASP.NET MVC3 của bạn. Một dạng xem được gọi là NotFound được hiển thị thay vì trang lỗi ASP.NET mặc định.

Bạn có thể thêm plugin này qua nuget bằng cách sử dụng: Install-Package NotFoundMvc

NotFoundMvc tự động cài đặt chính nó trong quá trình khởi động ứng dụng web. Nó xử lý tất cả các cách khác nhau mà một 404 HttpException thường được ASP.NET MVC ném ra. Điều này bao gồm một bộ điều khiển, hành động và tuyến đường bị thiếu.

Hướng dẫn cài đặt từng bước:

1 - Nhấp chuột phải vào Dự án của bạn và Chọn Quản lý Gói Nuget ...

2 - Tìm kiếm NotFoundMvcvà cài đặt nó. nhập mô tả hình ảnh ở đây

3 - Sau khi cài đặt xong, hai tệp sẽ được thêm vào dự án của bạn. Như thể hiện trong ảnh chụp màn hình bên dưới.

nhập mô tả hình ảnh ở đây

4 - Mở NotFound.cshtml mới được thêm vào hiện tại tại Views / Shared và sửa đổi nó theo ý muốn của bạn. Bây giờ hãy chạy ứng dụng và nhập một url không chính xác, và bạn sẽ được chào đón với trang 404 thân thiện với người dùng.

nhập mô tả hình ảnh ở đây

Không còn nữa, người dùng sẽ nhận được thông báo lỗi như Server Error in '/' Application. The resource cannot be found.

Hi vọng điêu nay co ich :)

Tái bút: Kudos cho Andrew Davey vì đã tạo ra một plugin tuyệt vời như vậy.


@niico Từ việc xem mã nguồn, có vẻ như đặt mã phản hồi thành 404, vì vậy có.
Will Dean

20

Hãy thử điều này trong web.config để thay thế các trang lỗi IIS. Đây là giải pháp tốt nhất mà tôi đoán, và nó cũng gửi mã trạng thái chính xác.

<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>

Thông tin thêm từ Tipila - Sử dụng các trang lỗi tùy chỉnh ASP.NET MVC


1
+1. Đây là điều duy nhất dường như hoạt động nhất quán đối với tôi trên MVC5 với nhiều lĩnh vực.
hawkke

Đây là giải pháp dễ dàng nhất. Tuy nhiên, bạn không thể sử dụng cú pháp dao cạo trong trang lỗi của mình.
highace

15

Giải pháp này không cần thay đổi tệp web.config hoặc bắt tất cả các tuyến.

Đầu tiên, tạo một bộ điều khiển như thế này;

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

Sau đó, tạo chế độ xem trong "Lượt xem / Lỗi / Index.cshtml" như;

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

Sau đó, thêm thông tin sau vào tệp Global asax như bên dưới:

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

Nếu bạn vẫn nhận được trang lỗi IIS tùy chỉnh sau khi thực hiện việc này, hãy đảm bảo rằng các phần sau được nhận xét (hoặc trống) trong tệp cấu hình web:

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

Tôi không nghĩ rằng phương pháp này sẽ hoạt động trong mọi trường hợp, vì 404 thường bị máy chủ web chặn và do đó không bao giờ được xử lý ở cấp ứng dụng.
Chris Halcrow

Tôi muốn thêm rằng nếu bạn sử dụng cách tiếp cận này, tôi khuyên bạn nên thêm một Response.End();vào cuối trình xử lý Application_Error của bạn. Nếu không có điều này, chỉ sự xuất hiện đầu tiên của lỗi được kích hoạt cho một phiên nhất định, đây là một vấn đề khi bạn có, ví dụ: lỗi tùy chỉnh đăng nhập trong trình xử lý Application_Error.
Keith

6

Nếu bạn làm việc trong MVC 4, bạn có thể xem này giải pháp , nó đã làm việc cho tôi.

Thêm phương thức Application_Error sau vào của tôi 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();

Bản thân bộ điều khiển thực sự đơn giản:

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

Kiểm tra mã nguồn đầy đủ của Mvc4CustomErrorPage tại GitHub .


0

Tôi đã gặp vấn đề tương tự, điều bạn phải làm là thay vì thêm thuộc tính customErrors trong tệp web.config trong thư mục Chế độ xem của bạn, bạn phải thêm nó vào tệp web.config trong thư mục gốc dự án của bạn


0

Đây là câu trả lời đúng cho phép tùy chỉnh hoàn toàn trang lỗi ở một nơi duy nhất. Không cần phải sửa đổi web.config hoặc tạo mã riêng biệt.

Hoạt động cũng trong MVC 5.

Thêm mã này vào bộ điều khiển:

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

Dựa trên http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages


0

Tôi sẽ nói về một số trường hợp cụ thể,

nếu bạn đang sử dụng 'phương thức PageNotFound' trong HomeController như bên dưới

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

nó sẽ không hoạt động này. Nhưng bạn phải xóa các thẻ Tuyến đường như bên dưới,

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

Và nếu bạn thay đổi nó thành phương thức Name trong web.config thì nó sẽ hoạt động. Tuy nhiên, đừng quên làm mã như dưới đây trong 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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.