简体   繁体   中英

Custom model binder for complex model with collection of polymorphic objects

How can I write custom model binder for complex model with collection of polymorphic objects?

I have the next structure of models:

public class CustomAttributeValueViewModel
{
    public int? CustomAttributeValueId { get; set; }
    public int CustomAttributeId { get; set; }
    public int EntityId { get; set; }
    public CustomisableTypes EntityType { get; set; }
    public string AttributeClassType { get; set; }
}

public class CustomStringViewModel : CustomAttributeValueViewModel
{
    public string Value { get; set; }
}

public class CustomIntegerViewModel : CustomAttributeValueViewModel
{
    public int Value { get; set; }
}

And if I want to bind CustomAttributeValueViewModel to some of it's inheritors, I use such custom model binder:

public class CustomAttributeValueModelBinder : DefaultModelBinder
{
    protected override object CreateModel(
        ControllerContext controllerContext,
        ModelBindingContext bindingContext,
        Type modelType)
    {
        if (modelType == typeof(CustomAttributeValueViewModel))
        {
            var attributeClassType = (string)bindingContext.ValueProvider
                .GetValue("AttributeClassType")
                .ConvertTo(typeof(string));

            Assembly assembly = typeof(CustomAttributeValueViewModel).Assembly;
            Type instantiationType = assembly.GetType(attributeClassType, true);

            var obj = Activator.CreateInstance(instantiationType);
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
            bindingContext.ModelMetadata.Model = obj;
            return obj;
        }

        return base.CreateModel(controllerContext, bindingContext, modelType);
    }
}

It works great. But now I want to bind such models as items of collection of another model. For instance:

public class SomeEntity
{
    // different properties here

    public IList<CustomAttributeValueViewModel> CustomAttributes { get; set; }
}

How can I do that?

EDITED:

I want to bind a posted data which I received from a client. For more clarity it is an example of my POST HTTP request:

POST someUrl HTTP/1.1
User-Agent: Fiddler
Host: localhost
Content-Type: application/json; charset=utf-8
Content-Length: 115

{
  "ProductName": "Product Name",
  "CustomAttributeValues": [
    {
      "CustomAttributeId": "1",
      "Value": "123",
      "AttributeClassType": "namespace.CustomStringViewModel"
    }
  ]
}

And I receive this data in my action:

public void Save([ModelBinder(typeof(SomeBinder))] SomeEntity model)
{
    // some logic
}

I want to write such binder for getting collection of inheritors.

You need to include full path to the AttributeClassType ,

var valueProviderResult = bindingContext.ValueProvider
                            .GetValue(bindingContext.ModelName + ".AttributeClassType");

please take a look at this working Github sample

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM