#19561: Implementing WebAPI filters support

Work Item: 19561
This commit is contained in:
Sebastien Ros
2013-12-05 17:42:05 -08:00
parent e31b2bc10e
commit b374e9814f
7 changed files with 111 additions and 0 deletions

View File

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

View File

@@ -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());

View File

@@ -587,6 +587,10 @@
<Compile Include="WebApi\DefaultOrchardWebApiHttpControllerSelector.cs" />
<Compile Include="WebApi\DefaultOrchardWebApiHttpHttpControllerActivator.cs" />
<Compile Include="WebApi\Extensions\RouteExtension.cs" />
<Compile Include="WebApi\Filters\UnhandledApiExceptionFilter.cs" />
<Compile Include="WebApi\Filters\IFilterProvider.cs" />
<Compile Include="WebApi\Filters\OrchardApiExceptionFilterDispatcher.cs" />
<Compile Include="WebApi\Filters\OrchardApiActionFilterDispatcher.cs" />
<Compile Include="WebApi\Routes\IHttpRouteProvider.cs" />
<Compile Include="WebApi\Routes\StandardExtensionHttpRouteProvider.cs" />
<Compile Include="WorkContextExtensions.cs" />

View File

@@ -0,0 +1,8 @@
namespace Orchard.WebApi.Filters {
/// <summary>
/// Any implementation of <see cref="IApiFilterProvider"/> will be injected as a WebAPI filter.
/// </summary>
public interface IApiFilterProvider : IDependency {
}
}

View File

@@ -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<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
var workContext = actionContext.ControllerContext.GetWorkContext();
foreach (var actionFilter in workContext.Resolve<IEnumerable<IApiFilterProvider>>().OfType<IActionFilter>()) {
continuation = () => actionFilter.ExecuteActionFilterAsync(actionContext, cancellationToken, continuation);
}
return await continuation();
}
}
}

View File

@@ -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<IEnumerable<IApiFilterProvider>>().OfType<IExceptionFilter>()) {
await exceptionFilter.ExecuteExceptionFilterAsync(actionExecutedContext, cancellationToken);
}
}
}
}

View File

@@ -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");
}
}
}