【问题标题】:Intercepting webpi2 calls with Windsor Castle使用温莎城堡拦截 webpi2 调用
【发布时间】:2015-02-09 11:32:27
【问题描述】:

我正在使用 webapi2 和 Castle Windsor。我正在尝试拦截对 ApiController 的调用以进行一些日志记录,但我在参数中找不到调用的方法、url、参数等。返回的方法名称是 ExecuteAsync。

这是我的拦截器调用(被命中)

    public class LoggingInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            var methodName = invocation.Method.Name;
            invocation.Proceed();
        }
    }

【问题讨论】:

  • 你的意思是invocation.Arguments

标签: asp.net-web-api castle-windsor asp.net-web-api2 castle


【解决方案1】:
if (invocation.Method.Name == "ExecuteAsync")
{
    var ctx = (HttpControllerContext) invocation.Arguments[0];
    Console.WriteLine("Controller name: {0}", ctx.ControllerDescriptor.ControllerName);
    Console.WriteLine("Request Uri: {0}", ctx.Request.RequestUri);
}
invocation.Proceed();

拦截 ExecuteAsync 调用,您可以访问 HttpControllerContext 但不能访问 HttpActionContext,后者包含有关正在调用的实际控制器操作方法的详细信息。 (据我所知,这仅适用于 ActionFilter)。

因此有关请求的详细信息是有限的:例如,使用此技术无法获得反序列化参数。

如果您愿意,您可以将控制器操作方法设置为virtual,然后这些方法也会被拦截,然后您可以通过invocation.arguments 访问实际操作参数。但是,在您的拦截器中,您需要以某种方式将您希望记录的操作方法与控制器上调用的其他方法(即Intialize()Dispose()ExecuteAsync()Ok() 等)区分开来。 )

【讨论】:

    【解决方案2】:

    虽然使用 ASP.NET MVC 框架可以从 LoginInterceptor 获取操作调用者(检查 this link),但在 ASP.NET Web Api 中,我还没有找到使用带有 Castle Windsor 的拦截器来实现它的正确方法。

    另一方面,我找到了一种方法来实现您想要做的事情,利用 Caller Info Attributes 和 Castle Windsor LoggingFacility 组件。

    来电信息属性

    这些属性是

    • [CallerMemberName] - 设置有关呼叫者成员名称的信息。
    • [CallerFilePath] - 设置调用者源代码的信息 文件。
    • [CallerLineNumber] - 设置来电者的线路号码信息。

    你可以这样使用它们(作为可选参数):

    public static void ShowCallerInfo([CallerMemberName] 
          string callerName = null, [CallerFilePath] string 
          callerFilePath = null, [CallerLineNumber] int callerLine=-1)
    {
        Console.WriteLine("Caller Name: {0}", callerName);
        Console.WriteLine("Caller FilePath: {0}", callerFilePath);
        Console.WriteLine("Caller Line number: {0}", callerLine);
    }
    

    调用ShowCallerInfo();方法(不带参数)显示:

    Caller Name: Main
    Caller FilePath: h:\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1\Class1.cs
    Caller Line number: 7 
    

    记录设施

    Castle Windsor 提供了LoggingFacility 组件作为日志记录的替代方案(使用注入而不是拦截),它允许在您的方法中进行日志记录,而不仅仅是在之后和之前(允许使用拦截器)。

    只需以这种方式注册您的 Logger:

    container.AddFacility<LoggingFacility>(f => f.UseNLog().WithConfig("NLog.config"));
    

    自动注入可在您的代码中使用的 ILogger 对象。

    public class MyController : ApiController
    {
        public ILogger Logger { get; set; }
    
        [HttpGet]
        public IHttpActionResult Get()
        {
            Logger.Info("Log Test");
            …
        }
        ...
    }
    

    查看linklink 了解更多信息。

    示例

    因此,例如,您可以混合使用这两种功能以通过这种方式在控制器操作中实现登录:

    public class MyController : ApiController
    {
        // Make Logger optional
        private ILogger logger = NullLogger.Instance;
        public ILogger Logger
        {
            get { return logger; }
            set { logger = value; }
        }
    
        [HttpGet]
        public IHttpActionResult Get()
        {
            loggerError("Error");
    
            ...
    
            return Ok();
        }
    
        ....
    
        public void loggerError(string message, 
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "", 
            [CallerLineNumber] int sourceLineNumber = 0)
        {
            Logger.Error(message + 
                " - Caller Name: " + memberName 
                + " - Caller FilePath: " + sourceFilePath 
                + " - Line number: " + sourceLineNumber
            );
        }
        ...
    }
    

    【讨论】:

    • 是的,我已经在使用日志记录工具,但我不想破坏类,这就是我想把它放在拦截器中的方式......无论如何谢谢!
    猜你喜欢
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    相关资源
    最近更新 更多