How to use a custom model binding engine that supports dependency injection in ASP.NET Core?

I am trying to use a custom mediator in MVC that I want to resolve from my IoC container. The problem I am facing is that I cannot access my container while adding the MVC service, because my container has not been created yet (and I need to add MVC before creating my container). It feels like a chicken / egg problem, and I'm sure I miss a simple solution.

Example:

services.AddMvc().AddMvcOptions(options =>
{
     options.ModelBinders.Add(serviceProvider.Resolve<CustomModelBinder>());
});

My own connecting device is as follows:

public class CustomModelBinder : IModelBinder
{
    private IServiceProvider serviceProvider;

    public CustomModelBinder(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
    {
        var model = serviceProvider.GetService(bindingContext.ModelType);
        bindingContext.Model = model;

        var binder = new GenericModelBinder();
        return binder.BindModelAsync(bindingContext);
    }
}
+5
3

: https://github.com/aspnet/Mvc/issues/4167

, :

bindingContext.OperationBindingContext.ActionContext.HttpContext.RequestServices

, [FromServices], .

+3

ASP.NET Core 2.2 DI:

public class CustomModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        // dependency injection
        var model = bindingContext.HttpContext.RequestServices.GetService(bindingContext.ModelType);

        // other changes...

        bindingContext.Result = ModelBindingResult.Success(model);

        return Task.CompletedTask;
    }
}
0

, , IConfigureOptions . , .

, ICustomService:

class CustomModelBinder : IModelBinder
{
    private readonly ICustomService customService;

    public CustomModelBinder(ICustomService customService) => this.customService = customService;

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        // Use customService during model binding.
    }
}

:

class CustomModelBinderProvider : IModelBinderProvider
{
    private readonly ICustomService customService;

    public CustomModelBinderProvider(ICustomService customService) => this.customService = customService;

    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        // Return CustomModelBinder or null depending on context.
        return new CustomModelBinder(customService);
    }
}

Startup :

services.AddMvc().AddMvcOptions(options =>
{
    options.ModelBinderProviders.Add(new CustomModelBinderProvider(customService));
});

, , . customService . IConfigureOptions , :

class CustomModelBinderConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
    private readonly ICustomService customService;

    public CustomModelBinderConfigureMvcOptions(ICustomService customService) => this.customService = customService;

    public void Configure(MvcOptions options)
        => options.ModelBinderProviders.Add(new CustomModelBinderProvider(customService));
}

Startup

services.AddSingleton<IConfigureOptions<MvcOptions>, CustomModelBinderConfigureMvcOptions>();

.

0

All Articles