【问题标题】:Require one field or another需要一个或另一个字段
【发布时间】:2017-09-11 15:30:16
【问题描述】:

基本上我想弄清楚的是如何要求在视图中至少填写两个字段中的一个。

在我看来,我有两个名为 ISBN 和 ISBN13 的文本字段。用户填写哪一项并不重要,只要填写其中一项即可。

我不知道在这里做什么期望考虑编写自定义验证器,所以我想我会先问。我会包含一些代码,但由于它只是两个简单的字段,我认为这种解释会更好。

【问题讨论】:

  • 您可以对发布在此的答案进行一些小改动,以获得您想要的 stackoverflow.com/questions/11959431/…
  • 自定义代码在这里绝对合适。事实上,您甚至不需要自定义验证器;这是核心领域业务逻辑,而不仅仅是 UI 问题。在无效状态下创建实体应该是不可能的(例如,您可以在构造中放入 throwing-code 来验证这一点。在 UI 中单独的 javascript 验证将有助于为用户提供即时反馈
  • 当用户收到对他们问题的良好回答时,该用户可以选择“接受”回答。问题原作者已接受的答案旁边的彩色复选标记表示接受。
  • @SandRock 虽然你的回答非常好,但我最终却不是这样。我决定的解决方案是让模型本身执行验证。
  • @ChristopherJohnson 那么我建议您回答自己的问题,以帮助公众看到另一种替代解决方案。

标签: c# asp.net asp.net-mvc validationattribute


【解决方案1】:

使用数据注释,如果您想避免第三方,我认为这是一个不错的选择。跳过必需的属性并在仅具有 getter 的属性上设置规则:

public class EditModel
{
    public string ISBN { get; set; }
    public string ISBN13 { get; set; }
    
    [Range(1, Double.MaxValue, ErrorMessage = "At least one field must be given a value")]
    public int Count
    {
        get
        {
            var totalLength = 0;
            totalLength += ISBN?.Length ?? 0;
            totalLength += ISBN13?.Length ?? 0;
            return totalLength;
        }
    }
}

对于其他数据类型和特定属性,它可以像这样使用:

public class EditModel
{
    [MinLength(10)]
    public string ISBN { get; set; }
    [MinLength(13)]
    public string ISBN13 { get; set; }
    [MinLength(1)]
    public List<Guid> ISBNItems { get; set; }
    [Range(1, 100)]
    public int? SomeNumber { get; set; }
    
    [Range(1, Double.MaxValue, ErrorMessage = "At least one field must be given a value")]
    public int Count
    {
        get
        {
            var totalLength = 0;
            totalLength += ISBN?.Length ?? 0;
            totalLength += ISBN13?.Length ?? 0;
            totalLength += ISBNItems?.Count ?? 0;
            totalLength += SomeNumber ?? 0;
            return totalLength;
        }
    }
}

编辑:我只是想到了另一种方法,将 Count-property 替换为:

[RegularExpression("True|true", ErrorMessage = "At least one field must be given a value")]
public bool Any => ISBN != null || ISBN13 != null;

基本上都是一样的,只是检查属性不为空的getter。

【讨论】:

    【解决方案2】:

    .net 框架:万无一失

    .net 核心:FoolProof.Core

    [RequiredIfEmpty] 存在于新版本中。例如:

        [RequiredIfEmpty(dependentProperty: "ISBN", DependentPropertyDisplayName = "ISBN", ErrorMessage = "If ISBN is null then ISBN13 is require")]
    

    还有很多其他属性:

    [RequiredIf]
    [RequiredIfNot]
    [RequiredIfTrue]
    [RequiredIfFalse]
    [RequiredIfEmpty]
    [RequiredIfNotEmpty]
    [RequiredIfRegExMatch]
    [RequiredIfNotRegExMatch]
    

    查看参考点击this link

    【讨论】:

      【解决方案3】:

      我想在将更改保存到数据库之前,在创建部分中将类似的内容添加到您的控制器中。

      int countISBN = Product.ISBN.Count() + Product.ISBN13.Count();
      if (countISBN <= 9)
      {
          // Add in an error message.
          return View();
      }
      

      这将做的是计算两个字段中的字符,并将它们相加。如果它们的总和低于 10,则会引发错误。

      【讨论】:

        【解决方案4】:

        您可以在控制器操作中进行手动验证。 AddModelError 方法将帮助您使用验证堆栈。

        [HttpPost]
        public ActionResult Edit(EditModel model)
        {
            if (string.IsNullOrEmpty(model.ISBN) && string.IsNullOrEmpty(model.ISBN13))
            {
                var validationMessage = "Please provide ISBN or ISBN13.";
                this.ModelState.AddModelError("ISBN", validationMessage);
                this.ModelState.AddModelError("ISBN13", validationMessage);
            }
        
            if (!string.IsNullOrEmpty(model.ISBN) && !string.IsNullOrEmpty(model.ISBN13))
            {
                var validationMessage = "Please provide either the ISBN or the ISBN13.";
                this.ModelState.AddModelError("ISBN", validationMessage);
                this.ModelState.AddModelError("ISBN13", validationMessage);
            }
        
            if (this.ModelState.IsValid)
            {
                // do something with the model
            }
        
            return this.View(model);
        }
        

        有些人可能会说,验证查询不是控制器的责任。我认为控制器的职责是将网络请求适应域请求。因此,控制器可以具有验证逻辑。如果您没有域/业务层,那么这种考虑毫无意义。

        【讨论】:

          【解决方案5】:

          使用MVC Foolproof NuGet 包,然后您可以使用RequiredIf 属性,如下所示:

          [RequiredIf("ISBN==\"\"")] // backslash is used for escaping the quotes
          public string ISBN13 { get; set; }
          
          [RequiredIf("ISBN13==\"\"")]
          public string ISBN { get; set; }
          

          【讨论】:

            猜你喜欢
            • 2014-07-24
            • 1970-01-01
            • 2016-07-21
            • 1970-01-01
            • 1970-01-01
            • 2015-04-09
            • 1970-01-01
            • 2021-10-24
            • 2020-11-11
            相关资源
            最近更新 更多