对定制属性执行客户端验证


74

我创建了一个自定义验证属性:

public class FutureDateAttribute : ValidationAttribute
    {
        public override bool IsValid(object value) 
        {
            if (value == null|| (DateTime)value < DateTime.Now)
                return false;

            return true;
        }

    }

我如何使用jquery在客户端也能使用它?

Answers:


165

操作方法如下:

首先定义自定义验证属性:

public class FutureDateAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        if (value == null || (DateTime)value < DateTime.Now)
            return false;

        return true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "futuredate"
        };
    }
}

注意它如何实现IClientValidatable。接下来,我们编写模型:

public class MyViewModel
{
    [FutureDate(ErrorMessage = "Should be in the future")]
    public DateTime Date { get; set; }
}

然后是一个控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            // intentionally put in the past
            Date = DateTime.Now.AddDays(-1)
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

最后是一个视图:

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.Date)
    @Html.TextBoxFor(x => x.Date)
    @Html.ValidationMessageFor(x => x.Date)
    <input type="submit" value="OK" />
}

魔术发生的最后一部分是定义自定义适配器:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    // we add a custom jquery validation method
    jQuery.validator.addMethod('greaterThan', function (value, element, params) {
        if (!/Invalid|NaN/.test(new Date(value))) {
            return new Date(value) > new Date($(params).val());
        }
        return isNaN(value) && isNaN($(params).val()) || (parseFloat(value) > parseFloat($(params).val()));
    }, '');

    // and an unobtrusive adapter
    jQuery.validator.unobtrusive.adapters.add('futuredate', { }, function (options) {
        options.rules['greaterThan'] = true;
        options.messages['greaterThan'] = options.message;
    });
</script>

1
@raklos,这将取决于浏览器和服务器的本地化设置。如果存在差异,事情会变得复杂,因为一种格式可以通过客户端验证,但不能通过服务器验证,反之亦然。此外,它是由你来决定你想要什么格式的日期是英寸
达林季米特洛夫

我可以为此亲吻你
Shashank Shekhar

2
很好的例子。为了让我为客户端工作,需要将适配器更改return new Date(value) > new Date($(params).val()); return new Date(value) > new Date();新Date($(params).val())新Date()
PhilW 2012年

我在使用Ajax.BeginForm而不是Html.BeginForm使客户端工作时遇到问题。在这种情况下会出现问题吗?
user1790300

1
@kehrk,是的,如果您使用的是ASP.NET 4捆绑软件,则最好使其成为某些捆绑软件的一部分。
Darin Dimitrov 2013年

5

自问您的问题以来花了一段时间,但如果您仍然喜欢元数据,并且仍然愿意使用简化的替代方法,则可以使用以下注释解决问题:

[Required]
[AssertThat("Date > Now()")]
public DateTime? Date { get; set; }

开箱即用,适用于服务器和客户端。有关更多详细信息,请查看ExpressiveAnnotations库。


您在图书馆里度过了我的一天。使用简单,非常有用。谢谢
Maco 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.