【问题标题】:Data validation attribute for a condition between two properties asp.net mvc两个属性asp.net mvc之间条件的数据验证属性
【发布时间】:2014-09-05 09:05:11
【问题描述】:

我想在两个属性之间设置一个规则,即一个属性必须大于另一个。 那么可以让我这样做的数据验证属性是什么?

这是我的属性

  public int Min{get;set;}
  public int Max{get;set;} 

正如您可以轻松理解的那样,Max 必须大于 Min。

感谢您的帮助!

【问题讨论】:

  • 使用 jquery 代替模型验证
  • 我更喜欢模型验证我不知道如何处理 Jquery
  • 好吧..但据我了解 mvc 很难获得您的功能,唯一的方法是制作自定义验证属性,但使用 jquery 非常容易..
  • 好的,你能告诉我如何实现吗?
  • 这些 Min 和 Max 是文本框????

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


【解决方案1】:

对您的对象进行数据验证是一件好事(以及使用客户端验证)。

这是一个属性,您可以使用它来执行您所要求的操作(它将能够比较实现 IComparable 的类型对)

public class GreaterThanAttribute : ValidationAttribute
{

    public GreaterThanAttribute(string otherProperty)
        : base("{0} must be greater than {1}")
    {
        OtherProperty = otherProperty;
    }

    public string OtherProperty { get; set; }

    public string FormatErrorMessage(string name, string otherName)
    {
        return string.Format(ErrorMessageString, name, otherName);
    }

    protected override ValidationResult
        IsValid(object firstValue, ValidationContext validationContext)
    {
        var firstComparable = firstValue as IComparable;
        var secondComparable = GetSecondComparable(validationContext);

        if (firstComparable != null && secondComparable != null)
        {
            if (firstComparable.CompareTo(secondComparable) < 1)
            {
                object obj = validationContext.ObjectInstance;
                var thing = obj.GetType().GetProperty(OtherProperty);
                var displayName = (DisplayAttribute)Attribute.GetCustomAttribute(thing, typeof(DisplayAttribute));

                return new ValidationResult(
                    FormatErrorMessage(validationContext.DisplayName, displayName.GetName()));
            }
        }

        return ValidationResult.Success;
    }

    protected IComparable GetSecondComparable(
        ValidationContext validationContext)
    {
        var propertyInfo = validationContext
                              .ObjectType
                              .GetProperty(OtherProperty);
        if (propertyInfo != null)
        {
            var secondValue = propertyInfo.GetValue(
                validationContext.ObjectInstance, null);
            return secondValue as IComparable;
        }
        return null;
    }
}

然后你可以装饰你的模型:

  public int Min{get;set;}

  [GreaterThan("Min")]
  public int Max{get;set;}

这是一个关于小于验证的有用问题MVC custom validation: compare two dates,但适用于日期而不是整数,但同样的方法也适用

【讨论】:

  • 我个人喜欢这种方法。即使这些天来,每个人都可能启用了 javascript,但在客户端和服务器上执行验证仍然是最佳实践。如果你只打算在一个地方做,我仍然会在服务器端做。您可能应该这样做以及此答案下方的 JQuery 解决方案。
  • 谢谢!!你的帖子很有趣
  • 最佳实践提示:[GreaterThan(nameof(Min))]
  • 如果你想要一个 GreaterThanOrEqualAttribute ,请将 1 替换为 0
【解决方案2】:

您可以使用属性,或者您的视图模型可以实现 IValidatableObject。好在 asp.net mvc modelbinder 会在 post 上自动运行。

public class TestCompareModel : IValidatableObject
{
    [Required]
    public Int32 Low { get; set; }

    [Required]
    public Int32 High { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();

        if (High < Low)
            results.Add(new ValidationResult("High cannot be less than low"));

        return results;
    }
}

控制器动作:

    [HttpPost]
    public ActionResult Test(TestCompareModel viewModel)
    {
        if (!ModelState.IsValid)
            return View(viewModel);

        return RedirectToAction("Index");
    }

查看

@model Scratch.Web.Models.TestCompareModel

@{
    ViewBag.Title = "Test";
}

<h2>Test</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>TestCompareModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Low, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Low, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Low, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.High, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.High, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.High, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

【讨论】:

  • 这应该被标记为答案!它符合 DRY 并在客户端生成验证代码。我可以要求 POST,因为这种验证更多的是业务/域验证。编写的代码也少得多(没有新的属性类或向视图添加逻辑)。
【解决方案3】:

我同意 Exception,JQuery 比模型本身更容易使用来完成这种功能。然而,如果没有 Javascript/Jquery 的经验,那么值得看看 JQuery here 的文档。

您还可以找到很棒的教程here

最重要的部分,实际的 JQuery 库文件here。您可以下载该文件并将其包含在您的解决方案中,或者只需在您的视图标题中包含指向该文件的服务器托管 CDN 版本的链接。 (这两个选项都在我给你的链接上提供了说明)

但是,对异常答案的更新,您不包括在输入控件中只允许整数值所需的功能。要解决此问题,只需将输入类型属性更改为“数字”,如下所示。

<input type="number" id="Max" name="Max"  />

并修改脚本以将字符串解析为整数,如下所示:

$("#Max").focusout(function(){
      if( $(this).val() < $("#Min").val() )
      {
         $("#errormess").html('Max value cannot be lower then min Value');
      }
      else{ $("#errormess").html(''); }
   });

   $("#Min").focusout(function(){
      if( $(this).val() >= $("#Max").val() )
      {
         $("#errormess").html('Max value cannot be lower then min Value');
      }
      else{ $("#errormess").html(''); }
   });

【讨论】:

  • 非常感谢您的帮助!!
【解决方案4】:

您需要的功能可以使用 Jquery 轻松实现,如下所示:-

HTML :-

<input type="text" id="Max" name="Max"  />  //with model validations just make sure user can input numbers in Max and Min textboxes.
<input type="text" id="Min" name="Min" />
<div id="errormess"></div>

jquery:

$(document).ready(function(){
   $("#Max").focusout(function(){
      if(parseInt($(this).val()) < parseInt($("#Min").val()))
      {
         $("#errormess").html('Max value cannot be lower then Min Value');
      }
      else{ $("#errormess").html(''); }
   });

   $("#Min").focusout(function(){
      if(parseInt($(this).val()) > parseInt($("#Max").val()))
      {
         $("#errormess").html('Max value cannot be lower then Min Value');
      }
      else{ $("#errormess").html(''); }
   });
});

DEMO

【讨论】:

  • 感谢您的帮助例外情况现在更清楚了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多