MVC2 客户端验证日期时间?

发布于 2024-09-14 20:29:40 字数 742 浏览 4 评论 0原文

您建议采用什么方法在 MVC 客户端验证 DateTime?

假设我有一个模型,其属性名为 DateOfBirth,它是一个 DateTime,如下所示。

public class UserModel
{
    [DataType(DataType.Date)]
    public DateTime DateOfBirth {get;set;}
}

在视图上,我有一个简单的方法

<%: Html.LabelFor(model=>model.DateOfBirth) %>
<%: Html.EditorFor(model=>model.DateOfBirth) %>
<%: Html.ValidationMessageFor(model=>model.DateOfBirth) %>
<input type="submit" value="Submit" />

,可以使用 Microsoft MVC 验证或 jQuery 验证。如何获取 DateTime 来验证客户端?

我意识到 DataTypeAttribute 所做的只是提供格式提示,并没有真正执行任何验证(它将该部分留给 ModelBinder)。

基本上,我想复制 ModelBinder 在尝试将发布的值放入模型的 DateOfBirth 属性中时所做的操作。

您有什么建议?

What approach do you recommend for validating a DateTime on the client side in MVC?

Let's say I have a model with a property named DateOfBirth that is a DateTime, like so.

public class UserModel
{
    [DataType(DataType.Date)]
    public DateTime DateOfBirth {get;set;}
}

On the View, I have a simple

<%: Html.LabelFor(model=>model.DateOfBirth) %>
<%: Html.EditorFor(model=>model.DateOfBirth) %>
<%: Html.ValidationMessageFor(model=>model.DateOfBirth) %>
<input type="submit" value="Submit" />

I can use either the Microsoft MVC validations or the jQuery validations. How do I get the DateTime to validate client-side?

I realize all the DataTypeAttribute does is provide formatting hints and doesn't really do any validation (it leaves that part to the ModelBinder).

Basically I want to duplicate what the ModelBinder does when it tries to put the posted value into the model's DateOfBirth property.

What are your recommendations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦境 2024-09-21 20:29:40

如上所述,请遵循 Phil Haack 关于自定义验证的帖子: http: //haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

这是我的做法:


  1. 添加一个“DateFormatAttribute”类,如下所示:

    public class DateFormatAttribute : ValidationAttribute {
      public override bool IsValid(object value) {    
        if (value == null) {
          return true;
        }

        // Note: the actual server side validation still has to be implemented :-)
        // Just returning true now...

        return true;
      }
    }

  1. 添加一个“DateFormatValidator”类,如so:

    public class DateFormatValidator : DataAnnotationsModelValidator 
    {
      string message;

      public PriceValidator(ModelMetadata metadata, ControllerContext context
        , DateFormatAttribute attribute)
        : base(metadata, context, attribute) 
      {
        message = attribute.ErrorMessage;
      }

      public override IEnumerable GetClientValidationRules() 
      {
        var rule = new ModelClientValidationRule {
          ErrorMessage = message,
          ValidationType = "date" // note that this string will link to the JavaScript function we'll write later on
        };

        return new[] { rule };
      }
    }

  1. 在 Global.asax.cs 中的某处注册上述类:

    DataAnnotationsModelValidatorProvider
        .RegisterAdapter(typeof(DateFormatAttribute), typeof(DateFormatValidator));

  1. 在客户端添加验证功能。请注意,这必须根据用户的区域设置来实现。以下是荷兰语(nl-NL,nl-BE)客户端验证函数:

    /*
     * Localized default methods for the jQuery validation plugin.
     * Locale: NL
     */
    jQuery.extend(jQuery.validator.methods, {
        date: function(value, element) {
            return this.optional(element) || /^\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?$/.test(value);
        }
    });

这应该涵盖一些内容......

As suggested above, follow Phil Haack's post on custom validations: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

