これは、不正なコントローラ名、不正なルート名、およびアクションメソッド内に適合すると思われるその他の基準へのリクエストを処理できるMVCツールを使用した別のメソッドです。個人的には、302/200リダイレクトを実行Server.Transfer
し、Razorビューを使用したResponseRewrite()をサポートしないため、できるだけ多くのweb.config設定を回避することを好みます。SEOの理由から、カスタムエラーページを含む404を返したいと思います。
これの一部は、上記のcottsakの手法の新しい見方です。
このソリューションでは、代わりにMVC 3エラーフィルターを優先する最小限のweb.config設定も使用します。
使用法
アクションまたはカスタムActionFilterAttributeからHttpExceptionをスローするだけです。
Throw New HttpException(HttpStatusCode.NotFound, "[Custom Exception Message Here]")
ステップ1
次の設定をweb.configに追加します。これは、MVCのHandleErrorAttributeを使用するために必要です。
<customErrors mode="On" redirectMode="ResponseRedirect" />
ステップ2
HTTPエラーを除いて、MVCフレームワークのHandleErrorAttributeと同様のカスタムHandleHttpErrorAttributeを追加します。
<AttributeUsage(AttributeTargets.All, AllowMultiple:=True)>
Public Class HandleHttpErrorAttribute
Inherits FilterAttribute
Implements IExceptionFilter
Private Const m_DefaultViewFormat As String = "ErrorHttp{0}"
Private m_HttpCode As HttpStatusCode
Private m_Master As String
Private m_View As String
Public Property HttpCode As HttpStatusCode
Get
If m_HttpCode = 0 Then
Return HttpStatusCode.NotFound
End If
Return m_HttpCode
End Get
Set(value As HttpStatusCode)
m_HttpCode = value
End Set
End Property
Public Property Master As String
Get
Return If(m_Master, String.Empty)
End Get
Set(value As String)
m_Master = value
End Set
End Property
Public Property View As String
Get
If String.IsNullOrEmpty(m_View) Then
Return String.Format(m_DefaultViewFormat, Me.HttpCode)
End If
Return m_View
End Get
Set(value As String)
m_View = value
End Set
End Property
Public Sub OnException(filterContext As System.Web.Mvc.ExceptionContext) Implements System.Web.Mvc.IExceptionFilter.OnException
If filterContext Is Nothing Then Throw New ArgumentException("filterContext")
If filterContext.IsChildAction Then
Return
End If
If filterContext.ExceptionHandled OrElse Not filterContext.HttpContext.IsCustomErrorEnabled Then
Return
End If
Dim ex As HttpException = TryCast(filterContext.Exception, HttpException)
If ex Is Nothing OrElse ex.GetHttpCode = HttpStatusCode.InternalServerError Then
Return
End If
If ex.GetHttpCode <> Me.HttpCode Then
Return
End If
Dim controllerName As String = filterContext.RouteData.Values("controller")
Dim actionName As String = filterContext.RouteData.Values("action")
Dim model As New HandleErrorInfo(filterContext.Exception, controllerName, actionName)
filterContext.Result = New ViewResult With {
.ViewName = Me.View,
.MasterName = Me.Master,
.ViewData = New ViewDataDictionary(Of HandleErrorInfo)(model),
.TempData = filterContext.Controller.TempData
}
filterContext.ExceptionHandled = True
filterContext.HttpContext.Response.Clear()
filterContext.HttpContext.Response.StatusCode = Me.HttpCode
filterContext.HttpContext.Response.TrySkipIisCustomErrors = True
End Sub
End Class
ステップ3
のGlobalFilterCollection(GlobalFilters.Filters
)にフィルタを追加しGlobal.asax
ます。この例では、すべてのInternalServerError(500)エラーをError共有ビュー(Views/Shared/Error.vbhtml
)にルーティングします。NotFound(404)エラーは、共有ビューのErrorHttp404.vbhtmlにも送信されます。ここに401エラーを追加して、これを追加のHTTPエラーコードに拡張する方法を示します。これらは共有ビューでなければならず、すべてSystem.Web.Mvc.HandleErrorInfo
オブジェクトをモデルとして使用することに注意してください。
filters.Add(New HandleHttpErrorAttribute With {.View = "ErrorHttp401", .HttpCode = HttpStatusCode.Unauthorized})
filters.Add(New HandleHttpErrorAttribute With {.View = "ErrorHttp404", .HttpCode = HttpStatusCode.NotFound})
filters.Add(New HandleErrorAttribute With {.View = "Error"})
ステップ4
基本コントローラークラスを作成し、それをコントローラーで継承します。この手順により、不明なアクション名を処理し、HTTP 404エラーをHandleHttpErrorAttributeに発生させることができます。
Public Class BaseController
Inherits System.Web.Mvc.Controller
Protected Overrides Sub HandleUnknownAction(actionName As String)
Me.ActionInvoker.InvokeAction(Me.ControllerContext, "Unknown")
End Sub
Public Function Unknown() As ActionResult
Throw New HttpException(HttpStatusCode.NotFound, "The specified controller or action does not exist.")
Return New EmptyResult
End Function
End Class
手順5
ControllerFactoryオーバーライドを作成し、Application_StartのGlobal.asaxファイルでオーバーライドします。この手順により、無効なコントローラー名が指定された場合にHTTP 404例外を発生させることができます。
Public Class MyControllerFactory
Inherits DefaultControllerFactory
Protected Overrides Function GetControllerInstance(requestContext As System.Web.Routing.RequestContext, controllerType As System.Type) As System.Web.Mvc.IController
Try
Return MyBase.GetControllerInstance(requestContext, controllerType)
Catch ex As HttpException
Return DependencyResolver.Current.GetService(Of BaseController)()
End Try
End Function
End Class
'In Global.asax.vb Application_Start:
controllerBuilder.Current.SetControllerFactory(New MyControllerFactory)
手順6
BaseController UnknownアクションのRoutTable.Routesに特別なルートを含めます。これは、ユーザーが不明なコントローラーや不明なアクションにアクセスした場合に404を発生させるのに役立ちます。
'BaseController
routes.MapRoute( _
"Unknown", "BaseController/{action}/{id}", _
New With {.controller = "BaseController", .action = "Unknown", .id = UrlParameter.Optional} _
)
概要
この例では、MVCフレームワークを使用して、フィルター属性と共有エラービューを使用したリダイレクトを行わずに404 Httpエラーコードをブラウザーに返す方法を示しました。また、無効なコントローラー名とアクション名が指定されたときに同じカスタムエラーページを表示する方法も示しています。
無効なコントローラー名、アクション名、およびHome / TriggerNotFoundアクションから生成されたカスタム404のスクリーンショットを追加します。このソリューションを使用して次のURLにアクセスすると、Fiddlerが404メッセージを返します。
/InvalidController
/Home/InvalidRoute
/InvalidController/InvalidRoute
/Home/TriggerNotFound
上記のcottsakの投稿とこれらの記事は良い参考文献でした。