0

I'm following along at Model binder for abstract class in asp.net core mvc 2, but my model doesn't bind the HostedControls in ConcreteControlHost (see below). If I change the type of HostedControls to ConcreteControlText[], it does bind. I'd like to keep it as AbstractControl[] so that I can host multiple types of control.

I know the abstract binder is working because MainModel.Controls binds.

While debugging the binding of ConcreteControlHost, binder._propertyBinders has an entry for HostedControls as follows:
{[ModelMetadata (Property: 'ConcreteControlHost.HostedControls' Type: 'AbstractControl[]'), {Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder<MyProject.AbstractControl>}]} Following that property (Value.ElementBinder.Inner) eventually leads to AbstractModelBinder.

Breakpoints in AbstractModelBinder are not hit when binding the properties of ConcreteControlHost, but are when binding the properties of MainModel (as in, I get the hits for ConcreteControlHost, but not for ConcreteControlText).

This isn't related to In an Editor Template call another Editor Template with the same Model because it isn't the same model, and because everything renders correctly, it just doesn't bind. None of the ConcreteControlTexts referenced by HostedControls are referenced directly by MainModel.Controls.

public class MainModel {
   public AbstractControl[] Controls;
}

public abstract class AbstractControl {
   public string TypeName { get; set;}
}

public class ConcreteControlText: AbstractControl {
   public string Text { get; set; }
}

public class ConcreteControlHost: AbstractControl {
   public AbstractControl[] HostedControls { get; set; }
}

Does anyone see what I need to change to allow model-binding to work on ConcreteControlHost.HostedControls?

  • Your `IModelBinderProvider` would be the first thing to debug. Are you creating your `IModelBinder` for the correct types? You should post the source for both, and how you are configuring them on startup. – Jeremy Lakeman Jul 09 '20 at 01:40
  • Looks like ArrayModelBinder will silently skip an array that is not null. Is there any chance that ConcreteControlHost will create an array before binding has completed? https://github.com/aspnet/Mvc/blob/master/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs – Jeremy Lakeman Jul 09 '20 at 01:48

1 Answers1

0

Turns out in my actual code, HostedControls had { get; private set; }. Removing the private modifier on the setter made it work.

Jeremy, thanks for looking into this.