将对象传递给MVC C#中的ActionFilter构造函数

时间:2020-04-09 12:46:07

标签: c# asp.net-mvc action-filter custom-action-filter asp.net-mvc-filters

我正在尝试在我的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.");
            }
        }
    }

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

2 个答案:

答案 0 :(得分:0)

添加公共属性,并在此处的“名称”属性之类的属性中进行设置:

[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")]

答案 1 :(得分:0)

前一段时间,我是使用Ninject for DI在ASP.NET MVC项目上进行此操作的。安德鲁在4月10日对自己的答案的评论是正确的方向,但是这对您来说可能是什么样子(示例使用Ninject,但您可以适应使用的任何DI)。

  1. 从技术上讲,您的属性还可以,但实际上,您应该定义一个没有行为的属性,该属性仅与行为所在的 filter 相关。我已按照以下最佳做法调整了您的应用程序:
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包而异。

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

相关问题