【问题标题】:How to inject service into custom ActionFilterAttribute (Web API)?如何将服务注入自定义 ActionFilterAttribute (Web API)?
【发布时间】:2021-05-21 19:37:07
【问题描述】:

我试过这个答案:[https://stackoverflow.com/questions/18406506/custom-filter-attributes-inject-dependency][1] 为 Web API 项目实现 ActionFilterAttribute (System.Web.Http.Filters) (不是MVC)。但是我的自定义属性从未在控制器中调用过。如有任何建议,我将不胜感激。

自定义属性:

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

这里有什么问题吗?

【问题讨论】:

    标签: asp.net .net asp.net-web-api


    【解决方案1】:

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

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

    全局注册示例:

                services.AddControllers(options => 
                {
                    options.Filters.Add(typeof(LoggerFilterAttribute));
                });
    

    Controller中方法注册示例:

    我想要通知 - 在这种情况下,您应该使用 ServiceFilter - 这有助于 DI 解决您的过滤器的任何依赖项。

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

    这是我的这个任务的简单示例:

    1. 我的SimpleService
        public interface ISimpleService 
        {
            void Notify(string text);
        }
        public class SimpleService : ISimpleService
        {
            public void Notify(string text)
            {
                Console.WriteLine($"Notify from {nameof(SimpleService)}. {text}");
            }
        }
    
    1. ActionFilterAttribute
        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);
            }
        }
    
    1. 主要步骤 - 您应该选择注册方式,因为全局注册和代码中的每个控制器/方法之间存在主要区别。
    • 如果你想使用这种注册方式 - 你只需要注册全局过滤器就足够了。所有魔法都将由 WebAPI 通过 DI 注册完成。
                services.AddControllers(options => 
                {
                    options.Filters.Add(typeof(LoggerFilterAttribute));
                });
    
    • 如果您想使用每个控制器/方法的注册。 您需要在 DI 中注册您的过滤器。因为没有它您将有异常。
    services.AddScoped<LoggerFilterAttribute>();
    
            [HttpGet]
            [ServiceFilter(typeof(LoggerFilterAttribute))]
            public IEnumerable<WeatherForecast> Get()
            {
    
            }
    
    1. 最后一步注册我的服务
    services.AddTransient<ISimpleService, SimpleService>();
    
    1. 结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多