Last active
December 29, 2015 15:59
-
-
Save gabrieljoelc/7694719 to your computer and use it in GitHub Desktop.
Constructor injected global action filter example that can be used for specific actions. The original idea came from this SO answer: http://stackoverflow.com/a/4169916/34315. The alternative is implementing a custom container-specific action invoker (http://lostechies.com/jimmybogard/2010/05/03/dependency-injection-in-asp-net-mvc-filters/, http:…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Web.Mvc; | |
namespace Gabe.Web.Common | |
{ | |
/// <summary> | |
/// Use this for getting constructor injected dependencies on IActionFilters. | |
/// </summary> | |
/// <typeparam name="TFilterAttr"></typeparam> | |
/// <remarks> | |
/// <para><typeparam name="TFilterAttr"></typeparam> must inherit from FilterAttribute so that we can leverage ActionDescriptor::GetFilterAttributes() caching.</para> | |
/// <para>I chose to use this solution instead of a custom container-specific <see cref="FilterAttributeFilterProvider"/> | |
/// because the filter provider solution only allows for Setter injection. This decision is another example of my | |
/// OCDness and stubbornness.</para> | |
/// </remarks> | |
public abstract class FilterAttributeSpecificGlobalActionFilter<TFilterAttr> : IGlobalActionFilter | |
where TFilterAttr : FilterAttribute | |
{ | |
protected TFilterAttr FilterAttribute { get; set; } | |
protected bool HasFilterAttribute { get { return FilterAttribute != null; } } | |
protected virtual void OnActionExecuting(ActionExecutingContext filterContext) | |
{ | |
} | |
protected virtual void OnActionExecuted(ActionExecutedContext filterContext) | |
{ | |
} | |
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) | |
{ | |
FilterAttribute = filterContext.ActionDescriptor | |
// pass true to use cache for the filter attributes | |
.GetFilterAttributes(true) | |
.OfType<TFilterAttr>() | |
.SingleOrDefault(); | |
if (!HasFilterAttribute) return; | |
OnActionExecuting(filterContext); | |
} | |
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) | |
{ | |
if (!HasFilterAttribute) return; | |
OnActionExecuted(filterContext); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Web.Mvc; | |
namespace Gabe.Web.Common | |
{ | |
// this one has to be both action and result filter to take advantage of getting the filter attribute from | |
// the action descriptor because result filter contexts don't have access to the action descriptor | |
public abstract class FilterAttributeSpecificGlobalResultFilter<TFilterAttr> : | |
IActionFilter, IGlobalResultFilter where TFilterAttr : FilterAttribute | |
{ | |
protected TFilterAttr FilterAttribute { get; set; } | |
protected bool HasFilterAttribute { get { return FilterAttribute != null; } } | |
protected virtual void OnResultExecuting(ResultExecutingContext filterContext) | |
{ | |
} | |
protected virtual void OnResultExecuted(ResultExecutedContext filterContext) | |
{ | |
} | |
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) | |
{ | |
FilterAttribute = filterContext.ActionDescriptor | |
// pass true to use cache for the filter attributes | |
.GetFilterAttributes(true) | |
.OfType<TFilterAttr>() | |
.SingleOrDefault(); | |
} | |
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) | |
{ | |
} | |
void IResultFilter.OnResultExecuting(ResultExecutingContext filterContext) | |
{ | |
if (!HasFilterAttribute) return; | |
OnResultExecuting(filterContext); | |
} | |
void IResultFilter.OnResultExecuted(ResultExecutedContext filterContext) | |
{ | |
if (!HasFilterAttribute) return; | |
OnResultExecuted(filterContext); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Web.Mvc; | |
namespace Gabe.Web.Common | |
{ | |
// It's easier to use these interfaces that implement the MVC filter interfaces for IoC container | |
// scanning because we don't want to include controller's which also implmenent IActionFilter & IResultFilter | |
public interface IGlobalActionFilter : IActionFilter | |
{ | |
} | |
public interface IGlobalResultFilter : IResultFilter | |
{ | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Web.Mvc; | |
using LinqKit; | |
namespace Gabe.Web.Common | |
{ | |
public class GlobalFilterBootstrapTask : IRunAtStartup | |
{ | |
private readonly GlobalFilterCollection _filters; | |
private readonly IEnumerable<IGlobalActionFilter> _actionFilters; | |
private readonly IEnumerable<IGlobalResultFilter> _resultFilters; | |
public GlobalFilterTask(GlobalFilterCollection filters, IEnumerable<IGlobalActionFilter> actionFilters, | |
IEnumerable<IGlobalResultFilter> resultFilters) | |
{ | |
_filters = filters; | |
_actionFilters = actionFilters; | |
_resultFilters = resultFilters; | |
} | |
public void Execute() | |
{ | |
_actionFilters.ForEach(_filters.Add); | |
_resultFilters.ForEach(_filters.Add); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Gabe.Web.Common; | |
namespace Gabe.Web.MainWebApp.App_Start | |
{ | |
// call these methods from your System.Web.HttpApplication::Application_Start() | |
public static class ApplicationFramework | |
{ | |
public static void Bootstrap() | |
{ | |
ObjectFactory.Configure(x => | |
{ | |
x.AddRegistry<PersistenceRegistry>(); | |
x.AddRegistry<ApplicationServicesRegistry>(); | |
x.AddRegistry<ModelMetadataRegistry>(); | |
x.AddRegistry<TaskRegistry>(); | |
x.AddRegistry<MappingRegistry>(); | |
x.AddRegistry<MvcRegistry>(); | |
// adding filter registry to get all | |
x.AddRegistry<FilterRegistry>(); | |
}); | |
} | |
public static void Start() | |
{ | |
foreach (var task in ObjectFactory.GetAllInstances<IRunAtStartup>()) | |
{ | |
task.Execute(); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Gabe.Web.Common; | |
using StructureMap.Configuration.DSL; | |
namespace Gabe.Web.Common | |
{ | |
class FilterRegistry : Registry | |
{ | |
public FilterRegistry() | |
{ | |
Scan(scanner => | |
{ | |
scanner.AssembliesFromApplicationBaseDirectory(assembly => assembly.FullName.StartsWith("Gabe.Web.")); | |
scanner.AddAllTypesOf<IGlobalActionFilter>(); | |
scanner.AddAllTypesOf<IGlobalResultFilter>(); | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment