一个视图中的两个模型,仅验证其中一个

Posted

技术标签:

【中文标题】一个视图中的两个模型,仅验证其中一个【英文标题】:Two Models in One View, Validate only one of them 【发布时间】:2012-06-24 15:15:55 【问题描述】:

我有一个包含 ParentModel 的视图,其中包含 2 个模型。 我只想验证一个或另一个的字段。不是都。 假设我有:

public ParentModel
  public BlueUser BlueUser get; set;
  public GreenUser GreenUser get; set;

所以用户选择他是 GreenUser 还是 BlueUser。每种类型的用户都有不同的字段,并且根据用户选择的用户类型,我只想验证该特定类型用户的字段。 如何做到这一点?

编辑: 两个表单/模型必须在同一个视图上,可能带有一些 JQuery 或 Partials?

【问题讨论】:

您总是可以为适当类型的用户构建一个表单 但是 2 个表单必须在同一个视图上......这就是客户想要的方式,他们甚至为我提供了 Illustrator 布局。 那么也许你应该编辑你的问题并提供更多信息.. 【参考方案1】:

使用htmlHelper<BlueUser> 创建一个表单,使用HtmlHelper<GreenUser> 创建另一个表单,并将它们发布到不同的操作。

首先,视图模型是:

@model ParentModel

然后使用HtmlHelperFor为每个子模型创建一个HtmlHelper:

@
   var blueHtml = Html.HtmlHelperFor(Model.BlueUser);
   var greenHtml = Html.HtmlHelperFor(Model.GreenUser);


@using (blueHtml.BeginForm("BluePost", null)) 
   @blueHtml.EditorForModel()


@using (greenHtml.BeginForm("GreenPost", null)) 
   @greenHtml.EditorForModel()

最后,在控制器中为每个表单创建不同的 POST 操作:

[HttpPost]
public ActionResult BluePost(BlueUser model) 
   ...


[HttpPost]
public ActionResult GreenPost(GreenUser model) 
   ...

扩展方法如下:

public static class HtmlHelperFactoryExtensions 

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper) 
      return HtmlHelperFor(htmlHelper, default(TModel));
   

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper, TModel model) 
      return HtmlHelperFor(htmlHelper, model, null);
   

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper, TModel model, string htmlFieldPrefix) 

      var viewDataContainer = CreateViewDataContainer(htmlHelper.ViewData, model);

      TemplateInfo templateInfo = viewDataContainer.ViewData.TemplateInfo;

      if (!String.IsNullOrEmpty(htmlFieldPrefix))
         templateInfo.HtmlFieldPrefix = templateInfo.GetFullHtmlFieldName(htmlFieldPrefix);

      ViewContext viewContext = htmlHelper.ViewContext;
      ViewContext newViewContext = new ViewContext(viewContext.Controller.ControllerContext, viewContext.View, viewDataContainer.ViewData, viewContext.TempData, viewContext.Writer);

      return new HtmlHelper<TModel>(newViewContext, viewDataContainer, htmlHelper.RouteCollection);
   

   static IViewDataContainer CreateViewDataContainer(ViewDataDictionary viewData, object model) 

      var newViewData = new ViewDataDictionary(viewData) 
         Model = model
      ;

      newViewData.TemplateInfo = new TemplateInfo  
         HtmlFieldPrefix = newViewData.TemplateInfo.HtmlFieldPrefix 
      ;

      return new ViewDataContainer 
         ViewData = newViewData
      ;
   

   class ViewDataContainer : IViewDataContainer 

      public ViewDataDictionary ViewData  get; set; 
   

【讨论】:

感谢 Max 的回答,很高兴了解 HtmlHelperFor 类。可悲的是,设计师给了我 html 标记,所以我不得不围绕它编写代码,即我无法将 HTML 代码分成两种形式。我得到的布局非常混乱。我最终使用流体验证来进行个案验证。谢谢!【参考方案2】:

解决方案 1

你所做的是使用依赖验证,它不是默认内置的,只有Compare属性,你可以构建自己的属性,如果单选按钮值是必需的,或者你可以使用类似Mvc.ValidationTookit的东西


解决方案 2

例如,当用户选择蓝色用户时,您使用 javascript 在表单提交事件中检查他选择了什么,具体取决于他选择的内容,您将引导他使用适当的模型作为参数传递的不同操作

【讨论】:

【参考方案3】:

服务器端实现

    您应该看到两个表单。

    每个表单都应该在发布时在控制器中执行不同的操作。

动画的客户端实现

    您可以使用任何您喜欢的 JavaScript 库来禁用一个表单,而另一个启用鼠标焦点。

【讨论】:

以上是关于一个视图中的两个模型,仅验证其中一个的主要内容,如果未能解决你的问题,请参考以下文章

两个模型表单一个视图表单验证不显示

如何对绑定到 mvc 中模型的相同属性的多个局部视图应用验证?

交叉验证和bootstrap在internal validation 中的应用

knockoutjs 验证,立即验证

viewmodel + Catel 上的验证

如何让模型验证与 Rails 中的视图层对话以提供简单的功能?