エラーを直接ビューではなくErrorControllerで処理します
-
10-07-2019 - |
質問
MVCのエラー処理を回避しようとしています。 私が探しているのは、ネセカリーが他のアクションを実行し、最終的に正しいビューをユーザーに表示する場合、エラーをキャッチし、ログを記録し、可能であれば解決するための集中化された方法です。
このために[HandleError]フィルターを使用できると思いますが、コントローラー/アクションにルーティングする方法がわかりません。私が見る唯一のオプションは、それを直接ビューに向けることです。
解決
HandleErrorAttribute はMVCに付属しています非常に基本的なIExceptionFilter。
あなたが望むと思うことを達成するためのいくつかのオプションがあります。
アクション/コントローラーで[HandleError(Type = typeof(MyException)、View =" ErrorView")]を使用するか、独自に実装することができます
HandleErrorAttribute はそれほど複雑ではありません。このコードをコピーして、要件に合わせて変更することをお勧めします。
OnExceptionオーバーライドにより、ExceptionContextを介して、コントローラー、アクション、ルートデータなど、必要なすべての情報にアクセスできます。
ExceptionHandledを設定することを忘れないでください。次に、filterContext.ResultをErrorControllerとアクションにリダイレクトする新しいRedirectToActionインスタンスに設定できます。明らかに、特定のコントローラーとアクションをプロパティで公開できます。
他のヒント
Leppi、iアクション結果に送信する場合、エラー時にリダイレクトするアクションとコントローラーを定義できます。これは良い例ですが、個人的にはカスタムページやコードへのHTTPコードを使用しないのが好きではありません
これは私のIExtenptionFilterの例です。ベースコントローラーには、制御されていないエラーをすべて処理するためのデフォルトのIExceptionFilterがあります。
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class GenericExceptionHandlerFilter : ActionFilterAttribute, IExceptionFilter
{
public Type ExceptionType { get; set;}
public string RedirectToAction { get; set;}
public string RedirectToController { get; set;}
protected bool ApplyFilter(ExceptionContext filterContext)
{
Type lExceptionType = filterContext.Exception.GetType();
return (ExceptionType == null ||
lExceptionType.Equals(ExceptionType));
}
#region IExceptionFilter Members
public void OnException(ExceptionContext filterContext)
{
if (ApplyFilter(filterContext))
{
IbfControllerLogger.Log(filterContext.Exception);
filterContext.ExceptionHandled = true;
#region Calculate Action Controller Error
RouteValueDictionary lRoutes = new RouteValueDictionary(new
{
action = RedirectToAction,
controller = String.IsNullOrEmpty(RedirectToController) ? (string)filterContext.RouteData.Values["controller"] : RedirectToController
});
UrlReWriterUtils.UrlReWriter(filterContext.Controller.ViewData, lRoutes);
#endregion
filterContext.Controller.TempData[TempDataName.C_TEMPDATA_EXCEPTIONERROR] = filterContext.Exception;
filterContext.Result = new RedirectToRouteResult(lRoutes);
}
}
#endregion
ActionResultから派生した独自のErrorResultを作成しませんか?
私がやっているのは(良いプラクティスかもしれないし、そうでないかもしれない)これは:
エラーが発生した場合:
- 期待して処理できる場合は、ELMAHでログに記録します
- 予想して処理できない場合、ELMAHにログを記録し、エラーページであるViewResultを返します
- エラーの説明、標準メッセージ、私がやっていることへのリンクを含める
- 予想していなかった場合、ベースコントローラークラスのOnErrorのオーバーライドは前のステップを実行します
- 処理できない他のすべてのエラーは、ELMAHおよびリクエストのイエロースクリーンによって自動的に記録されます
一般的なエラー処理のほとんどは、すべてのコントローラーの基本クラスで行われます。唯一の問題は、エラーページでリダイレクト用のActionLinkを生成できるように、ベースクラスでコントローラーとアクションの値を手動で設定する必要があることです。