Search code examples
c#asp.net-mvcpostdefaultmodelbindermodelbinder

Found property which wasn't bound from response body (form data) to model MVC, default model binder


I send post request and get in response body form data: 0[family]=Marco&0[name]=Polo&0[age]=66&1[family]=Family&0[name]=Name&0[age]=22

var formData = "0[family]=Marco&0[name]=Polo&0[age]=66&1[family]=Family&0[name]=Name&0[age]=22";
var data = new Dictionary<string, string>();
var preData = HttpUtility.ParseQueryString(formData);

foreach (string key in preData.AllKeys)
{
    if (key != null)
    {
        data.Add(Replace(key), preData[key]);
    }
}

I have model:

public class User {
  public string Family {get;set;}
  public int Age {get;set;}
}

For bind I use DefaultModelBinder:

private static bool TryUpdateModel(User user, IDictionary<string, string> formdata, ModelStateDictionary modelState) where TModel : class
{
    var binder = new DefaultModelBinder();

    var valueProvider = new DictionaryValueProvider<string>(formdata, CultureInfo.InvariantCulture);

    var bindingContext = new ModelBindingContext
    {
        ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => user, typeof(User)),
        ModelState = modelState,
        PropertyFilter = propertyName => true,
        ValueProvider = valueProvider
    };

    var ctx = new ControllerContext();
    binder.BindModel(ctx, bindingContext);
    return modelState.IsValid;
}
  • I want to know that I have data in responce "0[name]=Polo" which didn't bind to model User. Property "Name" don't exist in model User.
  • I want know if in response was more data then we can bind.

How I can do it?


Solution

  • You still need to compare the Model to the form data in each case so you could try something like the below:

    public bool HasAdditionalVals<TModel>(TModel model, IDictionary<string, string> formData)
    {
        var propsNameList = new List<string>();
        var propsList = typeof(TModel).GetProperties().ToList();
        propsList.ForEach(p => propsNameList.Add(p.Name.ToLower()));
    
        var keysList = formdata.Keys.ToList()
        var additionalProps = keysList.Except(propsNameList);
        return additionalProps.Count() > 0;
    }
    

    You could then call this within your 'TryUpdateModel' or wherever you need to check if the form data has more properties than the model you are trying to bind to. Just to note though that this is reliant on the form data keys being in lower case. If not you will have to ensure that they are before calling 'keysList.Except(propsNameList)'.