Лучший способ реализовать 404 в ASP.NET - PullRequest
35 голосов
/ 20 марта 2009

Я пытаюсь определить лучший способ реализации страницы 404 в стандартном веб-приложении ASP.NET. Я в настоящее время ловлю 404 ошибки в событии Application_Error в файле Global.asax и перенаправляю на дружественную страницу 404.aspx. Проблема в том, что запрос видит перенаправление 302, за которым пропускает страницу 404. Есть ли способ обойти перенаправление и ответить немедленным 404, содержащим дружественное сообщение об ошибке?

Заботится ли сканер веб-сайтов, такой как Googlebot, о том, что запрос на несуществующую страницу возвращает 302, а затем 404?

Ответы [ 9 ]

43 голосов
/ 20 марта 2009

Обработайте это в событии OnError вашего Global.asax:

protected void Application_Error(object sender, EventArgs e){
  // An error has occured on a .Net page.
  var serverError = Server.GetLastError() as HttpException;

  if (serverError != null){
    if (serverError.GetHttpCode() == 404){
      Server.ClearError();
      Server.Transfer("/Errors/404.aspx");
    }
  }
}

На странице ошибки вы должны убедиться, что вы правильно устанавливаете код состояния:

// If you're running under IIS 7 in Integrated mode set use this line to override
// IIS errors:
Response.TrySkipIisCustomErrors = true;

// Set status code and message; you could also use the HttpStatusCode enum:
// System.Net.HttpStatusCode.NotFound
Response.StatusCode = 404;
Response.StatusDescription = "Page not found";

Вы также можете прекрасно обрабатывать различные другие коды ошибок здесь.

Google обычно следует 302, а затем учитывает код состояния 404, поэтому вам необходимо убедиться, что вы вернули его на своей странице ошибки.

14 голосов
/ 20 марта 2009

Вы можете использовать web.config для отправки 404 ошибок на пользовательскую страницу.

    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
        <error statusCode="403" redirect="NoAccess.htm" />
        <error statusCode="404" redirect="FileNotFound.htm" />
    </customErrors>
3 голосов
/ 18 апреля 2015

Мне очень нравится этот подход: он создает единое представление для обработки всех типов ошибок и переопределяет IIS.

[1]: удалить все 'customErrors' и 'httpErrors' из Web.config

[2]: проверьте, что 'App_Start / FilterConfig.cs' выглядит следующим образом:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

[3]: в 'Global.asax' добавьте этот метод:

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

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

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

    Response.TrySkipIisCustomErrors = true;
    IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

[4]: ​​добавить 'Controllers / ErrorPageController.cs'

public class ErrorPageController : Controller
{
    public ActionResult Error(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        ViewBag.StatusCode = statusCode + " Error";
        return View();
    }
}

[5]: в 'Views / Shared / Error.cshtml'

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}

 <h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>


//@Model.ActionName
//@Model.ContollerName
//@Model.Exception.Message
//@Model.Exception.StackTrace

: D

3 голосов
/ 25 февраля 2014

Я также столкнулся с 302 вместо 404. Мне удалось исправить это, выполнив следующее:

Контроллер:

public ViewResult Display404NotFoundPage()
        {
            Response.StatusCode = 404;  // this line fixed it.

            return View();
        }

Вид:

Показывать пользователю сообщение об ошибке.

web.config:

<customErrors mode="On"  redirectMode="ResponseRedirect">
      <error statusCode="404" redirect="~/404NotFound/" />
</customErrors>

Наконец, RouthConfig:

routes.MapRoute(
             name: "ErrorPage",
             url: "404NotFound/",
             defaults: new { controller = "Pages", action = "Display404NotFoundPage" }
         );
3 голосов
/ 20 марта 2009

Самый простой ответ: не делайте этого в коде, но настройте IIS вместо .

2 голосов
/ 20 марта 2009

Я вижу, что настройка страницы 404 в web.config - это хороший чистый метод, НО он все еще первоначально отвечает перенаправлением 302 на страницу ошибки. Например, если вы перейдете к:

https://stackoverflow.com/x.aspx

вы будете перенаправлены с помощью перенаправления 302 на:

https://stackoverflow.com/404?aspxerrorpath=/x.aspx

То, что я хочу, это:

http://www.cnn.com/x.aspx

Перенаправления нет. Запрос отсутствующего URL-адреса возвращает код состояния 404 с понятным сообщением об ошибке.

2 голосов
/ 20 марта 2009

Вы используете это где-нибудь?

 Response.Status="404 Page Not Found"
0 голосов
/ 20 марта 2009

Я думаю, что лучший способ - это использовать пользовательскую конструкцию ошибок в вашем файле web.config, как показано ниже, это позволит вам подключать страницы для простой и эффективной обработки всех различных HTTP-кодов.

  <customErrors mode="On" defaultRedirect="~/500.aspx">
     <error statusCode="404" redirect="~/404.aspx" />
     <error statusCode="500" redirect="~/500.aspx" />
  </customErrors>
0 голосов
/ 20 марта 2009

Можно настроить сам IIS для возврата определенных страниц в ответ на любой тип ошибки http (включая 404).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...