Here's how I would do it:


  1. Add a "DateFormatAttribute" class, like so:

    public class DateFormatAttribute : ValidationAttribute {
      public override bool IsValid(object value) {    
        if (value == null) {
          return true;
        }

        // Note: the actual server side validation still has to be implemented :-)
        // Just returning true now...

        return true;
      }
    }

  1. Add a "DateFormatValidator" class, like so:

    public class DateFormatValidator : DataAnnotationsModelValidator 
    {
      string message;

      public PriceValidator(ModelMetadata metadata, ControllerContext context
        , DateFormatAttribute attribute)
        : base(metadata, context, attribute) 
      {
        message = attribute.ErrorMessage;
      }

      public override IEnumerable GetClientValidationRules() 
      {
        var rule = new ModelClientValidationRule {
          ErrorMessage = message,
          ValidationType = "date" // note that this string will link to the JavaScript function we'll write later on
        };

        return new[] { rule };
      }
    }

  1. Register the above classes somewhere in Global.asax.cs:

    DataAnnotationsModelValidatorProvider
        .RegisterAdapter(typeof(DateFormatAttribute), typeof(DateFormatValidator));

  1. Add a validation function on the client. Note that this will have to be implemented attributng the locale of the user. The following is a Dutch (nl-NL, nl-BE) client-side validation function:

    /*
     * Localized default methods for the jQuery validation plugin.
     * Locale: NL
     */
    jQuery.extend(jQuery.validator.methods, {
        date: function(value, element) {
            return this.optional(element) || /^\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?$/.test(value);
        }
    });

That should cover things...

苄①跕圉湢 2024-09-21 20:29:40

Josh,

你的问题是 MVC 中的一个常见问题,即 modelbinder 试图将表单中的输入值绑定到模型中。显然,如果它不“适合”,您会立即收到错误消息。

那么如何让 modelbinder 使用我的自定义验证呢?并返回我的错误消息?

好吧,首先阅读并执行 phil haack 写的东西。然后你就有了自定义验证。

接下来的事情是。不要在模型中使用整数和日期时间!
如果用户可以在文本框中输入他想要的任何内容,这总是会出现问题。

你应该做的是,为你的对象创建一个平面对象。

flatObject 非常简单。它是一个对象,内部变量的精确副本,只是,inst和日期时间是字符串(因为它们总是绑定在模型绑定器中)

示例:

namespace MVC2_NASTEST.Models {

    public partial class FlatNieuw {
        public int Niw_ID { get; set; }
        public string Niw_Datum { get; set; }
        public string Niw_Titel { get; set; }
        public string Niw_Bericht { get; set; }
        public int Niw_Schooljaar { get; set; }
        public bool Niw_Publiceren { get; set; }
    }
}

我唯一拥有的整数来自下拉列表,因为如果值在下拉菜单是整数。
日期(数据)是一个字符串。我对此字符串进行自定义验证。
modelbinder 绑定到此 FlatNieuw 对象。

我的 Nieuw 类具有与此类完全相同的字段名称。因此,当您使用 UpdateModel() 时,这仍然有效。
如果您正在创建一个新条目,则可以使用 automapper 将此 flatObject 映射到您的普通对象。

我认为这篇文章和 phil haack 的博客应该可以帮助您了解如何做到这一点。如果您有疑问,请随时提问。

Josh,

your problem is quite a common problem in MVC, which is that the modelbinder is trying to BIND the inputted values from the form into the model. obviously, if it doesnt 'fit' you'll get an error straight away.

so how do I make the modelbinder use my custom validation? and return my error message?

well, first read and do the things written by phil haack. then you have your custom validation.

the next thing is. dont use Integers and datetimes in your model!
If the user can input whatever he wants in a textbox, this always will give problems.

what you should do is, make a flatObject of your object.

a flatObject is pretty simple. It's an object, an exact copy of the variables inside, only, the inst and datetimes are strings (cos those always bind in the modelbinder)

example:

namespace MVC2_NASTEST.Models {

    public partial class FlatNieuw {
        public int Niw_ID { get; set; }
        public string Niw_Datum { get; set; }
        public string Niw_Titel { get; set; }
        public string Niw_Bericht { get; set; }
        public int Niw_Schooljaar { get; set; }
        public bool Niw_Publiceren { get; set; }
    }
}

the only ints i have are from the dropdowns, cos those dont fail, if the value in the dropdowns are ints.
the date (datum) is a string. i do the custom validation on this string.
the modelbinder binds to this FlatNieuw object.

my Nieuw class has exactly the same names of fields as this class. so when you are using UpdateModel() this still works.
if you are making a new entry, you can use automapper to map this flatObject to your normal Object.

i think this, together with phil haack's blog should give you a hand on how to do this. if you have questions dont hesitate to ask.

南汐寒笙箫 2024-09-21 20:29:40

