如何从自定义中间件将依赖项传递到控制器?

时间:2018-07-17 10:29:48

标签: c# asp.net-core dependency-injection .net-core middleware

我有一个自定义的中间件,我想从中添加一个有范围的依赖项。

<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">
</head>
<body>
  <div class="row"> 
  <div class="col-md-12">
      <div class="col-md-3">
       <div class="form-group">
         <label for="reference">Reference</label>
             <div class="row">
              <div class="col-md-6">
             <input type="text" class="form-control" id="reference" name="reference" placeholder="Reference">
          <div class="input-error form-control-input" style="color: Red; display: none;">Person is required</div>
        </div>
        <div class="col-md-6">                  
          <div class="form-group">
            <label class="checkbox-inline">
              <input type="checkbox" value="">Option 1</label>
              <div class="input-error form-control-input" style="color: Red; display: none;">Demo is required
              </div>
          </div>
        </div> 
         </div> <!-- ROW CLOSING TAG -->
    </div>

  </div>
  </div>

这样我就可以在控制器中使用它:

public class MyMiddleware {
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext,
        IOptionsSnapshot<ApiClientHttpSettings> settings,
        IServiceCollection services)
    {
        services.AddScoped<ICustomer>(new Customer());

        await _next(httpContext);
    }
}

但是在中间件public class CustomerController : ControllerBase { public ControllerBase(ICustomer customer) { } } 中无法解析。 我想这样做是因为有很多逻辑可以解决所涉及的DI。

我也可以尝试在IServiceCollection内部进行操作,但随后我将无法访问每个请求所需的ConfigureServices

真的很感谢任何指向正确方向的指针。

2 个答案:

答案 0 :(得分:1)

  

我也可以尝试在ConfigureServices内部进行操作,但随后我将无法访问每个请求所需的IOptionsSnapshot<SupplyApiClientHttpSettings>设置。

在这里,您可以在自定义服务中访问IOptionsSnapshot。完整的来源是here in GitHub

创建设置类。

public class SupplyApiClientHttpSettings
{
    public string SomeValue { get; set; }
}

在配置中为其添加一个值(例如,在appsettings.json中)。

{
    "someValue": "Value from appsettings"
}

定义服务并将IOptionsSnapshot注入其中。

public class CustomerService
{
    private readonly SupplyApiClientHttpSettings settings;

    public CustomerService(IOptionsSnapshot<SupplyApiClientHttpSettings> options)
    {
        this.settings = options.Value;
    }

    public Customer GetCustomer()
    {
        return new Customer
        {
            SomeValue = settings.SomeValue
        };
    }
}

Startup中将您的配置,选项和服务连接在一起。

public class Startup
{
    IConfiguration Configuration;

    public Startup()
    {
        Configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<SupplyApiClientHttpSettings>(Configuration);
        services.AddScoped<CustomerService>();
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseMvcWithDefaultRoute();
    }
}

将服务注入您的控制器。使用该服务为客户提供最新的选项快照。

public class CustomerController : Controller
{
    private readonly CustomerService customerService;

    public CustomerController(CustomerService customerService)
    {
        this.customerService = customerService;
    }

    public IActionResult Index() 
    {
        return Json(customerService.GetCustomer());
    }
}

此处是完整来源in GitHub

答案 1 :(得分:0)

答案非常简单和接近。以下就是我要做的:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ICustomer>(provider => {
        var settings = Configuration.GetSection("ApiClientHttpSettings").Get<ApiClientHttpSettings>();
        return new Customer(settings.Name, settings.Age);
    });
}

上面为我勾选了所有框:

  1. 每个请求的新实例
  2. 能够在请求时读取更新的配置
  3. 根据自定义逻辑创建实例