0

我有一个没有参数的操作方法。

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 机制的事后模型绑定。

4

4 回答 4

0

我的控制器动作

var viewModelTypeName = queryString[ValidationKeys.ViewModelType];
var viewModelType = Type.GetType(viewModelTypeName);
var instance = Activator.CreateInstance(viewModelType);
UpdateModelUsingQueryString(instance);

更新模型

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或者TryUpdateModelobject按设计工作。两种方法都使用typeof(TModel). 但是你必须使用model.GetType().

看看:模型绑定 - 输入外部程序集

Darin Dimitrov 给出了正确的答案:)

于 2012-06-22T08:56:13.700 回答
0

要手动执行自定义模型绑定,请创建自定义模型绑定器(实现IModelBinder)并将其注册到您的 IoC 容器。

或者您可以this.UpdateModel在您的操作方法中调用。这应该将您的 ValueProvider(RouteData、Request.Form 集合和 QueryString)中的值绑定到您的模型。

于 2012-06-21T15:36:56.547 回答
0

你要求的是序列化。为了简单地做到这一点,您可以放置​​一个接受 QueryStringValueProvider 作为参数的构造函数重载,并且该构造函数负责根据提供者初始化模型的所有属性。如果你坚持使用字符串,你可以很容易地将这样的构造函数放入一个模型基类中,该基类可以被你的所有模型继承。

这也可以内置到扩展方法中,因此可以称为“按需”而不是在构造时。

于 2012-06-21T15:37:46.390 回答
0

你可以使用TryUpdateModel

public ContentResult TestAction()
{
   var model = new MyModel();

   if(TryUpdateModel(model, new QueryStringValueProvider(ControllerContext)))
   {
      return Content("success");
   }

   return Content("failed");
}
于 2012-06-21T17:24:01.643 回答