使用 Autofac 在 .NET Core 2.0 Web API 控制器上拦截

Interception on .NET Core 2.0 Web API Controller By Using Autofac

我正在尝试使用 Autofac 在 .Net Core 2.0 WebApi 应用程序上使用拦截,但我无法在控制器上成功。我尝试的是

首先,我创建了一个基本的 webapi,它有一个默认控制器 (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, while EnableClassInterceptors() 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 核心控制器的方法。在这种情况下,默认情况下 Autofac 不会解析控制器

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.

Autofac documentation - Controllers as services

你必须添加 AddControllersAsServices 方法

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddMvc()
        .AddControllersAsServices();
}

并且像 Steven 在评论中提到的那样,依靠中间件来拦截控制器的方法调用可能更容易