// 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);
}
}
}
}
}