ASP.NET Custom 404 Trả về 200 OK thay vì 404 Not Found


80

Sau khi cố gắng thiết lập trang web của tôi cho Công cụ quản trị trang web của Google, tôi nhận thấy rằng trang ASP.NET 404 tùy chỉnh của tôi không trả lại mã trạng thái 404. Nó hiển thị đúng trang tùy chỉnh và nói với trình duyệt rằng mọi thứ đều ổn. Đây được coi là soft 404 hoặc false 404. Google không thích điều này. Vì vậy, tôi đã tìm thấy nhiều bài báo về vấn đề này nhưng giải pháp tôi muốn dường như không hoạt động.

Giải pháp mà tôi muốn làm là thêm hai dòng sau vào mã đằng sau phương thức Page_Load của trang 404 tùy chỉnh.

Response.Status = "404 Not Found";
Response.StatusCode = 404;

Điều này không hoạt động. Trang vẫn trả về 200 OK. Tuy nhiên, tôi thấy rằng nếu tôi viết mã sau vào mã thiết kế, nó sẽ hoạt động bình thường.

<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">

<%
    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
%>

 ... Much more code ...

</asp:content>

Trang đang sử dụng trang chính. Và tôi đang định cấu hình các trang lỗi tùy chỉnh trong web.config của mình. Tôi thực sự muốn sử dụng mã phía sau tùy chọn nhưng dường như tôi không thể làm cho nó hoạt động nếu không đặt mã nội tuyến hack vào thiết kế / bố cục.


Trạng thái trình duyệt là gì? Tôi sử dụng addon Header Spy cho Firefox.
Bobby Cannon

Phản hồi gián điệp tiêu đề: HTTP / 1.1 404 Không tìm thấy Ngày: Chủ nhật, ngày 07 tháng 12 năm 2008 06:21:20 GMT
Ryan Cook

Bạn đang sử dụng một trang chủ? Có lẽ vậy thôi. Tôi sẽ cố gắng một trang mà không sử dụng một trang chủ ...
Bobby Cannon

Không, tôi không có, nhưng tôi cũng có thể kiểm tra nhanh, tôi sẽ thử với một cái.
Ryan Cook

Đúng vậy! Trang chủ gây ra 200 OK
Ryan Cook

Câu trả lời:


72

Giải pháp:

Hóa ra vấn đề là việc sử dụng trang chủ. Tôi đã làm cho nó hoạt động bằng cách đặt mã trạng thái sau đó trong vòng đời của các trang, rõ ràng là quá trình hiển thị trang chính đang đặt lại nó, vì vậy tôi đã ghi đè phương thức kết xuất và đặt nó sau khi kết xuất hoàn tất.

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);
    Response.StatusCode = 404;
}

Có thể phải làm thêm nhiều việc để tìm ra chính xác thời điểm trang chính đang thiết lập trạng thái, nhưng tôi sẽ giao việc đó cho bạn.


Bài gốc:

Tôi đã có thể làm cho một ứng dụng web thử nghiệm hoạt động tốt, ít nhất nó cũng hiển thị trang lỗi tùy chỉnh và trả về mã trạng thái 404. Tôi không thể cho bạn biết ứng dụng của bạn có vấn đề gì, nhưng tôi có thể cho bạn biết tôi đã làm gì:

1) Đã chỉnh sửa web.config cho các lỗi tùy chỉnh:

<customErrors mode="On">
  <error statusCode="404" redirect="404.aspx"/>
</customErrors>

2) Đã thêm trang 404.aspx và đặt mã trạng thái thành 404.

public partial class _04 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.StatusCode = 404;
    }
}

Đó là về nó, nếu tôi truy cập bất kỳ tiện ích mở rộng trang nào được xử lý bởi Asp.Net và không tồn tại, nhật ký trình duyệt của tôi hiển thị rõ ràng 404, đây là tiêu đề:

HTTP/1.1 404 Not Found
Server: Microsoft-IIS/5.1
Date: Sun, 07 Dec 2008 06:04:13 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 533

Bây giờ nếu tôi truy cập một trang không được xử lý bởi Asp.Net, chẳng hạn như tệp htm, trang tùy chỉnh sẽ không hiển thị và 404 được cấu hình bởi IIS được hiển thị.

Đây là một bài đăng đi vào một số chi tiết khác có thể hữu ích cho bạn và sự cố của bạn, thử nghiệm của tôi thực hiện chuyển hướng đến trang mới nên url của tệp được yêu cầu bị mất khá nhiều (ngoại trừ nó trong chuỗi truy vấn) .

Các trang lỗi tùy chỉnh của Google 404 và .NET

Phản hồi gián điệp tiêu đề:

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT

4
Tiêu đề Spy là addon tiêu đề Spy cho Firefox
Kiquenet

Điều này hoạt động như thế nào đối với các .htmltrang lỗi tùy chỉnh tĩnh ?
ebyrob

28

Tôi đã gặp sự cố tương tự, tôi muốn hiển thị một trang tùy chỉnh dưới dạng 404 (là ASPX) và nó hoạt động tốt trên localhost nhưng ngay sau khi khách truy cập từ xa kết nối họ sẽ nhận được IIS 404 chung.

Giải pháp cho điều này là thêm

Response.TrySkipIisCustomErrors = true;

Trước khi thay đổi Mã phản hồi.

Tìm thấy qua Rick Strahl http://www.west-wind.com/weblog/posts/745738.aspx


12

Giải pháp IIS 7 là chỉ cần thêm tệp này vào tệp web.config của bạn:

