Ray*_*Ray 20 asp.net-mvc logging ninject ninject-interception asp.net-web-api
每次调用ASP.NET WebApi控制器的一个操作方法时,我们公司都需要记录某些内容.由于我们现在使用Ninject作为DI,我们也想将它用于此目的.这是我到目前为止所尝试的.
我有通过NuGet安装的Ninject,Ninject.Extensions.Interception和Ninject.Extensions.Interception.DynamicProxy,我有以下模块
public class InterceptAllModule : InterceptionModule
{
public override void Load()
{
Kernel.Intercept(p => p.Request.Service.Name.EndsWith("Controller")).With(new TimingInterceptor());
}
}
Run Code Online (Sandbox Code Playgroud)
TimingInterceptor的位置
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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我尝试使用ninject内核挂起模块时,运行我的站点
var kernel = new StandardKernel(new InterceptAllModule());
Run Code Online (Sandbox Code Playgroud)
但是,只要有一个调用进入其中一个操作方法,它就会抛出一个错误说
Cannot instantiate proxy of class: MyApiController.
Run Code Online (Sandbox Code Playgroud)
有经验的人可以指出我做错了吗?谢谢.
Mar*_*nes 30
更新
因此,使用你的Code和Remo关于需要将操作方法设置为虚拟并放入一个空的默认构造函数(只是为了安抚动态代理,保持其他构造函数仍然存在)的优点,我得到了动作过滤器和拦截方法.
我会说,因为它代表你的代码将拦截ApiController上可能不需要的方法,所以你可能还需要放置一些代码来过滤这些,例如ExecuteAsync和Dispose.
我唯一的另一点是表现.巨大的免责声明这些只是非常基本的测试(每次使用动作过滤器方法记录统计数据),我邀请你做自己的(!)...但是使用DynamicProxy拦截器我得到的时间大约是4毫秒得到请求
[Execution of Get took 00:00:00.0046615.]
[Execution of Get took 00:00:00.0041988.]
[Execution of Get took 00:00:00.0039383.]
Run Code Online (Sandbox Code Playgroud)
注释掉拦截代码并使用Action过滤器我获得了亚毫秒的性能:
[Execution of Get took 00:00:00.0001146.]
[Execution of Get took 00:00:00.0001116.]
[Execution of Get took 00:00:00.0001364.]
Run Code Online (Sandbox Code Playgroud)
这取决于你是否真的是一个问题或关注,但我想我会指出这一点.
以前的回应
你有没有使用ActionFilters?这是MVC操作上AOP的自然扩展点.
如果您对控制器上的实际操作以外的其他方法感兴趣,那么我会理解,但我认为无论如何我都会发布一个建议.
灵感来自ActionFilterAttributes是否跨线程重复使用?这是如何运作的?并测量时间调用ASP.NET MVC控制器操作.
更新以显示方法标记时排除计时器.核心WebApi框架的灵感来自AllowAnonymousAttribute和AuthorizeAttribute
全局注册,以便通过以下方式监控所有操作:
GlobalConfiguration.Configuration.Filters.Add(new TimingActionFilter());
Run Code Online (Sandbox Code Playgroud)
然后:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
和
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
public class NoLogAttribute : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)
现在您可以使用以下方法排除全局过滤器
public class ExampleController : ApiController
{
// GET api/example
[NoLog]
public Example Get()
{
//
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
19038 次 |
最近记录: |