ModelBinder, сложные вложенные типы и интерфейсы - PullRequest
2 голосов
/ 15 апреля 2010

У меня есть сценарий, в котором мне нужно привязать к интерфейсу - чтобы создать правильный тип, у меня есть пользовательское связующее для модели, которое знает, как создать правильный конкретный тип (который может отличаться).

Однако созданный тип никогда не имеет правильно заполненных полей. Я знаю, что мне здесь не хватает чего-то ослепительно простого, но кто-нибудь может сказать мне, почему или, по крайней мере, что мне нужно сделать, чтобы связыватель модели продолжал свою работу а привязать свойства?

public class ProductModelBinder : DefaultModelBinder
{
    override public object BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof (IProduct))
        {
            var content = GetProduct (bindingContext);

            return content;
        }

        var result = base.BindModel (controllerContext, bindingContext);

        return result;
    }

    IProduct GetProduct (ModelBindingContext bindingContext)
    {
        var idProvider = bindingContext.ValueProvider.GetValue ("Id");
        var id = (Guid)idProvider.ConvertTo (typeof (Guid));

        var repository = RepositoryFactory.GetRepository<IProductRepository> ();
        var product = repository.Get (id);

        return product;
    }
}

Модель в моем случае - это сложный тип со свойством IProduct, и мне нужно заполнить его значениями.

Модель:

[ProductBinder]
public class Edit : IProductModel
{
    public Guid Id { get; set; }
    public byte[] Version { get; set; }

    public IProduct Product { get; set; }
}

1 Ответ

0 голосов
/ 26 апреля 2012

ModelBinder работает рекурсивно, поэтому вам нужно внедрить пользовательский связыватель модели, метод переопределения onCreate и BindModel.

protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
// get actual type of a model you want to create here
    return Activator.CreateInstance(type);
}

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    // here our CreateModel method will be called
    var model = base.BindModel(controllerContext, bindingContext);
    // we will get actual metadata for type we created in the previous line
    var metadataForItem = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
    // and then we need to create another binding context and start model binding once again for created object
    var newModelBindingContext = new ModelBindingContext
        {
            ModelName = bindingContext.ModelName,
            ModelMetadata = metadataForItem,
            ModelState = bindingContext.ModelState,
            PropertyFilter = bindingContext.PropertyFilter,
            ValueProvider = bindingContext.ValueProvider
        };
        return base.BindModel(controllerContext, newModelBindingContext);

}

Надеюсь, это поможет.

...