Asp.net 如何将服务注入自定义ActionFilterAttribute(Web API)?

Asp.net 如何将服务注入自定义ActionFilterAttribute(Web API)?,asp.net,.net,asp.net-web-api,Asp.net,.net,Asp.net Web Api,我试着回答:[https://stackoverflow.com/questions/18406506/custom-filter-attributes-inject-dependency][1] 为WebAPI项目(非MVC)实现ActionFilterAttribute(System.Web.Http.Filters)。但我的自定义属性从未在控制器中调用。如蒙指教,我将不胜感激 自定义属性: public class MyAttribute : FilterAttribute { } 过滤

我试着回答:[https://stackoverflow.com/questions/18406506/custom-filter-attributes-inject-dependency][1] 为WebAPI项目(非MVC)实现ActionFilterAttribute(System.Web.Http.Filters)。但我的自定义属性从未在控制器中调用。如蒙指教,我将不胜感激

自定义属性:

public class MyAttribute : FilterAttribute { }
过滤器:

public class MyFilter : ActionFilterAttribute
{
    private readonly IMyService _myService;

    public MyFilter(IMyService myService)
    {
        _myService = myService;
    }

    public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        //do some with actionContext
        throw new Exception("You can`t go here");
    }
}
控制器方法:

[My] // Not called
[HttpPost]
[Route("/do-some")]
public async Task DoSome(string myString)
{
     //do some
}
寄存器筛选器:

public partial class Startup 
{
    protected void ConfigureApi(IAppBuilder app, IContainer container) 
    {
        var configuration = new HttpConfiguration();
        //...
        var serviceInstance = container.GetInstance<IMyService>();
        configuration.Filters.Add(new MyFilter(serviceInstance));
    }
}
公共部分类启动
{
受保护的void配置API(IAppBuilder应用程序、IContainer容器)
{
var配置=新的HttpConfiguration();
//...
var serviceInstance=container.GetInstance();
添加(新的MyFilter(serviceInstance));
}
}

这里有什么问题吗?

您的代码几乎一切正常,但您应该以另一种方式注册过滤器和服务

在Asp Net Core WebAPI中,有几种方法可以注册过滤器:

  • 全局-适用于所有控制器、操作和剃须刀页面。更多信息请访问
  • 仅适用于一个控制器/方法。更多信息请访问
全球注册示例:

            services.AddControllers(options => 
            {
                options.Filters.Add(typeof(LoggerFilterAttribute));
            });
控制器中的方法注册示例:

我需要注意-在这种情况下,您应该使用
ServiceFilter
-这有助于DI解决您的筛选器的任何依赖项

        [HttpGet]
        [ServiceFilter(typeof(LoggerFilterAttribute))]
        public IEnumerable<WeatherForecast> Get()
        {

        }
  • ActionFilterAttribute
  • 主要步骤-您应该选择注册方式,因为全局注册和代码中的每个控制器/方法之间存在主要区别
    • 如果你想使用这种注册方式,你只需要注册全局过滤器,这就足够了。所有的魔术都将通过DI注册的
      WebAPI
      实现
    • 如果您想使用每个控制器/方法的注册您需要在DI中注册过滤器。因为如果没有它,您将出现异常
    services.addScope();
    
    [HttpGet]
    [ServiceFilter(类型(LoggerFilterAttribute))]
    公共IEnumerable Get()
    {
    }
    
  • 最后一步注册我的服务
  • services.AddTransient();
    
  • 结果
  •     public interface ISimpleService 
        {
            void Notify(string text);
        }
        public class SimpleService : ISimpleService
        {
            public void Notify(string text)
            {
                Console.WriteLine($"Notify from {nameof(SimpleService)}. {text}");
            }
        }
    
        public class LoggerFilterAttribute : ActionFilterAttribute
        {
            private readonly ISimpleService _simpleService;
    
            public LoggerFilterAttribute(ISimpleService simpleService)
            {
                _simpleService = simpleService;
            }
    
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                _simpleService.Notify($"Method {nameof(OnActionExecuting)}");
            }
    
            public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
            {
                _simpleService.Notify($"Method {nameof(OnActionExecutionAsync)}");
                return base.OnActionExecutionAsync(context, next);
            }
        }
    
                services.AddControllers(options => 
                {
                    options.Filters.Add(typeof(LoggerFilterAttribute));
                });
    
    services.AddScoped<LoggerFilterAttribute>();
    
            [HttpGet]
            [ServiceFilter(typeof(LoggerFilterAttribute))]
            public IEnumerable<WeatherForecast> Get()
            {
    
            }
    
    services.AddTransient<ISimpleService, SimpleService>();