In .NET Core 3 I extended ComplexTypeModelBinder
class to create custom model binder for a specific class.
Main target was to override creation of model instance via CreateModel
method.
public MyModelBinder: ComplexTypeModelBinder
{
// Constructor here...
protected override object CreateModel(ModelBindingContext bindingContext)
{
// Create model instance based on custom condition.
}
}
After an upgrade to .NET 5, I'm receiving a compilation warning to replace ComplexTypeModelBinder
with ComplexObjectModelBinder
:
warning CS0618: 'ComplexTypeModelBinder' is obsolete: 'This type is obsolete and will be removed in a future version. Use ComplexObjectModelBinder instead.'
The problem is that ComplexObjectModelBinder
is sealed class and CreateModel
method is internal
, so subclass approach cannot work any more.
The solution I settled for is to create class MyModelBinder
which implement IModelBinder
interface and acts as a wrapper around ComplexObjectModelBinder
. ComplexObjectModelBinder
is passed in MyModelBinder
as constructor parameter.
Same approach is used for MyModelBinderProvider
and ComplexObjectModelProvider
.
Later, instead of overriding CreateMethod
of ComplexObjectModelBinder
, which is not possible in .NET 5, just assign bindingContext.Model
in the wrapper method BindAsyncModel
of MyModelBinder
, before passing the bindingContext
to ComplexObjectModelBinder
's BindAsyncModel
. This will make ComplexObjectModelBinder
use model that is passed in, instead of creating default new instance.
public class MyModelBinder: IModelBinder
{
private readonly ComplexObjectModelBinder _binder;
public MyModelBinder(ComplexObjectModelBinder binder)
{
_binder = binder;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
MyModel myModel = // custom instantiation logic here
bindingContext.Model = myModel;
return _binder.BindModelAsync(bindingContext);
}
}
For the registration of the custom model binder provider, first we find existing, automatically registered ComplexObjectBinderProvider
, use it in costructor of MyModelBinderProvider
and then insert MyModelBinderProvider
in front of ComplexObjectBinderProvider
.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options => {
// more configurations here...
var bindingProvider = options.ModelBinderProviders.First(provider =>
provider is ComplexObjectModelBinderProvider) as ComplexObjectModelBinderProvider;
var indexOf = options.ModelBinderProviders.IndexOf(bindingProvider);
options.ModelBinderProviders.Insert(indexOf, new MyModelBinderProvider(bindingProvider));
}
}