エラーが発生したときに実行され、エラーの詳細を自分にメールで送信するglobal.asax
ファイルのApplication_Error
イベントにコードがあります。
void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
if (error.Message != "Not Found")
{
// Send email here...
}
}
Visual Studioで実行している場合、これは正常に機能しますが、ライブサーバーに発行するとApplication_Error
イベントは発生しません。
いくつかのテストの後、Application_Error
を設定するとcustomErrors="Off"
が発生しますが、customErrors="On"
に戻すと、イベントは再び発生しなくなります。
Application_Error
でcustomErrors
が有効になっているときにweb.config
が起動しない理由を提案できますか?
[〜#〜] update [〜#〜]
この回答は解決策を提供するので、それを編集しませんが、この問題を解決するはるかにクリーンな方法を見つけました。詳細については my other answer を参照してください...
元の答え:Application_Error()
メソッドが呼び出されない理由を見つけました...
Global.asax.cs
_public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); // this line is the culprit
}
...
}
_
デフォルトでは(新しいプロジェクトが生成されるとき)、MVCアプリケーションは_Global.asax.cs
_ファイルにいくつかのロジックを持っています。このロジックは、ルートのマッピングとフィルターの登録に使用されます。デフォルトでは、HandleErrorAttribute
フィルターという1つのフィルターのみを登録します。 customErrorsがオンの場合(またはRemoteOnlyに設定されている場合はリモート要求を介して)、HandleErrorAttributeはMVCにエラービューを探すように指示し、Application_Error()
メソッドを呼び出しません。このドキュメントは見つかりませんでしたが、 programmers.stackexchange.comでのこの回答 で説明されています。
every未処理の例外を呼び出すApplicationError()メソッドを取得するには、HandleErrorAttributeフィルターを登録する行を削除します。
問題は次のとおりです:customErrorsを設定して、必要なものを取得する方法...
CustomErrorsセクションのデフォルトは_redirectMode="ResponseRedirect"
_です。 defaultRedirect属性をMVCルートとして指定することもできます。私は非常にシンプルなErrorControllerを作成し、web.configを次のように変更しました...
web.config
_<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
_
このソリューションの問題は、エラーURLに302リダイレクトを行い、それらのページが200ステータスコードで応答することです。これにより、Googleはエラーページのインデックスを作成しますが、これは不適切です。また、HTTP仕様にあまり準拠していません。私がやりたかったのはリダイレクトではなく、カスタムエラービューで元の応答を上書きしました。
_redirectMode="ResponseRewrite"
_を変更しようとしました。残念ながら、 このオプションはMVCルートをサポートしません 、静的HTMLページまたはASPXのみです。最初は静的なHTMLページを使用しようとしましたが、応答コードはまだ200でしたが、少なくともリダイレクトされませんでした。それから私は この答え ...からアイデアを得た.
エラー処理のためにMVCをあきらめることにしました。 _Error.aspx
_と_PageNotFound.aspx
_を作成しました。これらのページは非常にシンプルでしたが、1つの魔法がありました...
_<script type="text/C#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
}
</script>
_
このブロックは、ページに正しいステータスコードを提供するよう指示します。おおまかに言って、PageNotFound.aspxページでは、代わりに_HttpStatusCode.NotFound
_を使用しました。 web.configを次のように変更しました...
_<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
_
すべて完璧に機能しました!
要約:
filters.Add(new HandleErrorAttribute());
Application_Error()
メソッドを使用して例外をログに記録しますこのソリューションには、いくつかの欠点があります。
これらの問題には回避策がありますが、余分な作業を行うほど心配していませんでした。
これが皆さんのお役に立てば幸いです!
ExceptionFilterを作成し、Application_Errorの代わりにエラーをログに記録することでこれを解決しました。必要なのは、RegisterGlobalFiltersにinの呼び出しを追加することだけです
log4netExceptionFilter.cs
using System
using System.Web.Mvc;
public class log4netExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
Exception ex = context.Exception;
if (!(ex is HttpException)) //ignore "file not found"
{
//Log error here
}
}
}
Global.asax.cs
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new log4netExceptionFilter()); //must be before HandleErrorAttribute
filters.Add(new HandleErrorAttribute());
}
記事 を見つけました。これは、例外をログに記録する機能を妨げないMVC3 Webアプリでカスタムエラーページを作成するはるかにクリーンな方法を説明しています。
解決策は、<httpErrors>
セクションの <system.webServer>
要素を使用することです。
私はWeb.configをそのように設定しました...
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
<error statusCode="500" path="/Error" responseMode="ExecuteURL" />
</httpErrors>
また、customErrors
をmode="Off"
を持つように構成しました(記事で提案されているとおり)。
これにより、ErrorControllerのアクションによって応答がオーバーライドされます。そのコントローラーは次のとおりです。
public class ErrorController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult NotFound()
{
return View();
}
}
ビューは非常に単純で、標準のRazor構文を使用してページを作成しました。
MVCでカスタムエラーページを使用するには、それだけで十分です。
また、例外のログが必要だったので、カスタムExceptionFilterを使用する Markのソリューション を盗みました...
public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext exceptionContext)
{
var exception = exceptionContext.Exception;
var request = exceptionContext.HttpContext.Request;
// log stuff
}
}
最後に行う必要があるのは、Global.asax.csファイルに例外フィルターを登録することです。
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ExceptionPublisherExceptionFilter());
filters.Add(new HandleErrorAttribute());
}
これは、以前の回答よりもはるかにクリーンなソリューションのように感じられ、私が知る限りではうまく機能します。 MVCフレームワークと戦っている気がしなかったので、特に気に入っています。このソリューションは実際にそれを活用しています!
ASP.NET MVC5の場合
public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
public void OnException(ExceptionContext exceptionContext)
{
var exception = exceptionContext.Exception;
var request = exceptionContext.HttpContext.Request;
// HttpException httpException = exception as HttpException;
// Log this exception with your logger
_logger.Error(exception.Message);
}
}
FilterConfig.cs
のApp_Start
フォルダーにあります。
ExceptionFilterを使用したMarkの答えは気に入っていますが、すべてのコントローラーが同じベースコントローラーから派生している場合は、ベースコントローラーでOnExceptionをオーバーライドするだけです。ロギングと電子メール送信をそこで行うことができます。これには、既にIoCコンテナーを使用してベースコントローラーに注入した依存関係を使用できるという利点があります。
IExceptionFilterでIoCを使用することはできますが、バインディングを構成するのは少し複雑です。
これを回避するために、customerrorsを無効にして、global.asaxのApplication_Errorイベントからのすべてのエラーを処理することになりました。 301リダイレクトを返したくなかったため、MVCでは少し注意が必要で、適切なエラーコードを返しました。詳細については、私のブログの http://www.wduffy.co.uk/blog/using-application_error-in-asp-net-mvcs-global-asax-to-をご覧ください。 handle-errors / しかし、最終的なコードは以下にリストされています...
void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;
if (code != 404)
{
// Generate email with error details and send to administrator
}
Response.Clear();
Server.ClearError();
string path = Request.Path;
Context.RewritePath(string.Format("~/Errors/Http{0}", code), false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(Context);
Context.RewritePath(path, false);
}
そして、ここにコントローラーがあります
public class ErrorsController : Controller
{
[HttpGet]
public ActionResult Http404(string source)
{
Response.StatusCode = 404;
return View();
}
[HttpGet]
public ActionResult Http500(string source)
{
Response.StatusCode = 500;
return View();
}
}
Application_Error()
がヒットしなかった同じ問題を抱えていました。私はすべてを試しましたが、最終的には何が起こっているのかを確認しました。 ELMAHイベントに、送信する電子メールにJSONを追加するカスタムコードがあり、そこにnullエラーがありました!
内部エラーを修正することで、コードは予想どおりApplication_Error()
イベントに進むことができました。
このブログエントリは私を助けてくれました:
http://asp-net.vexedlogic.com/2011/04/23/asp-net-maximum-request-length-exceeded/
IIS 7.0以上を使用している場合、Web.configファイルを変更して、大きすぎる要求を処理できます。いくつかの注意事項がありますが、以下に例を示します。
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1048576" />
</requestFiltering>
</security>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="13" />
<error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="/UploadTooLarge.htm" responseMode="Redirect" />
</httpErrors>
</system.webServer>
これらの構成ファイル要素に関する追加の詳細がここにあります:
http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering/requestLimits
ステータスコード404.13は、「Content Length Too Large」として定義されています。注意すべき重要な点は、maxAllowedContentLength
がバイト単位で指定されることです。これは、キロバイト単位で指定される<system.web>
セクションにあるmaxRequestLength
設定とは異なります。
<system.web>
<httpRuntime maxRequestLength="10240" />
</system.web>
また、path
がresponseMode
の場合、Redirect
属性は絶対パスである必要があるため、必要に応じて仮想ディレクトリ名を追加します。 Jesse Webbの有益な回答は、responseMode="ExecuteURL"
を使用してこれを行う方法を示しており、そのアプローチもうまくいくと思います。
Visual Studio開発サーバー(Cassini、Visual Studioに統合されたWebサーバー)を使用して開発している場合、このアプローチは機能しません。私はそれがIIS Expressで動作すると仮定していますが、私はそれをテストしていません。
私が知る限り、urlパラメーターで指定されたページに制御を渡しているので、Application_Errorではなく、イベント通知がここに置かれます。
<customErrors defaultRedirect="myErrorPage.aspx"
mode="On">
</customErrors>
多くの情報がここにあります: http://support.Microsoft.com/kb/306355