// This software is part of the Autofac IoC container // Copyright © 2012 Autofac Contributors // http://autofac.org // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web.Mvc; using System.Web.Mvc.Async; using Autofac.Features.Metadata; namespace Autofac.Integration.Mvc { /// /// Defines a filter provider for filter attributes that performs property injection. /// public class AutofacFilterProvider : FilterAttributeFilterProvider { class FilterContext { public ActionDescriptor ActionDescriptor { get; set; } public ILifetimeScope LifetimeScope { get; set; } public Type ControllerType { get; set; } public List Filters { get; set; } } internal static string ActionFilterMetadataKey = "AutofacMvcActionFilter"; internal static string AuthorizationFilterMetadataKey = "AutofacMvcAuthorizationFilter"; internal static string ExceptionFilterMetadataKey = "AutofacMvcExceptionFilter"; internal static string ResultFilterMetadataKey = "AutofacMvcResultFilter"; /// /// Initializes a new instance of the class. /// /// /// The false constructor parameter passed to base here ensures that attribute instances are not cached. /// public AutofacFilterProvider() : base(false) { } /// /// Aggregates the filters from all of the filter providers into one collection. /// /// The controller context. /// The action descriptor. /// /// The collection filters from all of the filter providers with properties injected. /// /// /// Thrown if is . /// public override IEnumerable GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } var filters = base.GetFilters(controllerContext, actionDescriptor).ToList(); var lifetimeScope = AutofacDependencyResolver.Current.RequestLifetimeScope; if (lifetimeScope != null) { foreach (var filter in filters) lifetimeScope.InjectProperties(filter.Instance); var controllerType = controllerContext.Controller.GetType(); var filterContext = new FilterContext { ActionDescriptor = actionDescriptor, LifetimeScope = lifetimeScope, ControllerType = controllerType, Filters = filters }; ResolveControllerScopedFilters(filterContext); ResolveActionScopedFilters(filterContext, d => d.MethodInfo); ResolveActionScopedFilters(filterContext, d => d.AsyncMethodInfo); } return filters.ToArray(); } static void ResolveControllerScopedFilters(FilterContext filterContext) { ResolveControllerScopedFilter(filterContext, ActionFilterMetadataKey); ResolveControllerScopedFilter(filterContext, AuthorizationFilterMetadataKey); ResolveControllerScopedFilter(filterContext, ExceptionFilterMetadataKey); ResolveControllerScopedFilter(filterContext, ResultFilterMetadataKey); } static void ResolveControllerScopedFilter(FilterContext filterContext, string metadataKey) where TFilter : class { var actionFilters = filterContext.LifetimeScope.Resolve>>>(); foreach (var actionFilter in actionFilters.Where(a => a.Metadata.ContainsKey(metadataKey) && a.Metadata[metadataKey] is FilterMetadata)) { var metadata = (FilterMetadata)actionFilter.Metadata[metadataKey]; if (metadata.ControllerType != null && metadata.ControllerType.IsAssignableFrom(filterContext.ControllerType) && metadata.FilterScope == FilterScope.Controller && metadata.MethodInfo == null) { var filter = new Filter(actionFilter.Value.Value, FilterScope.Controller, metadata.Order); filterContext.Filters.Add(filter); } } } static void ResolveActionScopedFilters(FilterContext filterContext, Func methodSelector) where T : ActionDescriptor { var actionDescriptor = filterContext.ActionDescriptor as T; if (actionDescriptor == null) return; var methodInfo = methodSelector(actionDescriptor); ResolveActionScopedFilter(filterContext, methodInfo, ActionFilterMetadataKey); ResolveActionScopedFilter(filterContext, methodInfo, AuthorizationFilterMetadataKey); ResolveActionScopedFilter(filterContext, methodInfo, ExceptionFilterMetadataKey); ResolveActionScopedFilter(filterContext, methodInfo, ResultFilterMetadataKey); } static void ResolveActionScopedFilter(FilterContext filterContext, MethodInfo methodInfo, string metadataKey) where TFilter : class { var actionFilters = filterContext.LifetimeScope.Resolve>>>(); foreach (var actionFilter in actionFilters.Where(a => a.Metadata.ContainsKey(metadataKey) && a.Metadata[metadataKey] is FilterMetadata)) { var metadata = (FilterMetadata)actionFilter.Metadata[metadataKey]; if (metadata.ControllerType != null && metadata.ControllerType.IsAssignableFrom(filterContext.ControllerType) && metadata.FilterScope == FilterScope.Action && metadata.MethodInfo.GetBaseDefinition() == methodInfo.GetBaseDefinition()) { var filter = new Filter(actionFilter.Value.Value, FilterScope.Action, metadata.Order); filterContext.Filters.Add(filter); } } } } }