Передайте объекты конструктору ActionFilter в MVC C# - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь создать собственный фильтр журнала в моем приложении 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.");
            }
        }
    }

В приведенном выше коде я пытался передать экземпляр службы моему атрибуту фильтра. Как я могу добиться передачи экземпляра в мой пользовательский атрибут фильтра?

Ответы [ 2 ]

0 голосов
/ 13 апреля 2020

Я делал это некоторое время назад на ASP. NET MVC проекте с Ninject для DI. Комментарий Эндрю от 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
}
В 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.

Также см. мой более подробный ответ здесь относительно аналогичного вопроса / структуры.

0 голосов
/ 09 апреля 2020

Добавьте публичные c свойства и установите их в атрибуте, например, Свойство 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")]
...