拦截与温莎城堡的webpi2电话

时间:2014-12-14 14:53:52

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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()等等。)

答案 1 :(得分:0)

虽然使用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 

<强> LoggingFacility

Castle Windsor提供LoggingFacility组件作为Logging的替代方法(使用注入而不是拦截),允许在方法内部进行记录,不仅仅是在拦截器之后和之后(允许使用拦截器)。

只需以这种方式注册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");
        …
    }
    ...
}

查看此link和此link以获取更多信息。

示例

因此,作为示例,您可以混合使用这两种功能来实现以这种方式记录控制器操作:

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
        );
    }
    ...
}