gpt4 book ai didi

c# - ASP.NET MVC 全局错误处理

转载 作者:可可西里 更新时间:2023-11-01 09:11:13 26 4
gpt4 key购买 nike

我有一个自定义的 HandleError 属性,用于处理 MVC 管道上的错误;我的 Global.asax 上有一个 protected void Application_Error(object sender, EventArgs e) 方法,它处理来自管道外部的错误。

我遇到过一种我不知道可能发生的情况;在实现 DI 时,存在对 connectionString 的依赖,它取自应用程序配置文件。

由于连接字符串还不存在,创建 Controller 时会出现错误,这通常会触发 Application_Error 处理程序,并呈现正确的错误页面(通过将部分 View 呈现为字符串并将其作为响应发送,如果失败,它只会将“致命异常”写入响应。

除了在这种情况下,我得到了错误的默认 ASP.NET“运行时错误”蓝屏死机。告诉我:

Runtime Error

Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed.

Details: To enable the details of this specific error message to be viewable on the local server machine, please create a tag within a "web.config" configuration file located in the root directory of the current web application. This tag should then have its "mode" attribute set to "RemoteOnly". To enable the details to be viewable on remote machines, please set "mode" to "Off".

我的 customErrors 中没有设置 defaultRedirect,也没有关闭 Off,因为我不想重定向但要在用户所在的同一页面上呈现错误,避免不必要的重定向。

我该如何处理这种情况?它以这种方式运行而不像 Controller 外部的任何其他错误的原因甚至是什么?

我知道这不太可能经常发生,但我希望能够停止 YSOD(部分原因是我想隐藏我正在使用的技术,但主要是因为它既不漂亮也不用户友好)

我什至尝试为 UnhandledExceptions 注册一个处理程序,但它也没有触发。

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

最终产生这个的代码是:

返回 ConfigurationManager.ConnectionStrings[key].ConnectionString;,其中 ConnectionStrings[key]null

更新

这是处理应用程序错误的方式:

    protected void Application_Error(object sender, EventArgs e)
{
this.HandleApplicationError(new ResourceController());
}

public static void HandleApplicationError(this HttpApplication application, BaseController controller)
{
if (application == null)
{
throw new ArgumentNullException("application");
}
if (controller == null)
{
throw new ArgumentNullException("controller");
}
application.Response.Clear();
Exception exception = application.Server.GetLastError();
LogApplicationException(application.Response, exception);
try
{
RenderExceptionViewResponse(application, exception, controller);
}
catch (Exception exceptionRenderingView) // now we're in trouble. let's be as graceful as possible.
{
RenderExceptionTextResponse(application, exceptionRenderingView);
}
finally
{
application.Server.ClearError();
}
}

private static void LogApplicationException(HttpResponse response, Exception exception)
{
if (exception is HttpException)
{
HttpException httpException = (HttpException)exception;
if (httpException.GetHttpCode() == (int)HttpStatusCode.NotFound)
{
_log.Debug(Resources.Error.WebResourceNotFound, httpException);
response.Status = Resources.Constants.NotFound;
return;
}
}
_log.Error(Resources.Error.UnhandledException, exception);
}

private static void RenderExceptionViewResponse(HttpApplication application, Exception exception, BaseController controller)
{
if (!RenderAsJsonResponse(application, Resources.User.UnhandledExceptionJson))
{
ErrorViewModel model = WebUtility.GetErrorViewModel(exception);
string result = controller.RenderViewToString(Resources.Constants.ErrorViewName, model);
application.Response.Write(result);
}
}

private static void RenderExceptionTextResponse(HttpApplication application, Exception exceptionRenderingView)
{
application.Response.Clear();

if (!RenderAsJsonResponse(application, Resources.User.FatalExceptionJson))
{
application.Response.Write(Resources.User.FatalException);
}
_log.Fatal(Resources.Error.FatalException, exceptionRenderingView);
}

private static bool RenderAsJsonResponse(HttpApplication application, string message)
{
if (application.Request.IsAjaxRequest())
{
application.Response.Status = Resources.Constants.HttpSuccess;
application.Response.ContentType = Resources.Constants.JsonContentType;
application.Response.Write(message);
return true;
}
return false;
}

这是我用来装饰我的基本 Controller 的属性:

public class ErrorHandlingAttribute : HandleErrorAttribute
{
public Type LoggerType { get; set; }

public ErrorHandlingAttribute()
: this(typeof(ErrorHandlingAttribute))
{
}

public ErrorHandlingAttribute(Type loggerType)
{
LoggerType = loggerType;
}

public override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
{
return;
}
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
OnAjaxException(filterContext);
}
else
{
OnRegularException(filterContext);
}
}

internal protected void OnRegularException(ExceptionContext filterContext)
{
Exception exception = filterContext.Exception;

ILog logger = LogManager.GetLogger(LoggerType);
logger.Error(Resources.Error.UnhandledException, exception);

filterContext.HttpContext.Response.Clear();

ErrorViewModel model = WebUtility.GetErrorViewModel(exception);
filterContext.Result = new ViewResult
{
ViewName = Resources.Constants.ErrorViewName,
ViewData = new ViewDataDictionary(model)
};
filterContext.ExceptionHandled = true;
}

internal protected void OnAjaxException(ExceptionContext filterContext)
{
Exception exception = filterContext.Exception;

ILog logger = LogManager.GetLogger(LoggerType);
logger.Error(Resources.Error.UnhandledAjaxException, exception);

filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.Status = Resources.Constants.HttpSuccess;

string errorMessage = WebUtility.GetUserExceptionMessage(exception, true);

filterContext.Result = new ExceptionJsonResult(new[] { errorMessage });
filterContext.ExceptionHandled = true;
}
}

这是我的customErrors:

<customErrors mode="On" />

如您所见,它们非常广泛,但是在访问 ConnectionStrings 时它们甚至不会触发,而 ConnectionString 不存在;这有点令人费解。

确实在任何包含异常的 Controller 或不在 Controller 内的异常中触发,所以我不明白为什么这种情况有什么不同。

最佳答案

Application_Error 可能是在 ASP.NET WebForms 中处理错误的推荐方法。但不是在 MVC 中。

我们有错误过滤器来为我们处理错误。过滤器的问题在于它仅在调用 Controller 时才起作用。 404 和 401 错误(未找到和授权)和您的数据库连接问题是哪个问题。

customErrors 是前往此处的方式。我不明白为什么重定向应该是个问题?

我正在一篇博客文章中进行正确的错误处理:http://blog.gauffin.org/2011/11/how-to-handle-errors-in-asp-net-mvc/

关于c# - ASP.NET MVC 全局错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9461190/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com