From b374e9814f7c455c8db0521c247418bc6eb62d5c Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 5 Dec 2013 17:42:05 -0800 Subject: [PATCH] #19561: Implementing WebAPI filters support Work Item: 19561 --- .../Controllers/HelloController.cs | 38 +++++++++++++++++++ src/Orchard/Environment/OrchardStarter.cs | 4 ++ src/Orchard/Orchard.Framework.csproj | 4 ++ src/Orchard/WebApi/Filters/IFilterProvider.cs | 8 ++++ .../OrchardApiActionFilterDispatcher.cs | 23 +++++++++++ .../OrchardApiExceptionFilterDispatcher.cs | 18 +++++++++ .../Filters/UnhandledApiExceptionFilter.cs | 16 ++++++++ 7 files changed, 111 insertions(+) create mode 100644 src/Orchard.Web/Modules/Orchard.Blogs/Controllers/HelloController.cs create mode 100644 src/Orchard/WebApi/Filters/IFilterProvider.cs create mode 100644 src/Orchard/WebApi/Filters/OrchardApiActionFilterDispatcher.cs create mode 100644 src/Orchard/WebApi/Filters/OrchardApiExceptionFilterDispatcher.cs create mode 100644 src/Orchard/WebApi/Filters/UnhandledApiExceptionFilter.cs diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/HelloController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/HelloController.cs new file mode 100644 index 000000000..d3058575a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/HelloController.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Http; +using System.Web.Http.Controllers; +using System.Web.Http.Filters; +using Orchard.Localization; +using Orchard.Mvc.Filters; +using Orchard.WebApi.Filters; + +namespace Orchard.Blogs.Controllers { + public class HelloController : ApiController { + + public HelloController( + IOrchardServices orchardServices) { + Services = orchardServices; + T = NullLocalizer.Instance; + } + + public IOrchardServices Services { get; private set; } + public Localizer T { get; set; } + + public string Get() { + return "Hello, world!"; + } + } + + public class MyFilter : ActionFilterAttribute, IApiFilterProvider { + public override void OnActionExecuting(HttpActionContext actionContext) { + actionContext.Response.StatusCode = HttpStatusCode.NoContent; + } + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index 214d2d386..d694d0a5d 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -34,6 +34,7 @@ using Orchard.Mvc.ViewEngines.Razor; using Orchard.Mvc.ViewEngines.ThemeAwareness; using Orchard.Services; using Orchard.WebApi; +using Orchard.WebApi.Filters; namespace Orchard.Environment { public static class OrchardStarter { @@ -154,6 +155,9 @@ namespace Orchard.Environment { GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new DefaultOrchardWebApiHttpHttpControllerActivator(GlobalConfiguration.Configuration)); GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container); + GlobalConfiguration.Configuration.Filters.Add(new OrchardApiActionFilterDispatcher()); + GlobalConfiguration.Configuration.Filters.Add(new OrchardApiExceptionFilterDispatcher()); + ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new ThemeAwareViewEngineShim()); diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index b00e48f89..1756e6c8b 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -587,6 +587,10 @@ + + + + diff --git a/src/Orchard/WebApi/Filters/IFilterProvider.cs b/src/Orchard/WebApi/Filters/IFilterProvider.cs new file mode 100644 index 000000000..75fa31116 --- /dev/null +++ b/src/Orchard/WebApi/Filters/IFilterProvider.cs @@ -0,0 +1,8 @@ +namespace Orchard.WebApi.Filters { + /// + /// Any implementation of will be injected as a WebAPI filter. + /// + public interface IApiFilterProvider : IDependency { + + } +} \ No newline at end of file diff --git a/src/Orchard/WebApi/Filters/OrchardApiActionFilterDispatcher.cs b/src/Orchard/WebApi/Filters/OrchardApiActionFilterDispatcher.cs new file mode 100644 index 000000000..a317eb9db --- /dev/null +++ b/src/Orchard/WebApi/Filters/OrchardApiActionFilterDispatcher.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http.Controllers; +using System.Web.Http.Filters; + +namespace Orchard.WebApi.Filters { + public class OrchardApiActionFilterDispatcher : IActionFilter { + public bool AllowMultiple { get; private set; } + public async Task ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation) { + var workContext = actionContext.ControllerContext.GetWorkContext(); + + foreach (var actionFilter in workContext.Resolve>().OfType()) { + continuation = () => actionFilter.ExecuteActionFilterAsync(actionContext, cancellationToken, continuation); + } + + return await continuation(); + } + } +} \ No newline at end of file diff --git a/src/Orchard/WebApi/Filters/OrchardApiExceptionFilterDispatcher.cs b/src/Orchard/WebApi/Filters/OrchardApiExceptionFilterDispatcher.cs new file mode 100644 index 000000000..896120bd7 --- /dev/null +++ b/src/Orchard/WebApi/Filters/OrchardApiExceptionFilterDispatcher.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http.Filters; + +namespace Orchard.WebApi.Filters { + public class OrchardApiExceptionFilterDispatcher : IExceptionFilter { + public bool AllowMultiple { get; private set; } + public async Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { + var workContext = actionExecutedContext.ActionContext.ControllerContext.GetWorkContext(); + + foreach (var exceptionFilter in workContext.Resolve>().OfType()) { + await exceptionFilter.ExecuteExceptionFilterAsync(actionExecutedContext, cancellationToken); + } + } + } +} \ No newline at end of file diff --git a/src/Orchard/WebApi/Filters/UnhandledApiExceptionFilter.cs b/src/Orchard/WebApi/Filters/UnhandledApiExceptionFilter.cs new file mode 100644 index 000000000..ba7fd1820 --- /dev/null +++ b/src/Orchard/WebApi/Filters/UnhandledApiExceptionFilter.cs @@ -0,0 +1,16 @@ +using System.Web.Http.Filters; +using Orchard.Logging; + +namespace Orchard.WebApi.Filters { + public class UnhandledApiExceptionFilter : ExceptionFilterAttribute, IApiFilterProvider { + public UnhandledApiExceptionFilter() { + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public override void OnException(HttpActionExecutedContext actionExecutedContext) { + Logger.Error(actionExecutedContext.Exception, "Unexpected API exception"); + } + } +}