我正在尝试在我的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属性。如何实现将实例传递给自定义过滤器属性?
答案 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)。
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
}
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。