这是我的设置。它不会重定向并且可以处理应用程序和一些已配置的IIS错误。您还可以将任何信息传递给您的错误控制器。
在Web.config中:
<system.web>
<customErrors mode="Off" />
...
</system.web>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Auto">
<remove statusCode="403" />
<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/Display/403" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/Display/404" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error/Display/500" />
</httpErrors>
...
</system.webServer>
在
ErrorController 中(仅显示方法签名以简洁为要):
public ActionResult Index(Exception exception)
{
...
}
public ActionResult Display([Bind(Prefix = "id")] HttpStatusCode statusCode)
{
...
}
此外,我有一个
ErrorViewModel
和一个
Index
视图。
在Application_Error中:
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
var httpContext = new HttpContextWrapper(Context);
httpContext.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "Error";
routeData.Values["action"] = "Index";
routeData.Values["exception"] = exception;
IController errorController = DependencyResolver.Current.GetService<ErrorController>();
var context = new RequestContext(httpContext, routeData);
errorController.Execute(context);
}
到目前为止,这是我所拥有的基本设置。它不会执行重定向(错误控制器操作从Application_Error中执行),并且处理控制器异常以及例如IIS 404(例如yourwebsite.com/blah.html)。
从这一点开始,您的ErrorController内发生的任何事情都将基于您的需求。
作为一个例子,我将添加一些关于我的实现的额外细节。就像我所说的那样,我有一个
ErrorViewModel
。
我的
ErrorViewModel:
public class ErrorViewModel
{
public string Title { get; set; }
public string Text { get; set; }
public string ContentResourceKey { get; set; }
public Exception Exception { get; set; }
}
我的
ErrorController(相关部分):
public ActionResult Index(Exception exception)
{
ErrorViewModel model;
var statusCode = HttpStatusCode.InternalServerError;
if (exception is HttpException)
{
statusCode = (HttpStatusCode)(exception as HttpException).GetHttpCode();
if (exception is DisplayableException)
{
model = CreateErrorModel(exception as DisplayableException);
}
else
{
model = CreateErrorModel(statusCode);
model.Exception = exception;
}
}
else
{
model = new ErrorViewModel { Exception = exception };
}
return ErrorResult(model, statusCode);
}
public ActionResult Display([Bind(Prefix = "id")] HttpStatusCode statusCode)
{
var model = CreateErrorModel(statusCode);
return ErrorResult(model, statusCode);
}
private ErrorViewModel CreateErrorModel(HttpStatusCode statusCode)
{
var model = new ErrorViewModel();
switch (statusCode)
{
case HttpStatusCode.NotFound:
model.ContentResourceKey = "error-page-404";
break;
case HttpStatusCode.Forbidden:
model.Title = "Unauthorised.";
model.Text = "Your are not authorised to access this resource.";
break;
}
return model;
}
private ErrorViewModel CreateErrorModel(DisplayableException exception)
{
if (exception == null)
{
return new ErrorViewModel();
}
return new ErrorViewModel
{
Title = exception.DisplayTitle,
Text = exception.DisplayDescription,
Exception = exception.InnerException
};
}
private ActionResult ErrorResult(ErrorViewModel model, HttpStatusCode statusCode)
{
HttpContext.Response.Clear();
HttpContext.Response.StatusCode = (int)statusCode;
HttpContext.Response.TrySkipIisCustomErrors = true;
return View("Index", model);
}
在某些情况下,当出现错误时,我需要显示自定义消息。为此,我有一个自定义异常:
[Serializable]
public class DisplayableException : HttpException
{
public string DisplayTitle { get; set; }
public string DisplayDescription { get; set; }
public DisplayableException(string title, string description)
: this(title, description, HttpStatusCode.InternalServerError, null, null)
{
}
public DisplayableException(string title, string description, Exception exception)
: this(title, description, HttpStatusCode.InternalServerError, null, exception)
{
}
public DisplayableException(string title, string description, string message, Exception exception)
: this(title, description, HttpStatusCode.InternalServerError, message, exception)
{
}
public DisplayableException(string title, string description, HttpStatusCode statusCode, string message, Exception inner)
: base((int)statusCode, message, inner)
{
DisplayTitle = title;
DisplayDescription = description;
}
}
然后我像这样使用它:
catch(SomeException ex)
{
throw new DisplayableException("My Title", "My custom display message", "An error occurred and I must display something", ex)
}
在我的
ErrorController
中,我单独处理此异常,从这个
DisplayableException
设置
ErrorViewModel
的
Title
和
Text
属性。