Ошибки регистрации в ASP.NET MVC
В настоящее время я использую log4net в своем приложении ASP.NET MVC для регистрации исключений. То, как я это делаю, заключается в том, что все мои контроллеры наследуются от класса BaseController. В событии BaseController OnActionExecuting я регистрирую любые исключения, которые могли произойти:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Log any exceptions
ILog log = LogManager.GetLogger(filterContext.Controller.GetType());
if (filterContext.Exception != null)
{
log.Error("Unhandled exception: " + filterContext.Exception.Message +
". Stack trace: " + filterContext.Exception.StackTrace,
filterContext.Exception);
}
}
Это отлично работает, если во время действия контроллера произошло необработанное исключение.
Что касается ошибок 404, у меня есть собственная ошибка, настроенная в моем web.config так:
<customErrors mode="On">
<error statusCode="404" redirect="~/page-not-found"/>
</customErrors>
И в действии контроллера, который обрабатывает URL-адрес, который не был найден, я регистрирую исходный URL-адрес:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult PageNotFound()
{
log.Warn("404 page not found - " + Utils.SafeString(Request.QueryString["aspxerrorpath"]));
return View();
}
И это также работает.
Проблема, с которой я столкнулась, заключается в том, как регистрировать ошибки, которые находятся на самих страницах .aspx. Скажем, у меня есть ошибка компиляции на одной из страниц или какой-то встроенный код, который выдает исключение:
<% ThisIsNotAValidFunction(); %>
<% throw new Exception("help!"); %>
Похоже, что атрибут HandleError правильно перенаправляет это на мою страницу Error.aspx в общей папке, но это определенно не улавливается моим методом BaseAontroller OnActionExecuted. Я думал, что мог бы поставить код регистрации на самой странице Error.aspx, но я не уверен, как получить информацию об ошибках на этом уровне.
Ответы
Ответ 1
Я бы рассмотрел упрощение вашего веб-приложения, подключив Elmah.
Вы добавляете сборку Elmah в свой проект, а затем настраиваете свой web.config. Затем будут регистрироваться исключения, созданные на уровне контроллера или страницы. Его можно настроить для входа в различные места (например, SQL Server, электронная почта и т.д.). Он также предоставляет веб-интерфейс, чтобы вы могли просматривать журнал исключений.
Его первое, что я добавляю к любому приложению asp.net mvc, которое я создаю.
Я все еще использую log4net, но я использую его для регистрации debug/info и оставляю все исключения для Elmah.
Вы также можете найти дополнительную информацию в вопросе Как вы регистрируете ошибки (исключения) в своих приложениях ASP.NET?.
Ответ 2
Вы можете подключиться к событию OnError в Global.asax.
Что-то вроде этого:
/// <summary>
/// Handles the Error event of the Application control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Application_Error(object sender, EventArgs e)
{
if (Server != null)
{
Exception ex = Server.GetLastError();
if (Response.StatusCode != 404 )
{
Logging.Error("Caught in Global.asax", ex);
}
}
}
Ответ 3
MVC3
Создайте атрибут, который наследуется от HandleErrorInfoAttribute и включает ваш выбор ведения журнала
public class ErrorLoggerAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
LogError(filterContext);
base.OnException(filterContext);
}
public void LogError(ExceptionContext filterContext)
{
// You could use any logging approach here
StringBuilder builder = new StringBuilder();
builder
.AppendLine("----------")
.AppendLine(DateTime.Now.ToString())
.AppendFormat("Source:\t{0}", filterContext.Exception.Source)
.AppendLine()
.AppendFormat("Target:\t{0}", filterContext.Exception.TargetSite)
.AppendLine()
.AppendFormat("Type:\t{0}", filterContext.Exception.GetType().Name)
.AppendLine()
.AppendFormat("Message:\t{0}", filterContext.Exception.Message)
.AppendLine()
.AppendFormat("Stack:\t{0}", filterContext.Exception.StackTrace)
.AppendLine();
string filePath = filterContext.HttpContext.Server.MapPath("~/App_Data/Error.log");
using(StreamWriter writer = File.AppendText(filePath))
{
writer.Write(builder.ToString());
writer.Flush();
}
}
Поместите атрибут в Global.asax RegisterGlobalFilters
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// filters.Add(new HandleErrorAttribute());
filters.Add(new ErrorLoggerAttribute());
}
Ответ 4
Задумывались ли вы о расширении атрибута HandleError? Кроме того, у Скотта есть хорошая запись в блоге о фильтрах-перехватчиках на контроллерах/действиях здесь.
Ответ 5
Вы можете попробовать изучить HttpContext.Error, но я не уверен в этом.
Ответ 6
Представление Error.aspx определяется следующим образом:
namespace MvcApplication1.Views.Shared
{
public partial class Error : ViewPage<HandleErrorInfo>
{
}
}
В HandleErrorInfo есть три свойства:
string ActionName
string Имя контроллера
Исключение исключений
Вы должны иметь доступ к HandleErrorInfo и, следовательно, к исключению в представлении.