简体   繁体   English

如何将服务注入自定义过滤器属性 MVC

[英]How to Inject Service into Custom Filter Attribute MVC

I have a Custom Logging Attribute as below:我有一个自定义日志记录属性,如下所示:

public class LoggerAttribute: ActionFilterAttribute
    {

        private readonly IHttpLogService _httpLogService;
        private readonly ILogService _logService;
        public LoggerAttribute(IHttpLogService httpLogService, ILogService logService)
        {
            _httpLogService = httpLogService;
            _logService = logService;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            LogDetails(filterContext);
        }

        private void LogDetails(ActionExecutingContext filterContext)
        {
            try
            {
                HttpLogService httpService = new HttpLogService();
                var httplogger = new LogMetaData()
                {
                    RequestParams = filterContext,
                    ResponseParams  = filterContext
                };
                _httpLogService.Emit("source", "", "Name", httplogger);
            }
            catch (Exception ex)
            {
                _logService.Emit(Core.Enums.LogLevel.Error, "token", "Error encountered while trying to execute the request.", ex);
                throw new Exception("An error occurred. Please try again later.");
            }
        }
    }

Following is the code from controller action method from where I need to execute the above filter, but the below code doesn't work, because I am not sure how to pass the service through the attribute:以下是 controller 操作方法中的代码,我需要从中执行上述过滤器,但下面的代码不起作用,因为我不确定如何通过属性传递服务:

[LoggerAttribute]
public int testMethod(RequestObject obj)
{
-----
}

The IHttpLogService & ILogService are the one that I need to inject into my custom filter attribute. IHttpLogService 和 ILogService 是我需要注入到我的自定义过滤器属性中的一个。 But I am not quite sure how I can do this.但我不太确定如何做到这一点。 Can someone please help me out with this?有人可以帮我解决这个问题吗?

You will have to separate the attribute from the actionfilter.您必须将属性与操作过滤器分开。 Keep the attribute plain and simple:保持属性简单明了:

[AttributeUsage(AttributeTargets.Method)]
public class LoggerAttribute : Attribute
{
}

And let your actionfilter do the magic:让你的动作过滤器发挥作用:

public class LoggerActionFilter : IActionFilter
{
    // Can inject stuff in the constructor

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // You may need some more null checking here...
        var attribute = ((ReflectedActionDescriptor)filterContext.ActionDescriptor).MethodInfo.GetCustomAttributes(true).OfType<LoggerAttribute>().FirstOrDefault();
        if (attribute is null)
        {
            return;
        }

        // Work your logger magic here.
    }
}

Don't forget to register your actionfilter at startup:不要忘记在启动时注册您的操作过滤器:

services.AddControllersWithViews(options =>
{
    options.Filters.Add(typeof(LoggerActionFilter));
});

Even better: you can use an IAsyncActionFilter now!更好的是:您现在可以使用IAsyncActionFilter

According to my first analysis your code is not supposed to compile, what you are trying to use is known as filter in ASP.Net .根据我的第一次分析,您的代码不应该编译,您尝试使用的在ASP.Net中称为过滤器。

Filter Definition:过滤器定义:

ASP.NET MVC Filter is a custom class where you can write custom logic to execute before or after an action method executes. ASP.NET MVC 过滤器是一个自定义 class ,您可以在其中编写自定义逻辑以在操作方法执行之前或之后执行。 Filters can be applied to an action method or controller in a declarative or programmatic way.过滤器可以以声明或编程方式应用于操作方法或 controller。 Declarative means by applying a filter attribute to an action method or controller class and programmatic means by implementing a corresponding interface.声明性意味着通过将过滤器属性应用于操作方法或 controller class 和编程意味着通过实现相应的接口。

documention source 文档来源

1 - First Step: (Create your filter) 1 - 第一步:(创建您的过滤器)

public class TestFilter : ActionFilterAttribute
{
    private readonly ILoggerService loggerService;

    public TestFilter():this(new LoggerService())
    {

    }

    public TestFilter(ILoggerService loggerService)
    {
        this.loggerService = loggerService;
    }
    
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
    }
}

2 - Second Step:(Register your filter) 2 - 第二步:(注册您的过滤器)

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new TestFilter());
}

3 - Thirs Step:(Integrate you filter to your Controller or Action) 3 - 第三步:(将您的过滤器集成到您的 Controller 或操作)

[TestFilter]
public class CustomerController : Controller
{
    .....
}

In the first step i have instantiate my logger manually but in your case you are supposed to resolve your logger automticly throught your interface, what you can do is to replace this piece of code by your own code.在第一步中,我手动实例化了我的记录器,但在您的情况下,您应该通过您的界面自动解析您的记录器,您可以做的是用您自己的代码替换这段代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM