Web.configに次のものがあります。
<customErrors mode="On" defaultRedirect="Error">
<error statusCode="404" redirect="Error/NotFound" />
</customErrors>
私は
[HandleError]
私のHomeControllerクラスの一番上にあります。テストするために、単に例外をスローするアクションを作成して実行します。 。そしてそれは私のにリダイレクトします
ErrorController/Index
メソッドですが、HandleErrorInfoにバインドするビューに到達すると、モデルがnullになるため、エラーへの参照が失われました。
リダイレクトでエラーが失われることに関係していると確信しているので、何かが足りないかどうか、スタックトレースとエラーメッセージを表示するビューを表示できる提案があるかどうかを確認したいと思いました。
誤解が見えます。コントローラーアクションに対してMVC
とredirect
を実行します。
ただし、defaultRedirect
自体は_Web Form
_規則であるため、制限されます。別のコントローラーにリダイレクトすると、HttpContext
が失われ、それによってHandleErrorInfo
オブジェクトが失われます。
_[HandleError]
_属性には、エラーメッセージを送信するためのView
が必要です。上記の例では、ErrorController
用の_Views/Error
_フォルダーがあり、その中にIndex
ビューがあると仮定します。フィルタコンテキストでHandleErrorInfo
オブジェクトをそのビューに送信する場合は、
この構文を試してください:
_[HandleError(View="~/Views/Error/Index")]
Public class HomeController : Controller
_
しかし、ロギングはどうですか?!?!?
あなたの意図は、単にエラースタックをユーザーに表示するだけではなく、moreだと思います。実際、あなたにはそのような意図はまったくないと思います。私はあなたの本当の目的があなたのエラーを(おそらくdbに)記録し、あなたのユーザーにいくつかの当たり障りのないメッセージを表示することであると思います。
これまで説明してきたのは、「私のビューで未処理の例外を表示するのに最適な方法」でした。 _[HandleError]
_属性はそのために適しています。
ただし、次のステップ(エラーのログ記録)に移動する場合は、いくつかのオプションがあります。
1) ベースコントローラーのOn Exceptionメソッドをオーバーライドします ; MVCコントローラークラスから継承する独自のController
を作成しますが、OnExceptionメソッドをオーバーライドします。このアプローチは、[HandleError]属性と組み合わせて使用できます。
2) カスタム例外ハンドラーを作成します エラーをログに記録する独自の例外ハンドラーを作成します。例外ハンドラーは、選択したビューを呼び出すか、[HandleError(order=2)]
と連携して機能できます。これは、フィルター属性が優先順位を適用する順序引数を取ることができるためです。
Nitin Sawantは、エラービューがどのようになるかを尋ねます。ザ・
_@model System.Web.Mvc.HandleErrorInfo
<h2>Exception details</h2>
<p> Controller: @Model.ControllerName </p>
<p> Action: @Model.ActionName </p>
<p> Exception: @Model.Exception </p>
_
すべてのエラー(HandleError属性を持つコントローラーで発生するエラーだけでなく)を処理するmaxlegoと同様のことを行います。
私のMvcApplicationクラス(global.asax.cs内)には次のものがあります。
public class MvcApplication : HttpApplication
{
// usual stuff here...
protected void Application_Error(object sender, EventArgs e)
{
Server.HandleError(((MvcApplication)sender).Context);
}
}
上記のコードは、便利なもののMVCライブラリからの拡張メソッドを使用しています。これが適切に配置されていれば、エラー処理属性、customErrors構成、またはカスタムフィルターは必要ありません。代わりに、拡張メソッドはエラーの詳細をログに記録してから、次のいずれかの適切なビューを呼び出します。
これを機能させるための拡張メソッドコードは次のとおりです。
public static class HttpServerUtilityExtensions
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void HandleError(this HttpServerUtility server, HttpContext httpContext)
{
var currentController = " ";
var currentAction = " ";
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData != null)
{
if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
currentController = currentRouteData.Values["controller"].ToString();
if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
currentAction = currentRouteData.Values["action"].ToString();
}
var exception = server.GetLastError();
Logger.ErrorException(exception.Message, exception);
var controller = DependencyResolver.Current.GetService<ErrorController>();
var routeData = new RouteData();
var action = "InternalServerError";
if (exception is HttpException)
{
var httpEx = exception as HttpException;
switch (httpEx.GetHttpCode())
{
case 404:
action = "NotFound";
break;
case 401:
action = "AccessDenied";
break;
}
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = exception is HttpException ? ((HttpException)exception).GetHttpCode() : 500;
httpContext.Response.TrySkipIisCustomErrors = true;
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
controller.ViewData.Model = new HandleErrorInfo(exception, currentController, currentAction);
((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
}
上記はエラーの詳細をログに記録するためにNLogを使用していますが、他の何かをサポートするために簡単に変更できることに注意してください。また、このメソッドは、ErrorControllerを解決するときにIoCコンテナを尊重します。
この小さなコードを使用して、ユーザーが処理したエラーページを表示しました。ページが見つからなかったか、その他のエラーが発生したかどうか。
void Application_Error(object sender, EventArgs e)
{
// this value can be fetched from config or depend on DEBUG smybol
if (!handleErrors)
return;
var error = Server.GetLastError();
var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;
if (code == 404)
{
// do something if page was not found. log for instance
}
else
{
// collect request info and log exception
}
// pass exception to ErrorsController
Request.RequestContext.RouteData.Values["ex"] = error;
// execute controller action
IController errorController = new ErrorsController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), Request.RequestContext.RouteData));
}
そして、エラーコントローラは次のようになります。詳細な例外が必要な場合は、RouteDataからアクセスできます
public class ErrorsController : Controller
{
/// <summary>
/// Page not found
/// </summary>
/// <returns></returns>
public ActionResult Http404()
{
return View();
}
/// <summary>
/// All other errors
/// </summary>
/// <param name="actionName"></param>
protected override void HandleUnknownAction(string actionName)
{
// in case detailed exception is required.
var ex = (Exception) RouteData.Values["ex"];
return View();
}
}
Httpコードごとに異なるビューを追加できます。アクションHttp {Code}を実装するだけです