CẬP NHẬT
Vì câu trả lời này không cung cấp giải pháp, tôi sẽ không chỉnh sửa nó, nhưng tôi đã tìm ra cách giải quyết vấn đề này gọn gàng hơn nhiều. Xem câu trả lời khác của tôi để biết chi tiết ...
Câu trả lời gốc:
Tôi đã tìm ra lý do tại sao Application_Error()
phương thức này không được gọi ...
Toàn cầu.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); // this line is the culprit
}
...
}
Theo mặc định (khi một dự án mới được tạo), một ứng dụng MVC có một số logic trong Global.asax.cs
tệp. Logic này được sử dụng để ánh xạ các tuyến đường và đăng ký bộ lọc. Theo mặc định, nó chỉ đăng ký một bộ lọc: HandleErrorAttribute
bộ lọc. Khi customErrors được bật (hoặc thông qua các yêu cầu từ xa khi được đặt thành RemoteOnly), HandleErrorAttribution nói với MVC để tìm chế độ xem Lỗi và nó không bao giờ gọi Application_Error()
phương thức. Tôi không thể tìm thấy tài liệu về điều này nhưng nó được giải thích trong câu trả lời này trên lập trình viên.stackexchange.com .
Để có được phương thức ApplicationError () được gọi cho mọi ngoại lệ chưa được xử lý, chỉ cần xóa dòng đăng ký bộ lọc HandleErrorAttribution.
Bây giờ vấn đề là: Làm cách nào để định cấu hình customErrors để có được thứ bạn muốn ...
Phần customErrors mặc định là redirectMode="ResponseRedirect"
. Bạn cũng có thể chỉ định thuộc tính defaultRedirect là một tuyến MVC. Tôi đã tạo một ErrorContoder rất đơn giản và đã thay đổi web.config của mình thành như thế này ...
web.config
<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
Vấn đề với giải pháp này là nó thực hiện chuyển hướng 302 đến các URL lỗi của bạn và sau đó các trang đó phản hồi với mã trạng thái 200. Điều này dẫn đến việc Google lập chỉ mục các trang lỗi. Nó cũng không phù hợp với thông số HTTP. Những gì tôi muốn làm là không chuyển hướng và ghi đè phản hồi ban đầu với các chế độ xem lỗi tùy chỉnh của tôi.
Tôi đã cố gắng thay đổi redirectMode="ResponseRewrite"
. Thật không may, tùy chọn này không hỗ trợ các tuyến MVC , chỉ có các trang HTML tĩnh hoặc ASPX. Tôi đã cố gắng sử dụng một trang HTML tĩnh lúc đầu nhưng mã phản hồi vẫn là 200 nhưng, ít nhất nó không chuyển hướng. Sau đó tôi có một ý tưởng từ câu trả lời này ...
Tôi quyết định từ bỏ MVC để xử lý lỗi. Tôi đã tạo ra một Error.aspx
và một PageNotFound.aspx
. Những trang này rất đơn giản nhưng chúng có một mảnh ma thuật ...
<script type="text/C#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
}
</script>
Khối này cho biết trang sẽ được phục vụ với mã trạng thái chính xác. HttpStatusCode.NotFound
Thay vào đó , trên trang PageNotFound.aspx, tôi đã sử dụng thay thế. Tôi đã thay đổi web.config của mình thành như thế này ...
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
Tất cả đều hoạt động hoàn hảo!
Tóm lược:
- Xóa dòng:
filters.Add(new HandleErrorAttribute());
- Sử dụng
Application_Error()
phương pháp để ghi lại các ngoại lệ
- Sử dụng CustomErrors với FeedbackRewrite, chỉ vào các trang ASPX
- Làm cho các trang ASPX chịu trách nhiệm về mã trạng thái phản hồi của riêng họ
Có một vài nhược điểm tôi đã nhận thấy với giải pháp này.
- Các trang ASPX không thể chia sẻ bất kỳ đánh dấu nào với các mẫu Dao cạo, tôi đã phải viết lại đánh dấu tiêu đề và chân trang tiêu chuẩn của trang web của chúng tôi để có giao diện nhất quán.
- Các trang * .aspx có thể được truy cập trực tiếp bằng cách nhấn URL của họ
Có những cách giải quyết cho những vấn đề này nhưng tôi không đủ quan tâm đến họ để làm thêm.
Tôi hy vọng điều này sẽ giúp tất cả mọi người!