Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 3.0 ModelBinder bindingContext.ValueProvider.GetValue(key) returns null when binding in a collection

I am new using custom ModelBinders, I have been looking around and I couldn't find any post related to this specific case.

I have an entity like:

 public class DynamicData
    {
       public IList<DynamicDataItem> DynamicDataItems{get;set;}
    }

In the View i bind it like follows:

@Html.EditorFor(model => model.DynamicDataItems);

I have special information in the class DynamicDataItems, that I would like to retrieve in a specific way, so I created my own Model Binder.

public class DynamicDataItemBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext,
            ModelBindingContext bindingContext)
        {
            var key = bindingContext.ModelName;
            var valueProviderResult = bindingContext.ValueProvider
                .GetValue(key);

            if (valueProviderResult == null ||
                string.IsNullOrEmpty(valueProviderResult
                    .AttemptedValue))
            {
                return null;
            }

            //Here retrieve my own Information

            return DynamicDataItem;
        }
    }

The bindingContext.ModelName contains "DynamicDataItem[0]".

If I do bindingContext.ValueProvider.ContainsPrefix(key), it returns true, but when I do GetValue(key), it returns null. If I inspect what the ValueProvider contains, I see that there is several items with their Key Starting in "DynamicDataItem[0]". How Am I supossed to retrieve the information from all the fields for the Item that is being binded currently ("DynamicDataItem[0]")? Should I retrieve them all one by one? Like this:

 var result1= bindingContext.ValueProvider.GetValue("DynamicDataItem[0].Id");
 var result2= bindingContext.ValueProvider.GetValue("DynamicDataItem[0].Name");

I will greatly appreciate any guidance you can give me with this.

like image 404
Dzyann Avatar asked Feb 07 '12 16:02

Dzyann


2 Answers

I know this is old post but I have the same problem and my solution was to use bindingContext.ModelName:

ValueProviderResult result = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
if(result == null)
    result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "." + propertyDescriptor.Name);
like image 191
Vangi Avatar answered Sep 18 '22 10:09

Vangi


The problem appears to be that your are trying to bind an object of type DynamicDataItem to an input. Since DynamicDataItem isn't a string or some other primitive type, there is no straightforward way for the binder to figure out what to do with your input and it returns null.

Assuming the class DynamicDataItem has properties of it's own what you want to do is provide editors for each property of a DynamicDataItem. If all you are trying to do is pass a model with a bound collection of child objects from a view, you don't even need a custom model binder. What I think you want is something in your view that reads more like this

<input type="text" name="DynamicDataItem[0].SomeTextField" />
<input type="text" name="DynamicDataItem[0].SomeOtherTextField" />

Check out Phil Haack and Scott Hanselman on the topic

Here and Here

I hope that helps

like image 36
TonyKC Avatar answered Sep 18 '22 10:09

TonyKC