0

我正在尝试在我的 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("Error", "token", "Error encountered while trying to execute the request.", ex);
                throw new Exception("An error occurred. Please try again later.");
            }
        }
    }

在上面的代码中,我试图将服务实例传递给我的过滤器属性。如何实现将实例传递给我的自定义过滤器属性?

4

2 回答 2

0

添加公共属性并将它们设置在属性中,例如 Name 属性:

[DeserializeAs(Name = "MAIL")]

像那样:

public class LoggerAttribute: ActionFilterAttribute
{

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

    public string CustomProperty { get; set; }

    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("Error", "token", "Error encountered while trying to execute the request.", ex);
            throw new Exception("An error occurred. Please try again later.");
        }
    }
}

并设置它:

[Logger(CustomProperty="YourValue")]
于 2020-04-09T12:49:20.683 回答
0

不久前,我在一个带有 Ninject for DI 的 ASP.NET MVC 项目上做了这个。Andrew 在 4 月 10 日对他自己的答案的评论是正确的方向,但这可能对您来说是这样的(示例使用 Ninject,但您可以适应您使用的任何 DI)。

  1. 从技术上讲,您的属性是可以的,但作为实践,您应该定义一个没有行为的属性,该行为仅与行为所在的过滤器相关联。我已经调整了你的以适应这个最佳实践,如下所示:
public class LoggerAttribute : ActionFilterAttribute {}

public class LoggerFilter : IActionFilter
{

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

    // Code removed for brevity
}
  1. 在 Global.asax.cs 中,您需要实例化您的服务(如果您有的话,也可以从工厂获取一个)。
namespace MyApp.Web
{
    public class MvcApplication : NinjectHttpApplication
    {
        private static readonly IHttpLogService _httpLogService = someFactory.GetLogService();
        // Or if you don't use a factory
        // private static readonly IHttpLogService _httpLogService = new MyLogServiceImplementation();
        private static readonly ILogService _logService = new MyLogService();

        // Other stuff like OnApplicationStarted() here

        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.BindFilter<LoggerFilter>(FilterScope.Action, 0)
                .WhenActionMethodHas<LoggerAttribute>()
                .WithConstructorArgument("httpLogService", _httpLogService)
                .WithConstructorArgument("logService", _logService);
        }
    }
}

关键部分是我们.WithConstructorArgument()和语法将因 DI 包而异。

另请参阅我关于类似问题/结构的详细答案。

于 2020-04-13T19:14:28.217 回答