我有一个没有参数的动作方法。
QueryString
集合包含我的所有值。 QueryString
的键与我的视图模型属性匹配。
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
如何将QueryString
集合转换为视图模型?
当您将视图模型传递给操作方法参数时,ASP.NET MVC已经这样做了。所以我需要的是使用ASP.NET MVC机制的之后的模型绑定。
答案 0 :(得分:0)
要手动执行自定义模型绑定,请创建自定义模型绑定器(实现IModelBinder
)并将其注册到IoC容器中。
或者您可以在操作方法内部调用this.UpdateModel
。这应该将ValueProvider(RouteData,Request.Form集合和QueryString)中的值绑定到模型。
答案 1 :(得分:0)
您要求的是序列化。为简单起见,您可以将构造函数重载接受QueryStringValueProvider作为参数,并且构造函数负责根据提供程序初始化所有模型的属性。如果您坚持使用字符串,则可以非常轻松地将此类构造函数放入可由所有模型继承的模型基类中。
这也可以构建到扩展方法中,因此它可以被称为“按需”而不是构造。
答案 2 :(得分:0)
您可以使用TryUpdateModel
public ContentResult TestAction()
{
var model = new MyModel();
if(TryUpdateModel(model, new QueryStringValueProvider(ControllerContext)))
{
return Content("success");
}
return Content("failed");
}
答案 3 :(得分:0)
我的控制器操作
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);
}
问题在于UpdateModel
或TryUpdateModel
不适用于object
设计。
两种方法都使用typeof(TModel)
。但是你必须使用model.GetType()
。