I have an action method without parameters.
The QueryString
collection contain all of my values. The keys of the QueryString
match my view model properties.
var queryStringValueProvider = new QueryStringValueProvider(ControllerContext);
var providerResult = queryStringValueProvider.GetValue(ValidationKeys.Id); // ?!
var viewModelTypeName = queryString[ValidationKeys.ViewModelType];
var viewModelType = Type.GetType(viewModelTypeName);
var viewModelInstance = providerResult.ConvertTo(viewModelType); // throws an InvalidOperationException
How can I convert the QueryString
collection to a view model?
ASP.NET MVC already do this when you just pass the view model into the action method parameters. So what I need is an afterwards model binding using ASP.NET MVC mechanics.
My Controller Action
var viewModelTypeName = queryString[ValidationKeys.ViewModelType];
var viewModelType = Type.GetType(viewModelTypeName);
var instance = Activator.CreateInstance(viewModelType);
UpdateModelUsingQueryString(instance);
UpdateModel
protected internal void UpdateModelUsingQueryString<TModel>(TModel model) where TModel : class
{
if (model == null) throw new ArgumentNullException("model");
Predicate<string> propertyFilter = propertyName => new BindAttribute().IsPropertyAllowed(propertyName);
var binder = Binders.GetBinder(typeof(TModel));
var bindingContext = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()),
ModelState = ModelState,
PropertyFilter = propertyFilter,
ValueProvider = new QueryStringValueProvider(ControllerContext)
};
binder.BindModel(ControllerContext, bindingContext);
}
The problem was that UpdateModel
or TryUpdateModel
does not work for object
by design.
Both methods use typeof(TModel)
. But you have to use model.GetType()
.
Take a look at: Model Binding - Type in External Assembly
Darin Dimitrov gave the right answer :)