Exception handling in controllers. No more YSOD.

Create custom 500 error page (with admin theme) for all technical errors (i.e. exceptions that the app doesn't handle)
Implement an filter that will catch all unhandled exceptions and display the custom 500 page. Filter will also use ILogger to log the exception.

--HG--
branch : 1.x
extra : transplant_source : %F5P%0E%3EXv%A0%A3%85%DAu7%9Et%FB2l%86%FC%A3
This commit is contained in:
Suha Can
2011-06-08 14:27:05 -07:00
parent fa41a1b736
commit 51e43a624a
5 changed files with 71 additions and 1 deletions

View File

@@ -482,6 +482,9 @@
<ItemGroup>
<Content Include="Title\Views\Web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Shapes\Views\ErrorPage.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -0,0 +1,8 @@
<div>
<h1 id="page-title">@Html.TitleForPage(T("Oops. Something went wrong ... sorry"))</h1>
<div>
<p>@T("An unhandled exception has occurred. The exception message was : {0}", @Model.Message).Text</p>
<br />
<p>@T("Please refresh the page. If the error persists, go back.").Text</p>
</div>
</div>

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Orchard.Logging;
using Orchard.Mvc;
using Orchard.Mvc.Filters;
using IFilterProvider = Orchard.Mvc.Filters.IFilterProvider;
namespace Orchard.Exceptions.Filters {
public class UnhandledExceptionFilter : FilterProvider, IActionFilter {
private readonly IOrchardServices _orchardServices;
private readonly Lazy<IEnumerable<IFilterProvider>> _filterProviders;
public UnhandledExceptionFilter(
IOrchardServices orchardServices,
Lazy<IEnumerable<IFilterProvider>> filters) {
_orchardServices = orchardServices;
_filterProviders = filters;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void OnActionExecuting(ActionExecutingContext filterContext) {
}
public void OnActionExecuted(ActionExecutedContext filterContext) {
if (!filterContext.ExceptionHandled && filterContext.Exception != null) {
var shape = _orchardServices.New.ErrorPage();
shape.Message = filterContext.Exception.Message;
shape.Exception = filterContext.Exception;
Logger.Error(filterContext.Exception.Message);
filterContext.ExceptionHandled = true;
// inform exception filters of the exception that was suppressed
var filterInfo = new FilterInfo();
foreach (var filterProvider in _filterProviders.Value) {
filterProvider.AddFilters(filterInfo);
}
var exceptionContext = new ExceptionContext(filterContext.Controller.ControllerContext, filterContext.Exception);
foreach (var exceptionFilter in filterInfo.ExceptionFilters) {
exceptionFilter.OnException(exceptionContext);
}
if (exceptionContext.ExceptionHandled) {
filterContext.Result = exceptionContext.Result;
}
else {
filterContext.Result = new ShapeResult(filterContext.Controller, shape);
filterContext.RequestContext.HttpContext.Response.StatusCode = 500;
}
}
}
}
}

View File

@@ -6,7 +6,7 @@ namespace Orchard.Mvc {
ViewData = controller.ViewData;
TempData = controller.TempData;
ViewData.Model = shape;
ViewName = "~/Core/Shapes/Views/ShapeResult/Display.cshtml";
ViewName = "ShapeResult/Display";
}
}
}

View File

@@ -224,6 +224,7 @@
<Compile Include="Environment\WorkContextImplementation.cs" />
<Compile Include="Environment\WorkContextModule.cs" />
<Compile Include="Environment\WorkContextProperty.cs" />
<Compile Include="Exceptions\Filters\UnhandledExceptionFilter.cs" />
<Compile Include="FileSystems\Dependencies\IExtensionDependenciesManager.cs" />
<Compile Include="FileSystems\Dependencies\DefaultExtensionDependenciesManager.cs" />
<Compile Include="FileSystems\LockFile\ILockFile.cs" />
@@ -910,6 +911,7 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.