Environement:Unity和ASP.NET MVC WEBAPI 我按照网页http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection中的示例进行操作 在做了一些修改之后,我找到了一种为Controler注入Filter的方法。
我在boostrapper.cs中使用了这段代码
var container = new UnityContainer();
container.RegisterInstance<IFilterProvider>("FilterProvider", new FilterProvider(container));
container.RegisterInstance<IActionFilter>("LogActionFilter", new TraceActionFilter());
我添加了这个类FilterProvider
public class FilterProvider : IFilterProvider
{
private IUnityContainer container;
public FilterProvider(IUnityContainer container)
{
this.container = container;
}
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in this.container.ResolveAll<IActionFilter>())
{
yield return new Filter(actionFilter, FilterScope.First, null);
}
}
}
因此,每次通过调用一个实现Controller的类调用方法时,我都能看到TraceActionFilter类中调用的代码。
public class TraceActionFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Trace.Write("OnActionExecuted");
filterContext.HttpContext.Trace.Write("Action " + filterContext.ActionDescriptor.ActionName);
filterContext.HttpContext.Trace.Write("Controller " + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Trace.Write("OnActionExecuting");
filterContext.HttpContext.Trace.Write("Action " + filterContext.ActionDescriptor.ActionName);
filterContext.HttpContext.Trace.Write("Controller " + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
}
}
但是我没有在网上找到允许做同样事情的任何样本或正确方式:注入过滤器以添加关于WebApi的相同行为。 找到的唯一方法是使用标记手动添加过滤器,而不是使用依赖注入。 你能提供任何帮助吗?
祝你好运, 亚历山大
[第一次答复后的更新] 我启动命令Install-Package Unity.AspNet.WebApi以允许访问UnityConfig。 我添加了global.asax
protected void Application_Start()
{
Bootstrapper.Initialise();
UnityWebApiActivator.Start();
ConfigureApi(GlobalConfiguration.Configuration); //line added
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
我添加方法ConfigureApi()
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<ProductsApiController>();
unity.RegisterType<CategoriesApiController>();
unity.RegisterType<IProductService, ProductService>(
new HierarchicalLifetimeManager());
unity.RegisterType<IProductsDatabase, ProductsDatabase>(
new HierarchicalLifetimeManager());
unity.RegisterType<ICategorieService, CategorieService>(
new HierarchicalLifetimeManager());
unity.RegisterType<ICategoriesDatabase, CategoriesDatabase>(
new HierarchicalLifetimeManager());
unity.RegisterType<ILogProvider, ElmahProvider>(
new HierarchicalLifetimeManager());
unity.RegisterType<IRootController, RootController>(
new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
//ADDED PARTS
var providers = GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();
config.Services.Add(
typeof(System.Web.Http.Filters.IFilterProvider),
new Filter2Provider(UnityConfig.GetConfiguredContainer()));
var defaultprovider = providers.First(p => p is System.Web.Http.Filters.ActionDescriptorFilterProvider);
config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
}
当我调用方法时... api / categoriesapi / GetAll TraceActionFilter中的breakPoint未被调用。
任何想法?我继续搜索。
答案 0 :(得分:4)
您需要创建一个自定义的System.Web.Http.Filters.FilterProvider(请注意,MVC在不同的命名空间中具有相同名称的类):
public class UnityActionFilterProvider
: System.Web.Http.Filters.ActionDescriptorFilterProvider,
System.Web.Http.Filters.IFilterProvider
{
private readonly IUnityContainer container;
public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration,
HttpActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
{
// TODO: Determine correct FilterScope
yield return new FilterInfo(actionFilter, FilterScope.Global);
}
}
}
然后,您需要在启动时设置过滤器提供程序:
var providers =
GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();
GlobalConfiguration.Configuration.Services.Add(
typeof(System.Web.Http.Filters.IFilterProvider),
new UnityActionFilterProvider(UnityConfig.GetConfiguredContainer()));
var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);
GlobalConfiguration.Configuration.Services.Remove(
typeof(System.Web.Http.Filters.IFilterProvider),
defaultprovider);
您应该将上述内容与Unity bootstrapper for ASP.NET Web API
一起使用使用属性的类似问题:ASP.NET Web API - Inject Dependencies Into ActionFilterAttribute
由于您使用容器维护过滤器列表,因此您可以直接注册FilterInfo而不是IActionFilter。