using System; using System.Linq; using System.Net; using System.Web; using System.Web.Configuration; using System.Web.Mvc; using ApacKernel; using Newtonsoft.Json; namespace Now.Web.Modules { /// /// Enables support for CustomErrors ResponseRewrite mode in MVC. /// public class ErrorHandlerModule : IHttpModule { private HttpContext HttpContext { get { return HttpContext.Current; } } private CustomErrorsSection CustomErrors { get; set; } public void Init(HttpApplication application) { //System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~"); //CustomErrors = (CustomErrorsSection)configuration.GetSection("system.web/customErrors"); CustomErrors = (CustomErrorsSection)ApacConfig.Sections.GetSection("system.web/customErrors"); application.EndRequest += Application_EndRequest; } protected void Application_EndRequest(object sender, EventArgs e) { // only handle rewrite mode, ignore redirect configuration (if it ain't broke don't re-implement it) if (CustomErrors.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite && HttpContext.IsCustomErrorEnabled) { var statusCode = HttpContext.Response.StatusCode; // if this request has thrown an exception then find the real status code var exception = HttpContext.Error; if (exception != null) { // set default error status code for application exceptions statusCode = (int)HttpStatusCode.InternalServerError; } var httpException = exception as HttpException; if (httpException != null) { statusCode = httpException.GetHttpCode(); } if ((HttpStatusCode)statusCode != HttpStatusCode.OK) { var errorPaths = CustomErrors.Errors.Cast().ToDictionary(error => error.StatusCode, error => error.Redirect); // find a custom error path for this status code if (errorPaths.Keys.Contains(statusCode)) { string url = errorPaths[statusCode]; // avoid circular redirects if (!HttpContext.Request.Url.AbsolutePath.Equals(VirtualPathUtility.ToAbsolute(url))) { HttpContext.Response.Clear(); HttpContext.Response.TrySkipIisCustomErrors = true; HttpContext.Server.ClearError(); if (!new HttpRequestWrapper(HttpContext.Current.Request).IsAjaxRequest()) { // do the redirect here if (HttpRuntime.UsingIntegratedPipeline) { HttpContext.Server.TransferRequest(url, true); } else { HttpContext.RewritePath(url, false); IHttpHandler httpHandler = new MvcHttpHandler(); httpHandler.ProcessRequest(HttpContext); } } else if (exception != null) { HttpContext.Response.ContentType = "application/json"; HttpContext.Response.Write(JsonConvert.SerializeObject(exception)); } // return the original status code to the client // (this won't work in integrated pipleline mode) HttpContext.Response.StatusCode = statusCode; } } } } } public void Dispose() { } } }