我尝试在我的asp.net mvc 5应用程序中使用我一直使用的相同技术实现自定义错误处理:
protected void Application_Error(object sender, EventArgs e)
{
try
{
HandleApplicationErrors();
Response.TrySkipIisCustomErrors = true;
}
catch(Exception ex)
{
Response.Write(ex.ToString());
Response.StatusCode = 500;
}
}
private void HandleApplicationErrors(int? statusCode = null)
{
try
{
Exception ex = Server.GetLastError();
Response.Clear();
HttpException httpEx = ex as HttpException;
if (statusCode == null && httpEx != null) statusCode = httpEx.GetHttpCode();
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
switch (statusCode)
{
case 404:
routeData.Values.Add("action", "NotFound");
break;
case 403:
routeData.Values.Add("action", "Forbidden");
break;
default:
routeData.Values.Add("action", "ServerError");
break;
}
routeData.Values.Add("exception", ex);
Server.ClearError();
this.Server.ClearError();
this.Response.TrySkipIisCustomErrors = true;
IController controller = new ErrorController();
controller.Execute(new RequestContext(new HttpContextWrapper(this.Context), routeData));
}
catch(Exception ex)
{
Response.Write(ex.ToString());
Response.StatusCode = 500;
}
}
过去这种方法运行得很好,但是在这个应用程序中,我使用的是Autofac,并且无法解决实例,并且无法从此LifetimeScope创建嵌套生命周期它已被处理掉了。"在控制器上。执行线。我已经尝试将ErrorController从autofac注册中排除(它还没有构造函数参数)并直接构造它。
控制器代码非常简单:
private CustomErrorModel GetModel(Exception ex)
{
var model = new CustomErrorModel();
model.RequestedUrl = Request.Url.OriginalString;
model.ReferrerUrl = (Request.UrlReferrer == null || model.RequestedUrl == Request.UrlReferrer.OriginalString) ? null : Request.UrlReferrer.OriginalString;
model.Exception = ex;
return model;
}
public ActionResult ServerError(Exception ex)
{
var model = GetModel(ex);
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
Response.Status = "500 Internal Server Error";
return View(model);
}
任何人都有任何想法让这项工作?
答案 0 :(得分:1)
好的,在这里回答我自己的问题。我看了一下堆栈跟踪,看起来异常是由mvc尝试使用容器来查找模型绑定器引起的。所以我使我的操作方法无参数并且解决了它!
在此处发布代码供参考:
protected void Application_Error(object sender, EventArgs e)
{
try
{
HandleApplicationErrors();
Response.TrySkipIisCustomErrors = true;
}
catch(Exception ex)
{
Response.Write(ex.ToString());
Response.StatusCode = 500;
}
}
private void HandleApplicationErrors(int? statusCode = null)
{
try
{
Exception ex = Server.GetLastError();
Response.Clear();
HttpException httpEx = ex as HttpException;
if (statusCode == null && httpEx != null) statusCode = httpEx.GetHttpCode();
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
switch (statusCode)
{
case 404:
routeData.Values.Add("action", "NotFound");
break;
case 403:
routeData.Values.Add("action", "Forbidden");
break;
default:
routeData.Values.Add("action", "ServerError");
break;
}
//routeData.Values.Add("exception", ex);
Server.ClearError();
this.Server.ClearError();
this.Response.TrySkipIisCustomErrors = true;
IController controller = new ErrorController();
controller.Execute(new RequestContext(new HttpContextWrapper(this.Context), routeData));
}
catch(Exception ex)
{
Response.Write(ex.ToString());
Response.StatusCode = 500;
}
}
和我的控制器方法:
public ActionResult ServerError()
{
HttpException ex = Server.GetLastError() as HttpException;
var model = GetModel(ex);
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
Response.Status = "500 Internal Server Error";
return View(model);
}
答案 1 :(得分:1)
我在我的应用程序中做了类似的事情,包括使用Autofac进行依赖注入,并且没有遇到与您相同的问题。
仔细查看您的HandleApplicationErrors
方法,我发现您的路由数据与您的ServerError
操作所期望的参数不匹配。
在HandleApplicationErrors
中,您传递的参数名为 exception
在ServerError
中,您需要一个名为 ex
的参数
更新路线数据的设置以匹配:
routeData.Values.Add("ex", ex);
将解决问题。
答案 2 :(得分:0)
"请求生存期本身在EndRequest事件中处理。您 可以在添加的RequestLifetimeHttpModule中看到这一点 引用MVC集成时自动进入管道。 很可能存在Autofac事件处理程序的竞争条件 在您自己的EndRequest事件处理程序之前触发。这是最多的 现在可能只是因为最近的Autofac集成而出现 试图使模块等的注册更加无缝 开发人员,所以我们在预应用程序启动时注册模块。我们 首先订阅该事件,因此我们首先调用。
不幸的是,从那里开始真的没什么可做的 Autofac方面 - EndRequest是管道中的最后一个事件 必须处理生命范围,以便它发生在哪里。
如果您在EndRequest处理需要解决的问题, 可能为时已晚。即使在之前的集成中,EndRequest也会如此 一直是个风险。例如,如果您解析了一个对象 实现IDisposable,释放生命周期范围 EndRequest将丢弃该对象,并且您正在处理该对象 物体处于不良状态。
我建议您尝试将操作的执行时间移至某个时间 在EndRequest之前。或者,如果你100%确定 链中的对象不具有IDisposable,您可以解析该对象 在较早的事件中,将其存储在HttpContext.Items中,并检索它 从那里开始在你的EndRequest处理程序中使用。"