处理IIS Express和IIS 7.5的C#MVC错误
在IIS Express和IIS 7.5上是否存在真正处理错误(如404,500等)的完整解决方案?处理IIS Express和IIS 7.5的C#MVC错误
我也记不清多少篇文章我看了,对于Web.config文件,打开的customErrors开,关,等...或评论/从FilterConfig.cs在取消filters.Add(new HandleErrorAttribute());
有人可以请回顾一下我到目前为止,并告诉我什么是正确的配置,使我能够在IIS Express和IIS 7.5上完全捕获服务器错误,显示一个自定义错误页面,而不是似乎被调用的Shared/Error.cshtml,不管是什么和Application_Error被忽略。
的Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
var lastError = Server.GetLastError();
Server.ClearError();
var statusCode = lastError.GetType() == typeof(HttpException) ? ((HttpException)lastError).GetHttpCode() : 500;
var httpContextWrapper = new HttpContextWrapper(Context);
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "Index");
routeData.Values.Add("statusCode", statusCode);
routeData.Values.Add("exception", lastError);
IController errorController = new ErrorController();
var requestContext = new RequestContext(httpContextWrapper, routeData);
errorController.Execute(requestContext);
Response.End();
}
ErrorController.cs
public class ErrorController : Controller
{
private readonly Common _cf = new Common();
private readonly string _httpReferer = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_REFERER"];
private readonly string _httpUserAgent = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"];
public ActionResult Index(int? statusCode, Exception exception)
{
Response.TrySkipIisCustomErrors = true;
try
{
Response.StatusCode = ((HttpException) exception).GetHttpCode();
}
catch (Exception tryException)
{
SendEmail(tryException, statusCode.ToString());
return Redirect("/");
}
SendEmail(exception, Convert.ToString(Response.StatusCode));
ViewBag.Title = statusCode == 404 ? "Page Not Found" : "Server Error";
ViewBag.ExceptionMessage = Convert.ToString(exception.Message);
return View("Index");
}
private void SendEmail(Exception exception, string errorType)
{
const string to = "[email protected]";
const string @from = "[email protected]";
var subject = "SendEmailError (" + errorType + ")";
var stringBuilder = new StringBuilder();
stringBuilder.Append("<p><strong>Exception Message: </strong>" + exception.Message + "</p>");
stringBuilder.Append("<p><strong>Source: </strong>" + exception.Source + "</p>");
stringBuilder.Append("<p><strong>Referer: </strong>" + _httpReferer + "</p>");
stringBuilder.Append("<p><strong>IP Address: </strong>" + _cf.GetIpAddress() + "</p>");
stringBuilder.Append("<p><strong>Browser: </strong>" + _httpUserAgent + "</p>");
stringBuilder.Append("<p><strong>Target: </strong>" + exception.TargetSite + "</p>");
stringBuilder.Append("<p><strong>Stack Trace: </strong>" + exception.StackTrace + "</p>");
stringBuilder.Append("<p><strong>Inner Exception: </strong>" + (exception.InnerException != null ? exception.InnerException.Message : "") + "</p>");
var body = stringBuilder.ToString();
_cf.SendEmail(subject, to, from, body, null, true, null, null);
}
}
Index.cshtml
@model WebApplication1.Models.Error
@if (HttpContext.Current.IsDebuggingEnabled)
{
if (Model != null)
{
<p><strong>Exception:</strong> @Model.Exception.Message</p>
<div style="overflow:scroll">
<pre>@Model.Exception.StackTrace</pre>
</div>
}
else
{
<p><strong>Exception:</strong> @ViewBag.ExceptionMessage</p>
}
}
个Error.cs
using System;
namespace WebApplication1.Models
{
public class Error
{
public int HttpStatusCode { get; set; }
public Exception Exception { get; set; }
}
}
任何帮助,将不胜感激:-)
刚把通过一个项目我最近看。 我只有在的Application_Error(),它是一个行:
Exception ex = Server.GetLastError();
FilterConfig.cs
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute()); // Removed because ELMAH reports "cannot find Shared/Error" view instead of the exception.
}
}
ErrorPageController.cs
public ActionResult DisplayError(int id)
{
if (id == 404)
{
//... you get the idea
的Web.config
<customErrors mode="On" defaultRedirect="~/ErrorPage/DisplayError/500">
<error redirect="~/ErrorPage/DisplayError/403" statusCode="403" />
<error redirect="~/ErrorPage/DisplayError/404" statusCode="404" />
<error redirect="~/ErrorPage/DisplayError/500" statusCode="500" />
</customErrors>
和右侧下底我有这个,有一个方便的注释,以提醒自己:)
<system.webServer>
<handlers>
<add name="ELMAH" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
</handlers>
<httpErrors existingResponse="PassThrough" /> <!-- Required for IIS7 to know to serve up the custom error page -->
</system.webServer>
当我进一步深入研究,并进一步,我想通了,我的具体问题的原因。我有一条干扰的路线。
routes.MapRoute("Pages", "{mainCategory}/{subCategory}/{pageName}", new { controller = "Home", action = "Pages", subCategory = UrlParameter.Optional, pageName = UrlParameter.Optional, QueryStringValueProvider = UrlParameter.Optional });
随着网页测试www.mydomain.com/blahblah
不存在,它掉到页面路线,以检查是否存在于数据库的内容,因为它没有它返回一个空模型而这又因此返回View("Error"}
没有打错误控制器。
因此,我绑定了一个BaseController到HomeController,它具有override void ExecuteResult
以正确捕获404错误。
HomeController。CS
public class HomeController : BaseController
{
public ActionResult Pages(string mainCategory, string subCategory, string pageName)
{
var model = _pageDetailsRepository.GetPageDetails(mainCategory, subCategory, false);
if (model == null)
{
// return View("Error")
return HttpNotFound();
}
}
}
BaseController
public class BaseController : Controller
{
protected new HttpNotFoundResult HttpNotFound(string statusDescription = null)
{
return new HttpNotFoundResult(statusDescription);
}
protected HttpUnauthorizedResult HttpUnauthorized(string statusDescription = null)
{
return new HttpUnauthorizedResult(statusDescription);
}
protected class HttpNotFoundResult : HttpStatusCodeResult
{
public HttpNotFoundResult() : this(null) { }
public HttpNotFoundResult(string statusDescription) : base(404, statusDescription) { }
}
protected class HttpUnauthorizedResult : HttpStatusCodeResult
{
public HttpUnauthorizedResult(string statusDescription) : base(401, statusDescription) { }
}
protected class HttpStatusCodeResult : ViewResult
{
public int StatusCode { get; private set; }
public string StatusDescription { get; private set; }
public HttpStatusCodeResult(int statusCode) : this(statusCode, null) { }
public HttpStatusCodeResult(int statusCode, string statusDescription)
{
StatusCode = statusCode;
StatusDescription = statusDescription;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
context.HttpContext.Response.StatusCode = StatusCode;
if (StatusDescription != null)
{
context.HttpContext.Response.StatusDescription = StatusDescription;
}
ViewName = "Error";
ViewBag.Title = context.HttpContext.Response.StatusDescription;
base.ExecuteResult(context);
}
}
}
在Web.config具有<system.web><customErrors mode="Off" /></system.web>
和<system.webServer><httpErrors existingResponse="PassThrough" /></system.webServer>
由于VictorySaber因为这确保IIS 7.5经过404头。
我很高兴你已经解决了这个问题:) – VictorySaber
谢谢,你对'
我只是更新了这一点,但请先尝试对该行进行评论......好吧,只需进行这些简单更改,它是否适合您? – VictorySaber
谢谢,我已经注释掉了HandleErrorAttribute,将下面的内容添加到我的webconfig' customErrors>'但仍然没有喜悦,根本没有触及ErrorController。 –
iggyweb
尝试添加PassThrough到webconfig – VictorySaber