如何截获所有的ASP.NET的WebAPI控制器操作方法与Ninject拦截日志记录电话? [英] How to intercept all the ASP.NET WebApi controller action methods calls with Ninject interception for logging?

查看:283
本文介绍了如何截获所有的ASP.NET的WebAPI控制器操作方法与Ninject拦截日志记录电话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的公司有需要每次我们对我们的ASP.NET的WebAPI控制器的动作方法之一被调用登录某些事情。由于我们使用Ninject的DI,现在,我们希望也用它作此用途。这是我到目前为止已经试过。

Our company has the need to log certain things each time one of our action methods of our ASP.NET WebApi controllers gets called. Since we use Ninject for the DI right now, we'd like to use it also for this purpose. This is what I have tried so far.

我Ninject,Ninject.Extensions.Interception和Ninject.Extensions.Interception.DynamicProxy通过的NuGet安装和我有以下模块

I have Ninject, Ninject.Extensions.Interception and Ninject.Extensions.Interception.DynamicProxy installed through NuGet and I have the following module

public class InterceptAllModule : InterceptionModule
{
    public override void Load()
    {
        Kernel.Intercept(p => p.Request.Service.Name.EndsWith("Controller")).With(new TimingInterceptor());
    }
}

在哪里TimingInterceptor是

Where TimingInterceptor is

public class TimingInterceptor : SimpleInterceptor
{
    readonly Stopwatch _stopwatch = new Stopwatch();
    protected override void BeforeInvoke(IInvocation invocation)
    {
        _stopwatch.Start();
    }

    protected override void AfterInvoke(IInvocation invocation)
    {
        _stopwatch.Stop();
        string message = string.Format("[Execution of {0} took {1}.]",invocation.Request.Method,_stopwatch.Elapsed);
        Log.Info(message + "\n");
        _stopwatch.Reset();
    }
}

现在,当我试图钩模块与ninject内核,并运行我的网站

Now, when I try to hook the module up with ninject kernel, and run my site

var kernel = new StandardKernel(new InterceptAllModule());

然而,每当有进来的操作方法之一的调用,它抛出一个错误说

However, whenever there is a call coming in to one of the action method, it throws an error saying

Cannot instantiate proxy of class: MyApiController.

可能有人用丰富的经验指出,我做错了什么吗?谢谢你。

Could someone with experience point out what I'm doing wrong please? Thanks.

推荐答案

更新

所以使用code和雷莫的有关需要的操作方法是虚拟的,并把一个空的默认构造良好的出发点(只是为了安抚动态代理,让您的其它构造仍)我已经得到双方的动作过滤器和拦截的方式工作。

So using your Code and Remo's excellent point about needing the action methods to be virtual and putting in an empty default constructor (just to placate dynamic proxy, keep your other constructor still) I have got both the action filter and the interception approach working.

我要说的是,因为它代表你的code将截获的ApiController可能有害的方法,所以你可能也需要把一些code到位,这些如滤除ExecuteAsync和处置。

I would say that as it stands your code will intercept potentially unwanted methods on the ApiController so you will probably also need to put some code in place to filter these out e.g. ExecuteAsync and Dispose.

我唯一的另一点是性能。 巨大免责声明这些只是非常基本的测试(每次使用记录的统计动作滤波法),我请你做你自己(!)...但使用DynamicProxy拦截我得到每GET请求大约4毫秒的时间

My only other point is performance. Huge disclaimer these are just very basic tests (using the action filter approach each time to log the stats), I invite you to do your own(!)... but using the DynamicProxy interceptor I was getting a time of around 4 milliseconds per get request

[Execution of Get took 00:00:00.0046615.]
[Execution of Get took 00:00:00.0041988.]
[Execution of Get took 00:00:00.0039383.]

注释掉拦截code和使用动作过滤器我得到亚毫秒级的性能:

Commenting out the Interception code and using an Action filter I was getting sub millisecond performance:

[Execution of Get took 00:00:00.0001146.]
[Execution of Get took 00:00:00.0001116.]
[Execution of Get took 00:00:00.0001364.]

这是由你,这是否实际上是一个问题或关注,但我想我应该指出这一点。

It is up to you whether this is actually an issue or concern but I thought I would point this out.

previous响应

你有没有rulled了使用ActionFilters?这是自然的延伸点AOP的一个MVC的行动。

Have you rulled out using ActionFilters? This is the natural extension point for AOP on an MVC action.

如果您有兴趣比控制器上的实际操作等方法,然后我会理解,但我想我会反正发表建议。

If you were interested in methods other than the actual action on the controller then I would understand but I thought I would post a suggestion anyway.

按<一个启发href=\"http://stackoverflow.com/questions/8937200/are-actionfilterattributes-reused-across-threads-how-does-that-work\">Are ActionFilterAttributes跨线程重用?如何运作?和<一个href=\"http://stackoverflow.com/questions/11353155/measure-time-invoking-mvc-4-controller-actions\">Measure中调用时间4 MVC控制器动作的。

更新以显示定时器的排除方法时标记。从核心的WebAPI框架灵感特别<一个href=\"http://aspnetwebstack.$c$cplex.com/SourceControl/changeset/view/5d4159c85ff6#src/System.Web.Http/AllowAnonymousAttribute.cs\">AllowAnonymousAttribute和<一个href=\"http://aspnetwebstack.$c$cplex.com/SourceControl/changeset/view/5d4159c85ff6#src/System.Web.Http/AuthorizeAttribute.cs\">AuthorizeAttribute

Updated to show the exclusion of the timer when method tagged. Inspiration from core WebApi framework specifically AllowAnonymousAttribute and AuthorizeAttribute

中注册此全局,使所有操作由该监控:

Register this globally so that all actions are monitored by this:

GlobalConfiguration.Configuration.Filters.Add(new TimingActionFilter());

然后:

public class TimingActionFilter : ActionFilterAttribute
{
    private const string Key = "__action_duration__";

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (SkipLogging(actionContext))
        {
            return;
        }

        var stopWatch = new Stopwatch();
        actionContext.Request.Properties[Key] = stopWatch;
        stopWatch.Start();
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (!actionExecutedContext.Request.Properties.ContainsKey(Key))
        {
            return;
        }

        var stopWatch = actionExecutedContext.Request.Properties[Key] as Stopwatch;
        if(stopWatch != null)
        {
            stopWatch.Stop();
            var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
            Debug.Print(string.Format("[Execution of {0} took {1}.]", actionName, stopWatch.Elapsed));
        }

    }

    private static bool SkipLogging(HttpActionContext actionContext)
    {
        return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() ||
                actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any();
    }
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
public class NoLogAttribute : Attribute
{

}

现在你可以使用排除全局过滤器:

Now you can exclude the global filter using:

public class ExampleController : ApiController
{
    // GET api/example
    [NoLog]
    public Example Get()
    {
       //
    }
}

这篇关于如何截获所有的ASP.NET的WebAPI控制器操作方法与Ninject拦截日志记录电话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