繁体   English   中英

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

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

我有一个自定义日志记录属性,如下所示:

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

以下是 controller 操作方法中的代码,我需要从中执行上述过滤器,但下面的代码不起作用,因为我不确定如何通过属性传递服务:

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

IHttpLogService 和 ILogService 是我需要注入到我的自定义过滤器属性中的一个。 但我不太确定如何做到这一点。 有人可以帮我解决这个问题吗?

您必须将属性与操作过滤器分开。 保持属性简单明了:

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

让你的动作过滤器发挥作用:

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.
    }
}

不要忘记在启动时注册您的操作过滤器:

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

更好的是:您现在可以使用IAsyncActionFilter

根据我的第一次分析,您的代码不应该编译,您尝试使用的在ASP.Net中称为过滤器。

过滤器定义:

ASP.NET MVC 过滤器是一个自定义 class ,您可以在其中编写自定义逻辑以在操作方法执行之前或之后执行。 过滤器可以以声明或编程方式应用于操作方法或 controller。 声明性意味着通过将过滤器属性应用于操作方法或 controller class 和编程意味着通过实现相应的接口。

文档来源

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 - 第二步:(注册您的过滤器)

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

3 - 第三步:(将您的过滤器集成到您的 Controller 或操作)

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

在第一步中,我手动实例化了我的记录器,但在您的情况下,您应该通过您的界面自动解析您的记录器,您可以做的是用您自己的代码替换这段代码。

暂无
暂无

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

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