【问题标题】:Afterwards Model Binding in ASP.NET MVC: How to convert QueryString values into a view model?ASP.NET MVC 中的模型绑定:如何将 QueryString 值转换为视图模型?
【发布时间】:2012-06-23 21:23:54
【问题描述】:

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

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

【问题讨论】:

  • 这可能会回答您的问题。 stackoverflow.com/questions/627838/…
  • @Ademar 不,它没有。参数名称/属性名称仅在运行时已知。我尝试使用 RemoteAttribute 属性验证用户输入数据。我想要一个操作方法来处理应该是唯一的属性的远程验证。

标签: c# asp.net-mvc model-binding request.querystring value-provider


【解决方案1】:

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

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

【讨论】:

  • IoC 与我的问题有什么关系:o?
  • MVC 将使用您的 IoC 容器来解析模型绑定器。如果您创建自己的模型绑定器,则需要将其注册到您的 IoC 容器中。
  • 为什么我必须自己编写模型活页夹?
  • 如果您的 QueryString 中有任何数据无法与 DefaultModelBinder 绑定(例如,您可能希望在绑定之前进行一些计算),您将需要创建自己的模型绑定器以明确告诉 MVC 如何你的价值观应该映射到你的模型。如果 DefaultModelBinder 可以绑定您的值,那么您不需要创建自己的模型绑定器,并且正如许多人建议的那样,您可以在控制器上使用 UpdateModel 或 TryUpdateModel 方法。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    你可以使用TryUpdateModel

    public ContentResult TestAction()
    {
       var model = new MyModel();
    
       if(TryUpdateModel(model, new QueryStringValueProvider(ControllerContext)))
       {
          return Content("success");
       }
    
       return Content("failed");
    }
    

    【讨论】:

    • @Rookian 你问了一个问题,我给出了答案。尝试与否由您决定。
    • 如果您知道模型 TryUpdateModel 工作正常。但我不知道型号,但它的类型。
    • 您是否在模型绑定器中执行此过程?但我认为足够了解类型本身。你必须检查这个帖子prideparrot.com/blog/archive/2012/6/…
    【解决方案4】:

    我的控制器操作

    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);
    }
    

    问题在于 UpdateModelTryUpdateModel 在设计上不适用于 object。 两种方法都使用typeof(TModel)。但是你必须使用model.GetType()

    看看:Model Binding - Type in External Assembly

    达林·迪米特洛夫给出了正确的答案:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      相关资源
      最近更新 更多