<system.webServer>
  <httpErrors existingResponse="Replace">
    <remove statusCode="500" subStatusCode="-1" />
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath="" path="404.htm" responseMode="File" />
    <error statusCode="500" prefixLanguageFilePath="" path="500.htm" responseMode="File" />
  </httpErrors>
</system.webServer>

http://forums.asp.net/t/1563128.aspx/1


3
Đã làm cho tôi! Chỉ có giải pháp ở đây đã hoạt động, có thể do phiên bản như bạn lưu ý ... Lưu ý: Bạn chỉ có thể sử dụng tệp .htm tĩnh với giải pháp này.
squarecandy

11

Hãy thử gọi Response.End () để bỏ qua hiển thị ...

Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;

9

Sau nhiều thử nghiệm và khắc phục sự cố, có vẻ như một số nhà cung cấp dịch vụ lưu trữ nhất định có thể can thiệp vào mã trả lại. Tôi đã có thể giải quyết vấn đề này bằng cách áp dụng "hack" trong nội dung.

<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>

Điều này sẽ cho phép trang trả lại mã trả lại chính xác bất kể điều gì.


1

Tôi đã có thể khắc phục sự cố này bằng cách sử dụng thiết lập sau trong biểu mẫu web asp.net sử dụng .NET 3.5.

Mẫu mà tôi đã triển khai bỏ qua giải pháp chuyển hướng tùy chỉnh của .NET trong web.config như tôi đã viết riêng để xử lý tất cả các tình huống với mã trạng thái HTTP chính xác trong tiêu đề.

Đầu tiên, phần customErrors của web.config trông giống như sau:

<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />

Thiết lập này đảm bảo rằng chế độ CustomErrors được bật, một cài đặt chúng tôi sẽ cần sau này và cung cấp tùy chọn all-else-failed cho defaultRedirect của error.htm. Điều này sẽ hữu ích khi tôi không có trình xử lý cho lỗi cụ thể hoặc có điều gì đó dọc theo đường kết nối cơ sở dữ liệu bị hỏng.

Thứ hai, đây là sự kiện Lỗi asax toàn cầu:

protected void Application_Error(object sender, EventArgs e)
    {
       HandleError();
    }

    private void HandleError()
    {
        var exception = Server.GetLastError();
        if (exception == null) return;

        var baseException = exception.GetBaseException();

        bool errorHandled = _applicationErrorHandler.HandleError(baseException);
        if (!errorHandled) return;


        var lastError = Server.GetLastError();
    if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
    {
        Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
        Server.ClearError();
    }
    }

Mã này đang chuyển trách nhiệm xử lý lỗi cho một lớp khác. Nếu lỗi không được xử lý và CustomErrors được bật, điều đó có nghĩa là chúng tôi gặp phải trường hợp đang sản xuất và bằng cách nào đó, lỗi vẫn chưa được xử lý. Chúng tôi sẽ xóa nó ở đây để ngăn người dùng nhìn thấy nó, nhưng hãy đăng nhập nó vào Elmah để chúng tôi biết chuyện gì đang xảy ra.

Lớp applicationErrorHandler trông như thế này:

public bool HandleError(Exception exception)
        {
            if (exception == null) return false;

            var baseException = exception.GetBaseException();

            Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);

            if (!HttpContext.Current.IsCustomErrorEnabled) return false;

            try
            {

                var behavior = _responseBehaviorFactory.GetBehavior(exception);
                if (behavior != null)
                {
                    behavior.ExecuteRedirect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }
            return false;
        }

Về cơ bản, lớp này sử dụng mẫu lệnh để định vị trình xử lý lỗi thích hợp cho loại lỗi được đưa ra. Điều quan trọng là phải sử dụng Exception.GetBaseException () ở cấp độ này, vì hầu hết mọi lỗi sẽ được bao bọc trong một ngoại lệ cấp cao hơn. Ví dụ: thực hiện "ném System.Exception () mới" từ bất kỳ trang aspx nào sẽ dẫn đến việc nhận HttpUnhandledException ở cấp độ này, không phải là System.Exception.

Mã "nhà máy" rất đơn giản và trông giống như sau:

public ResponseBehaviorFactory()
    {
        _behaviors = new Dictionary<Type, Func<IResponseBehavior>>
                        {
                            {typeof(StoreException), () => new Found302StoreResponseBehavior()},
                            {typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
                            {typeof(HttpException), () => new HttpExceptionResponseBehavior()},
                            {typeof(Exception), () => new Found302DefaultResponseBehavior()}
                        };
    }

    public IResponseBehavior GetBehavior(Exception exception)
    {                                                                               
        if (exception == null) throw new ArgumentNullException("exception");

        Func<IResponseBehavior> behavior;
        bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);

        //default value here:
        if (!tryGetValue)
            _behaviors.TryGetValue(typeof(Exception), out behavior);

        if (behavior == null)
            Elmah.ErrorSignal.FromCurrentContext().Raise(
                new Exception(
                    "Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
                    exception));
        return behavior();
    }

Cuối cùng, tôi đã có một thiết lập chương trình xử lý lỗi có thể mở rộng. Trong mỗi "hành vi" được xác định, tôi có một triển khai tùy chỉnh cho loại lỗi. Ví dụ: một ngoại lệ Http sẽ được kiểm tra mã trạng thái và xử lý thích hợp. Mã trạng thái 404 sẽ yêu cầu Server.Transfer thay vì Request.Redirect, cùng với mã trạng thái thích hợp được viết trong tiêu đề.

Hi vọng điêu nay co ich.


0

Bạn có thể sử dụng mã dưới đây:

 Response.TrySkipIisCustomErrors = True
 Response.Status = "404 Not Found"
 Response.AddHeader("Location", "{your-path-to-your-404-page}")
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.