Asp.net

ASP.NET MVC - 如何拋出類似於 StackOverflow 上的 404 頁面

  • October 18, 2011

我目前有一個繼承自System.Web.Mvc.Controller. 在那個類上,我有HandleError將使用者重定向到“500 - 糟糕,我們搞砸了”頁面的屬性。這目前正在按預期工作。

這行得通

<HandleError()> _
Public Class BaseController : Inherits System.Web.Mvc.Controller

''# do stuff
End Class

我也有我的 404 頁面在 Per-ActionResult 基礎上工作,它再次按預期工作。

這行得通

   Function Details(ByVal id As Integer) As ActionResult
       Dim user As Domain.User = UserService.GetUserByID(id)

       If Not user Is Nothing Then
           Dim userviewmodel As Domain.UserViewModel = New Domain.UserViewModel(user)
           Return View(userviewmodel)
       Else
           ''# Because of RESTful URL's, some people will want to "hunt around"
           ''# for other users by entering numbers into the address.  We need to
           ''# gracefully redirect them to a not found page if the user doesn't
           ''# exist.
           Response.StatusCode = CInt(HttpStatusCode.NotFound)
           Return View("NotFound")
       End If

   End Function

同樣,這很好用。如果使用者輸入類似http://example.com/user/999的內容(其中 userID 999 不存在),他們將看到相應的 404 頁面,但 URL 不會更改(他們不會重定向到錯誤頁)。

我無法實現這個想法

這是我遇到問題的地方。如果使用者輸入http://example.com/asdf-他們會被踢到通用 404 頁面。我想要做的是保持 URL 不變(即:不重定向到任何其他頁面),而只是顯示“NotFound”視圖並將其推HttpStatusCode.NotFound送到客戶端。

例如,只需訪問https://stackoverflow.com/asdf,您將在其中看到自定義 404 頁面並查看完整的 URL。

顯然我錯過了一些東西,但我無法弄清楚。由於“asdf”實際上並不指向任何控制器,因此我的基本控制器類沒有啟動,所以我不能在其中的“HandleError”過濾器中執行此操作。

在此先感謝您的幫助。

注意:我絕對不想將使用者重定向到 404 頁面。我希望他們留在現有的 URL,並且我希望 MVC 將 404 VIEW 推送給使用者。

編輯:

我也嘗試了以下無濟於事。

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
   routes.RouteExistingFiles = False
   routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
   routes.IgnoreRoute("Assets/{*pathInfo}")
   routes.IgnoreRoute("{*robotstxt}", New With {.robotstxt = "(.*/)?robots.txt(/.*)?"})

   routes.AddCombresRoute("Combres")

   ''# MapRoute allows for a dynamic UserDetails ID
   routes.MapRouteLowercase("UserProfile", _
       "Users/{id}/{slug}", _
       New With {.controller = "Users", .action = "Details", .slug = UrlParameter.Optional}, _
       New With {.id = "\d+"} _
   )


   ''# Default Catch All Valid Routes
   routes.MapRouteLowercase( _
       "Default", _
       "{controller}/{action}/{id}/{slug}", _
       New With {.controller = "Events", .action = "Index", .id = UrlParameter.Optional, .slug = UrlParameter.Optional} _
   )

   ''# Catch All InValid (NotFound) Routes
   routes.MapRoute( _
       "NotFound", _
       "{*url}", _
       New With {.controller = "Error", .action = "NotFound"})

End Sub

我的“未找到”路線什麼也沒做。

在我的另一個 SO question 上找到了我的答案。非常感謝Anh-Kiet Ngo的解決方案。

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

   // A good location for any error logging, otherwise, do it inside of the error controller.

   Response.Clear();
   HttpException httpException = exception as HttpException;
   RouteData routeData = new RouteData();
   routeData.Values.Add("controller", "YourErrorController");

   if (httpException != null)
   {
       if (httpException.GetHttpCode() == 404)
       {
           routeData.Values.Add("action", "YourErrorAction");

           // We can pass the exception to the Action as well, something like
           // routeData.Values.Add("error", exception);

           // Clear the error, otherwise, we will always get the default error page.
           Server.ClearError();

           // Call the controller with the route
           IController errorController = new ApplicationName.Controllers.YourErrorController();
           errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
       }
   }
}

引用自:https://stackoverflow.com/questions/3431211