MVC 3.0 - 不显眼的客户端验证不适用于自定义属性
问题描述:
我是mvc 3.0和jquery的新手。我试图在客户端和服务器端使用自定义验证属性验证'日期'。它在服务器端运行良好,但无法使其在客户端工作。MVC 3.0 - 不显眼的客户端验证不适用于自定义属性
上午使用mvc 3.0,jquery,IE 7.0。 我们是否需要在MVC 3.0中的global.ascx中注册任何东西?
请让我知道我错了。 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; }
答
有几个问题我可以用你的代码中看到。第一招:
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";
在你有一对夫妇的问题,以及客户端。在您的验证方法中,您似乎在做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);
}
}
非常感谢Darin,它的工作:) – HKGR 2012-02-21 05:32:22
@DarinDimitrov什么将代替''错误信息到这里来''因为我总是得到相同的错误,而不是模型中定义的错误? – 2015-05-15 09:57:15
好的。了解。它将是'String.Format(ErrorMessage,metadata.GetDisplayName(),this.Min)' – 2015-05-15 10:27:47