我遇到了同样的问题,找不到解决方案。我不敢相信每个人都没有遇到过这个问题。我正在使用 jquery.maskedinput.js 模块,它工作得很好,但是当我开始使用“EditorFor”添加“[DataType(DataType.Date)]”装饰时,如果为日期时间输入分配了一个 class="text-box 类单线”。添加此类会破坏 maskedinput js。
它还将我的较低日期格式化为“2/3/1010”,然后破坏了我的“99/99/9999”的 jquery 掩码。

I am up against the same issue and can not find a solution. I can't believe everyone has not run into this issue. I was using the jquery.maskedinput.js module and it worked great, but when I started adding the "[DataType(DataType.Date)]" decoration with "EditorFor" if assigns the datetime input a class of class="text-box single-line". Adding this class breaks the maskedinput js.
It also formats my lower dates as "2/3/1010" which then blows my jquery mask of "99/99/9999".

海之角 2024-09-21 20:29:40

根据我的经验,有时 Microsoft MVC 验证或 jQuery 验证对于我们正在开发的某些项目来说是一种过度的杀伤力。这就是为什么有时我自己编码/抓取小东西的原因。

解决方案一:
在您的视图上自定义插件(您可以将其更改为适合您的方式)

(function($) {
    $.fn.extend({
            ValidateInput: function() {
                var bValid = true;
                this.removeClass('ui-state-error');
                this.each(function() {
                    if ($(this).hasClass('date')) {

                            var valdate = checkRegexp($(this), /^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[1-2]\d{3})$/, "date format is wrong, please input as dd/MM/yyyy, e.g. 02/28/2010");
                            if (!valdate) {
                                $(this).val("input in 'dd/mm/yyyy' format");
                            }
                            bValid = bValid && valdate;
                return bValid;

                        }
                }); 

    }});

    function checkRegexp(o, regexp, n) {
        if (!(regexp.test(o.val()))) {
            o.addClass('ui-state-error');
            //updateTips(n);
            return false;
        } else {
            return true;
        }
        }

 })(jQuery);

  1. 将 class='date' 添加到您的输入
    盒子
  2. 调用插件
    $("#yourInput").alidateInput();

解决方案 2: 使用 Jquery UI Date Pick(我现在使用的解决方案)

     <script language="javascript" type="text/javascript">
            $(function() {
// use date picker to your textbox input 
                $(".yourInput").datepicker();
                $(".yourInput").datepicker('option', { dateFormat: "dd/mm/yy" });
// disable any human input to the textbox input
                $(".yourInput").keyup(function() {
                    $(this).val("");
                });
            });
        </script>

有关解决方案 2 的更多详细信息:http:// /www.gregshackles.com/2010/03/templated-helpers-and-custom-model-binders-in-asp-net-mvc-2/

according to my experience some times either Microsoft MVC validations or the jQuery validations is a over kill for some projects that we are developing. that is why some times i code/grab small ones by my self.

Solution One:
Custom plugin(you can change it into the way suits you)

(function($) {
    $.fn.extend({
            ValidateInput: function() {
                var bValid = true;
                this.removeClass('ui-state-error');
                this.each(function() {
                    if ($(this).hasClass('date')) {

                            var valdate = checkRegexp($(this), /^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[1-2]\d{3})$/, "date format is wrong, please input as dd/MM/yyyy, e.g. 02/28/2010");
                            if (!valdate) {
                                $(this).val("input in 'dd/mm/yyyy' format");
                            }
                            bValid = bValid && valdate;
                return bValid;

                        }
                }); 

    }});

    function checkRegexp(o, regexp, n) {
        if (!(regexp.test(o.val()))) {
            o.addClass('ui-state-error');
            //updateTips(n);
            return false;
        } else {
            return true;
        }
        }

 })(jQuery);

on your view:

  1. add class='date' to your input
    box
  2. call the plugin
    $("#yourInput").alidateInput();

Solution 2: Use Jquery UI Date Pick (the solution i am using now)

     <script language="javascript" type="text/javascript">
            $(function() {
// use date picker to your textbox input 
                $(".yourInput").datepicker();
                $(".yourInput").datepicker('option', { dateFormat: "dd/mm/yy" });
// disable any human input to the textbox input
                $(".yourInput").keyup(function() {
                    $(this).val("");
                });
            });
        </script>

More Details on Solution 2: http://www.gregshackles.com/2010/03/templated-helpers-and-custom-model-binders-in-asp-net-mvc-2/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文