1

Is it possible to create custom model binder for nested inherited objects? I saw this article https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-5.0, but my case is more difficult, my objects are very complex.

For example, I have this simple structure:

First level

public class Top
{
    public string Value { set; get; }

    public IEnumerable<MiddleBase> MiddleClasses { set; get; }
}

Second level

public abstract class MiddleBase
{
    public ConcreteMiddleType Type { set; get; }

    public IEnumerable<BottomBase> BottomClasses { set; get; }
}

public class ConcreteMiddle1 : MiddleBase
{
    public string Value1 { set; get; }
}

public class ConcreteMiddle2 : MiddleBase
{
    public string Value2 { set; get; }
}

Third Level

public abstract class BottomBase
{
    public ConcreteBottomType Type { set; get; }
}

public class ConcreteBottom1 : BottomBase
{
    public string Value1 { set; get; }
}

public class ConcreteBottom2 : BottomBase
{
    public string Value2 { set; get; }
}

if I handle request I get error, I can't bind base abstract class.

Did anybody have experience with such issue?

  • Kinda makes sense since you cannot instantiate abstract classes. One possible (naive) solution could be is to maintain list of your concrete types. But I guess that would kinda beat the purpose of you inheritance, since every time you add a type you'll need to add a list, and some code to put the correct elements in the list. To be honest I think you best drop the whole inheritence stuff when passing data to the view and map all your object to some kind of view model which holds all properties of all your implementations and a discriminator – Jochem Van Hespen Oct 14 '21 at 13:50
  • It would be better if you provided more details about how you used these classes in your controllers – AndrewSilver Oct 15 '21 at 10:43

1 Answers1

-1

If you really want your base classes to be abstract, you can create a custom ModelBinder and override how the base is handled using bindingContext.MetaData. Here's an example:

MVC 3 Model Binding a Sub Type (Abstract Class or Interface)

Edit: In .net core, the model binder will need to extend IModelBinder interface and a custom IModelBinderProvider will need to be registered when configuring service on startup. The IModelBinderProvider will check for your model type and pass your IModelBinder in its GetBinder function. From your custom IModelBinder, you can access the bindingContext, which has everything you need to deserialize the abstract members of the view model.

Replacing DefaultModelBinder in ASP.net MVC core

  • Thanks for your advise. If I'm right .net core has different mechanism of binding and there is no DefaultModelBinder in .net core – Konstantin Shutko Oct 14 '21 at 15:39
  • Seems like you could implement the IModelBinder and IModelBinderProvider that will pass your custom model binder for your class type. In that case, you'd still have access to the bindingContext like in the preevious example. Here's something similar: https://stackoverflow.com/questions/50893324/replacing-defaultmodelbinder-in-asp-net-mvc-core – Adam Osmond Oct 14 '21 at 17:51