我正在尝试使用 Autofac 在 .Net Core 2.0 WebApi 应用程序上使用拦截,但我无法在 Controller 上成功。我尝试的是
首先,我创建了一个基本的 webapi,它有一个默认 Controller (ValuesController)。然后我设置 autofac 配置如下。项目运行没有任何错误,但拦截似乎没有运行。我做错了什么?
Startup.cs
public void ConfigureContainer(ContainerBuilder builder)
{
builder.Register(c => new CallLogger());
builder.RegisterType<ValuesController>()
.EnableClassInterceptors()
.InterceptedBy(typeof(CallLogger));
}
CallLogger.cs
public class CallLogger : IInterceptor
{
public CallLogger()
{
System.Console.WriteLine("XXXXX");
}
public void Intercept(IInvocation invocation)
{
Console.WriteLine($"Calling method {invocation.Method.Name} with parameters {(string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()))}... ");
invocation.Proceed();
Console.WriteLine("Done: result was {0}.", invocation.ReturnValue);
}
}
ValuesController.cs
[Route("api/[controller]")]
[Intercept(typeof(CallLogger))]
public class ValuesController : Controller
{
private readonly ITest _test;
public ValuesController(ITest test)
{
_test = test;
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id, [FromHeader(Name = "TenantId")] string tenantId)
{
_test.Log("asdasdasda");
return tenantId + " => " + id;
}
// POST api/values
[HttpPost]
public void Post([FromBody]string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
请您参考如下方法:
当使用类型拦截时,方法应该被声明为虚拟的
Under the covers,
EnableInterfaceInterceptors()creates an interface proxy that performs the interception, whileEnableClassInterceptors()dynamically subclasses the target component to perform interception of virtual methods.
Autofac documentation - Enable interception on types
即:
// GET api/values
[HttpGet]
public virtual IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
顺便说一句,您正在尝试拦截 ASP.net 核心 Controller 的方法。在这种情况下,Autofac 默认不解析 Controller
By default, ASP.NET Core will resolve the controller parameters from the container but doesn’t actually resolve the controller from the container. This usually isn’t an issue but it does mean:
- The lifecycle of the controller is handled by the framework, not the request lifetime.
- The lifecycle of controller constructor parameters is handled by the request lifetime.
- Special wiring that you may have done during registration of the controller (like setting up property injection) won’t work.
您必须添加 AddControllersAsServices 方法
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddControllersAsServices();
}
喜欢Steven在评论中提到,依靠中间件拦截 Controller 的方法调用可能更容易
