使用 ModelState 进行依赖注入

Dependency Injection with ModelState

首先,我知道在服务中使用 ModelState 通常不受欢迎,因为它将服务与 Mvc 框架紧密耦合。在我们的例子中,这不是问题,但我最终确实计划迁移到 IValidationDictionary 和 ModelState 包装器,但现在需要这一步才能工作。

现在,关于这个问题,这位很酷的家伙:

public class BaseService : IBaseService
    {

      protected MIRTContext _context;
      protected IMapper _mapper;
      //TODO: This tightly couples .NET MVC to our services. 
      // Could be imporoved with an interface and a ModelState wrapper
      // in order to decouple.
      private ModelStateDictionary _modelState;

      public BaseService(
        MIRTContext context, 
        IMapper mapper,
        ModelStateDictionary modelState
      ) {
        _context = context;
        _mapper = mapper;
        _modelState = modelState;
      }

     async Task<bool> IBaseService.SaveContext() {
        if(_modelState.IsValid) {
          try {
            await _context.SaveChangesAsync();
            return true;
          }
          catch {
            return false;
          }
        }
        else {
          return false;
        }
      }
    }

它一直给我这个错误:

Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary' while attempting to activate

我假设我在 Startup.cs 的 ConfigureServices 中缺少某种 AddSingleton 东西,但我似乎无法弄清楚是什么。任何人都知道如何将其正确注入依赖项?

ModelState 无法通过依赖注入获得,但您可以使用 IActionContextAccessor, which provides access to the current ActionContext and its ModelState 属性.

首先,您需要为DI注册IActionContextAccessor

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

接下来,更新您的 BaseService class 以使用它:

public class BaseService : IBaseService
{
    // ...

    private readonly IActionContextAccessor _actionContextAccessor;

    public BaseService(
        // ...
        IActionContextAccessor actionContextAccessor
    ) {
        // ...
        _actionContextAccessor = actionContextAccessor;
    }

    async Task<bool> IBaseService.SaveContext() {
        var actionContext = _actionContextAccessor.ActionContext;

        if (actionContext.ModelState.IsValid) {
            // ...
        }
        else {
            return false;
        }
    }
}

请注意,如果对 SaveContext 的调用在 MVC 及其控制器、过滤器等之外,则上面的 actionContext 将是 null