2016-04-15 85 views
2

在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; } 
    } 
} 

任何幫助,將不勝感激:-)

回答

1

剛把通過一個項目我最近看。 我只有在的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> 
+0

我只是更新了這一點,但請先嚐試對該行進行評論......好吧,只需進行這些簡單更改,它是否適合您? – VictorySaber

+0

謝謝,我已經註釋掉了HandleErrorAttribute,將下面的內容添加到我的webconfig' customErrors>'但仍然沒有喜悅,根本沒有觸及ErrorController。 – iggyweb

+0

嘗試添加PassThrough到webconfig – VictorySaber

0

當我進一步深入研究,並進一步,我想通了,我的具體問題的原因。我有一條幹擾的路線。

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頭。

+0

我很高興你已經解決了這個問題:) – VictorySaber

+0

謝謝,你對''的建議確實有幫助:-) – iggyweb