要保留原始 URL,您可以使用此处描述的路线并在 global.asax 中明确处理错误,而不是使用 web.config customerrors 或 httperrors 部分(仍可配置为后备),但更改链接网站示例上的 IHttpHandler.ProcessRequest 部分使用 HttpContext.Server.TransferRequest(path, true)。我在我的一个项目中实现了这样的 Application_Error 事件:
protected void Application_Error()
{
Exception error = Server.GetLastError();
var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;
if (!Context.IsDebuggingEnabled
&& code != 404)
{
// persist error to error log db
//Log.Logger.Error("unhandled exception: ", exception);
}
if (WebConfigurationManager.AppSettings["EnableCustomExceptionPage"].Equals("false"))
{
return;
}
Response.Clear();
Server.ClearError();
string path = this.Request.Path;
string action;
switch (code)
{
case 401:
action = "Unauthorized";
break;
case 403:
action = "Forbidden";
break;
case 404:
action = "NotFound";
break;
default:
action = "Generic";
break;
}
string newPath = string.Format("~/Error/{0}?source={1}&message={2}", action, path,
HttpUtility.UrlEncode(error.Message));
Context.Server.TransferRequest(newPath, true);
}
在内部,它将请求传输到一个新路径,即由 ErrorController 处理,如上面描述的示例中,其操作可能如下所示:
public ViewResult Generic(string source, string message)
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = 500;
ViewBag.Source = source;
ViewBag.Message = HttpUtility.UrlDecode(message);
return View();
}
public ViewResult NotFound(string source, string message)
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = 404;
ViewBag.Source = source;
ViewBag.Message = HttpUtility.UrlDecode(message);
return View();
}
...
TrySkipIisCustomErrors = true
阻止 IIS 重定向到默认的自定义错误页面。您可以在 Application_Error 覆盖方法中以不同的方式处理抛出的异常(如业务/服务层中抛出的特殊异常)而不是 HttpException。