MVC 3.0 - ненавязчивая проверка на стороне клиента не работает для пользовательских атрибутов - PullRequest
1 голос
/ 20 февраля 2012

Я новичок в MVC 3.0 и JQuery.я пытаюсь проверить «дату» как на стороне клиента, так и на стороне сервера, используя настроенные атрибуты проверки.Он работает нормально на стороне сервера, но не может заставить его работать на стороне клиента.

использую mvc 3.0, jquery, IE 7.0.Нужно ли регистрировать что-либо в global.ascx в MVC 3.0?

Пожалуйста, дайте мне знать, где я ошибаюсь.TIA.

Вот мой код:

Атрибут проверки

 public class FutureDateAttribute : ValidationAttribute, IClientValidatable
 {
        private const string DateFormat = "mm/dd/yyyy";
        private const string DefaultErrorMessage = "'{0}' must be a date between {1:d} and current date.";

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

        public FutureDateAttribute(string min)
            : base(DefaultErrorMessage)
        {
            Min = ParseDate(min);
            Max = DateTime.Now;
        }

        public override bool IsValid(object value)
        {
            if (value == null || !(value is DateTime))
            { return true; }
            DateTime dateValue = (DateTime)value;
            return Min <= dateValue && dateValue <= Max;
        }

        private static DateTime ParseDate(string dateValue)
        {
            return DateTime.ParseExact(dateValue, DateFormat, System.Globalization.CultureInfo.InvariantCulture);
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(System.Globalization.CultureInfo.CurrentCulture, ErrorMessageString, name, Min);
        }

        public class ModelClientValidationFutureDateRule : ModelClientValidationRule
        {
            public ModelClientValidationFutureDateRule(string errorMessage,
                DateTime min)
            {
                ErrorMessage = errorMessage;
                ValidationType = "futuredate";
                ValidationParameters["min"] = min.ToString("mm/dd/yyyy");
                ValidationParameters["max"] = DateTime.Now.ToString("mm/dd/yyyy");
            }
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationFutureDateRule("Error message goes here", this.Min);
            yield return rule;
        }

jquery

(function ($) {
$.validator.addMethod('futuredate', function (value, element, param) {
    if (!value) return false;
    var min = $(param.min).val();
    var max = $(param.max).val();
    if (value < min || value > max) {
        return false;
    }
    return true;
});

$.validator.unobtrusive.adapters.add(
  'futuredate', ['min', 'max'],
  function (options) {
      var params = {
          min: options.params.min,
          max: options.params.max
      };

      options.rules['futuredate'] = params;
      if (options.message) {
          options.messages['futuredate'] = options.message;
      }
  });
} (jQuery)); 

Рекомендации

<script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.js")" type="text/javascript"></script>
<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>
 ///reference path="jquery-1.5.1.min.js" />
 ///reference path="jquery.validate.js" />
 ///reference path="jquery-ui-1.8.11.js" />
  ///reference path="jquery.validate.unobtrusive.min.js" />
 ///reference path="jquery.validate-vsdoc.js" />

Модель:

[DisplayName("Assigned Date :")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
    [Required(ErrorMessage = "Assigned Date is required")]
    [DataType(DataType.Date)]
    [FutureDate("12/31/1899", ErrorMessage = "'{0}' must be a date between {1:d} and current date.")]
    public DateTime? AssignedDate { get; set; }

1 Ответ

2 голосов
/ 20 февраля 2012

Я вижу несколько проблем с вашим кодом.Первое:

ValidationParameters["min"] = min.ToString("mm/dd/yyyy");
ValidationParameters["max"] = DateTime.Now.ToString("mm/dd/yyyy");

действительно должно быть:

ValidationParameters["min"] = min.ToString("MM/dd/yyyy");
ValidationParameters["max"] = DateTime.Now.ToString("MM/dd/yyyy");

, потому что mm означает минуты, а не месяцы.

То же самое замечание для:

private const string DateFormat = "mm/dd/yyyy";

, который должен быть:

private const string DateFormat = "MM/dd/yyyy";

На стороне клиента у вас также есть пара проблем.В вашем методе проверки futuredate вы, похоже, делаете var min = $(param.min).val();, что переводится как var min = $('12/31/1899').val();, что, очевидно, не имеет особого смысла.Вам нужно будет проанализировать эти значения в javascript Date экземплярах, прежде чем вы сможете их сравнить.

Итак, вот что я бы вам предложил:

@model MyViewModel

<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">
    (function ($) {
        var parseDate = function (str) {
            var m = str.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
            return (m) ? new Date(m[3], m[1] - 1, m[2]) : null;
        };

        $.validator.addMethod('futuredate', function (value, element, param) {
            if (!value) return false;

            var min = parseDate(param.min);
            var max = parseDate(param.max);
            var current = parseDate(value);

            if (min == null || max == null || current == null) {
                return false;
            }

            return (current >= min && current <= max);
        });

        $.validator.unobtrusive.adapters.add('futuredate', ['min', 'max'], function (options) {
            var params = {
                min: options.params.min,
                max: options.params.max
            };

            options.rules['futuredate'] = params;
            if (options.message) {
                options.messages['futuredate'] = options.message;
            }
        });
    } (jQuery));
</script>

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.AssignedDate)
    @Html.EditorFor(x => x.AssignedDate)
    @Html.ValidationMessageFor(x => x.AssignedDate)
    <button type="submit">OK</button>
}

и вотполный код атрибута проверки, который я использовал для моего теста:

public class FutureDateAttribute : ValidationAttribute, IClientValidatable
{
    private const string DateFormat = "MM/dd/yyyy";
    private const string DefaultErrorMessage = "'{0}' must be a date between {1:d} and current date.";

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

    public FutureDateAttribute(string min)
        : base(DefaultErrorMessage)
    {
        Min = ParseDate(min);
        Max = DateTime.Now;
    }

    public override bool IsValid(object value)
    {
        if (value == null || !(value is DateTime))
        { return true; }
        DateTime dateValue = (DateTime)value;
        return Min <= dateValue && dateValue <= Max;
    }

    private static DateTime ParseDate(string dateValue)
    {
        return DateTime.ParseExact(dateValue, DateFormat, System.Globalization.CultureInfo.InvariantCulture);
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(System.Globalization.CultureInfo.CurrentCulture, ErrorMessageString, name, Min);
    }

    public class ModelClientValidationFutureDateRule : ModelClientValidationRule
    {
        public ModelClientValidationFutureDateRule(string errorMessage,
            DateTime min)
        {
            ErrorMessage = errorMessage;
            ValidationType = "futuredate";
            ValidationParameters["min"] = min.ToString("MM/dd/yyyy");
            ValidationParameters["max"] = DateTime.Now.ToString("MM/dd/yyyy");
        }
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationFutureDateRule("Error message goes here", this.Min);
        yield return rule;
    }
}

и модель:

public class MyViewModel
{
    [DisplayName("Assigned Date :")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
    [Required(ErrorMessage = "Assigned Date is required")]
    [DataType(DataType.Date)]
    [FutureDate("12/31/1899", ErrorMessage = "'{0}' must be a date between {1:d} and current date.")]
    public DateTime? AssignedDate { get; set; }
}

и контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            AssignedDate = DateTime.Now.AddDays(2)
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...