Skip to main content
 首页 » 编程设计

c#之使用 Autofac 拦截 .NET Core 2.0 Web API Controller

2024年02月04日33lori

我正在尝试使用 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, 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 核心 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.

Autofac documentation - Controllers as services

您必须添加 AddControllersAsServices 方法

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

喜欢Steven在评论中提到,依靠中间件拦截 Controller 的方法调用可能更容易