首页 > 解决方案 > C# ASP .NET Web API 依赖注入将当前控制器的属性传递给服务类构造函数

问题描述

假设我有一个控制器类,它将服务类的实例作为其构造函数中的参数,通过依赖注入注入:

    [ApiController]
    [Route("api/[controller]")]
    public class StudentsController : ControllerBase
    {
        private readonly IStudentsService _studentsService;

        public StudentsController(IStudentsService studentsService)
        {
            _studentsService= studentsService;
        }

并假设注入的服务将 Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary 的实例作为构造函数中的参数,如下所示:

    public class StudentsService : IStudentsService
    {
        private ModelStateDictionary _modelStateDictionary;

        public StudentsService(ModelStateDictionary modelStateDictionary)
        {
            _modelStateDictionary = modelStateDictionary;
        }

有没有一种方法可以确保注入到 StudentsService 的构造函数中的 ModelStateDictionary 不仅仅是任何ModelStateDictionary,而是由实例化 StudentsService 的特定 StudentsController 使用的ModelStateDictionary?即与当前对我的 API 的请求相关联的控制器?

也许它看起来像这样Startup

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddScoped<IStudentsService, StudentsService>(provider => provider.DoSomethingCleverToEnsureThisServiceGetsTheModelStateDictionaryOfItsController()
            );

我希望这样做的原因是,我可以对服务层中的请求执行进一步验证,并使用其自己的 ModelStateDictionary 将验证错误传递回控制器。感谢您的任何建议!

标签: c#dependency-injectionasp.net-core-webapi

解决方案


在阅读了@Xerillio 提供的 StackOverflow 问题后,我学到了两件事:

  1. 我的问题的直接答案是使用IActionContextAccessor接口 Microsoft.AspNetCore.Mvc.Infrastructure将其注入服务,从而提供对控制器及其 ModelState 的引用:
public class StudentService : IStudentService
{
    private readonly ModelStateDictionary _modelState;

    public MyService(IActionContextAccessor actionContextAccessor)
    {
        _modelState = actionContextAccessor.Context.ModelState;
    }
  1. 但是尽管得到了这个直接的答案,但这仍然可能不是一件明智的事情。本教程是我最初使用的:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/models-data/validating-with-a-service-layer-cs

但它现在已经很老了,它从未兑现将服务与控制器完全分离的承诺。实现我想要的更好的方法可能是遵循@Tseng 提出的三个解决方案之一,在这里:

将 ModelState 注入服务

它非常令人信服地论证了为什么最好不要将服务层耦合到 ASP .NET MVC,这样它就可以跨桌面和控制台应用程序(以及其他应用程序)使用。

这就是我现在要做的,而不是坚持使用 Microsoft 教程。

我希望这可以帮助其他人解决这个问题。


推荐阅读