【问题标题】:How to disable form validation for undisplayed fields in ASP .NET MVC如何禁用 ASP .NET MVC 中未显示字段的表单验证
【发布时间】:2015-04-30 23:01:54
【问题描述】:

在我看来,我有表单和两个字段集:modelA 和 modelB 输入字段。一些模型A 和模型B 字段是必需的,因此有一些验证机制(ValidationMessageFor)。例如,我想根据单选按钮显示 modelA 字段集或 modelB 字段集(现在我在 jQuery 和 css 显示属性中执行此操作)。我需要禁用对隐藏块中的字段的验证。我不应该只使用 css 来显示/隐藏功能吗?

例如:

型号:

public class ModelA
{
    [Required]
    public string FirstMidName { get; set; }

    [Required]
    public string LastName { get; set; }

    public string Position { get; set; }
}

public class ModelB
{
    [Required]
    public string Name { get; set; }

    public string IC { get; set; }
}

查看:

@using (Html.BeginForm())
{
    <div id="modelA-block">
        // inputs and validation for modelA
    </div>

    <div id="modelB-block">
        // inputs and validation for modelB
    </div>

    <input type="submit" value="Save" />
}

<script>
    $(function () {    
        $("#myRadioButton").change(function (arg) {
            var type= $(this).val();
            if (type== 1) {
                $("#modelA-block").css("display", "block");
                $("#modelB-block").css("display", "none");
            }
            if (type== 2) {
                $("#modelA-block").css("display", "none");
                $("#modelB-block").css("display", "block");
            }
        });
    });
</script>

【问题讨论】:

  • 创建 1 个包含属性的视图模型,包括一个将单选按钮绑定到的视图模型,并将 foolproof [RequiredIf] 或类似属性应用于属性。
  • 这很好,但我想我不能使用它,因为我使用复合模型(见下文),所以我看不到子模型的无线电属性。
  • 我的意思不是包含其他模型的模型。我的意思是包含所有属性的视图模型。在示例中,您显示了 5 个属性 - FirstMidNameLastNamePositionNameIC 以及要绑定到的单选按钮的附加属性。

标签: jquery asp.net-mvc validation


【解决方案1】:

创建复合模型:

public class CompositeModel
{
    public ModelA ModelA {get; set;}
    public ModelB ModelB {get; set;}
}

你的看法:

@model CompositeModel

@using (Html.BeginForm())
{
    <div id="modelA-block">
        // inputs and validation for modelA
        Html.TextBoxFor(m => m.ModelA.FirstMidName)

        <input type="submit" value="Save" /> <!-- moved inside of a block -->
    </div>
}

@using (Html.BeginForm())
{
    <div id="modelB-block">
        // inputs and validation for modelB
        Html.TextBoxFor(m => m.ModelB.FirstMidName)

        <input type="submit" value="Save" /> <!-- moved inside of a block -->
    </div>
}

// put your javascript here, create radio button outside form tag

在控制器中创建两个接受 ModelA 和 ModelB 的操作:

[HttpPost]
public ActionResult YourActionName([Bind(Prefix="ModelA")]ModelA model)
{
    //...
}

[HttpPost]
public ActionResult YourActionName([Bind(Prefix="ModelB")]ModelB model)
{
    //...
}

但我真的会从传统的验证转移到 that 之类的东西。

【讨论】:

  • 这是个好方法。我确实使用了复合模型之类的东西,但其中还有许多其他文件(地址、联系人等),这些文件对于两个模型(ModelA 和 ModelB)都很常见。所以我想我需要它保持一种形式。
  • 是什么让你这么想?为什么需要将它们保持在一种形式中?
  • 因为我有一个用于“Conact”的复合模型,它可以是 Company 或 Person,并且对于这两者都有许多其他常见属性,例如地址、电子邮件列表、电话列表等。但我认为你的方法是好的。所以我接受这个答案。非常感谢。
  • 为什么这个答案被接受了。它根本行不通!原因是第一个文本框生成name="ModelA.FirstMidName",但POST 方法接受ModelA 类型的参数。 Typeof ModelA 没有名为 ModelA 的复杂属性,而后者又包含名为 FirstMidName 的属性。绑定失败,模型将始终为null。 (其他形式和相关的 POST 方法同上)
  • 您可以通过添加 [Bind(Prefix="ModelA")] 来进行绑定,但这对于糟糕的设计来说是一个糟糕的解决方案。
【解决方案2】:

根据您的 cmets 一个模型是 Company 和另一个 Person,那么我建议您的 UI 是错误的,更好的方法是最初仅渲染单选按钮并使用 jquery 处理按钮 @987654325 @event 加载包含公司表单或人员表单的部分视图以进行编辑(如果您的问题说明了实际代码而不是一些伪代码,这将有所帮助)。

但是,如果您确实需要这种方法,则应使用包含要编辑的属性的视图模型以及 [RequiredIf] 属性。您可以下载foolproof nuget 包或编写自己的包(SO 上有很多示例,this article 很好地解释了使用客户端验证创建验证属性)

查看模型

public enum ContactType
{
  Person,
  Company
}
public class ContactVM
{
  public ContactType Type { get; set; }
  // Common properties such as for the address
  [Required(ErrorMessage = "Please enter ..")]
  public string Street { get; set; }
  ....
  // Specify properties for Person
  [Display(Name = "Last name")]
  [RequiredIf("Type", "Person", ErrorMessage="Please enter your last name")]
  public string LastName { get; set; }
  ....
  // Specify properties for Company
  [Display(Name = "Company name")]
  [RequiredIf("Type", "Company", ErrorMessage="Please enter your company name")]
  public string CompanyName { get; set; }
  ....
}

查看

@model yourAssembly.ContactVM
@using (Html.BeginForm())
{
  @Html.RadioButtonFor(m => m.Type, ContactType.Person, new { id = "Person" })
  <label for="Person">Person</label>
  @Html.RadioButtonFor(m => m.Type, ContactType.Company, new { id = "Company" })
  <label for="Company">Company</label>
  <div id="person-properties">
      // Controls specific to Person
      ....
  </div>
  <div id="common-properties">
      // Controls specific to Company
      ....
  </div>
  // Common controls
  ....
}

控制器

public ActionResult Create(ContactVM model)
{
  if (!ModelState.IsVald)
  {
    return View();
  }
  ContactType type = model.Type;
  if (type == ContactType.Person)
  {
    // Initialize a new instance of Person and map its properties from the view model, save and redirect
  }
  else
  {
    // Initialize a new instance of Company and map its properties from the view model, save and redirect
  }
}

【讨论】:

    【解决方案3】:

    @RomanPushkin,如果您将两个表单放在两个局部视图中,则不需要 Bind 属性,如下所示:

    _ModelAForm.cshtml部分:

    @model ModelA
    
    @using (Html.BeginForm("PostA", "Composite"))
    {
        @Html.TextBoxFor(m => m.FirstMidName)
        @Html.ValidationMessageFor(m => m.FirstMidName)
        <input type="submit" value="Save" />
    }
    

    _ModelBForm.cshtml部分:

    @model ModelB
    
    @using (Html.BeginForm("PostB", "Composite"))
    {
        @Html.TextBoxFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name)
        <input type="submit" value="Save" />
    }
    

    这里是视图:

    @model CompositeModel
    
    <div id="first-form-wrapper">
        @Html.Partial("_ModelAForm", Model.ModelA)
    </div>
    
    <div id="second-form-wrapper">
        @Html.Partial("_ModelBForm", Model.ModelB)
    </div>
    

    以及动作:

    public ActionResult PostA(ModelA modelA)
    {
        //..
    }
    
    public ActionResult PostB(ModelB modelB)
    {
        //..
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 2016-01-04
      • 2014-03-26
      • 1970-01-01
      • 2017-07-14
      • 2017-05-19
      • 1970-01-01
      相关资源
      最近更新 更多