问题
以下代码工作正常Server
,而非客户端。为什么?
当我提交表单时,控制转到BeAValidDate
函数以检查日期是否有效。有没有办法Validate
日期而不使用Fluent Validation
去服务器?
脚本
<script src="jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="jquery.validate.js" type="text/javascript"></script>
<script src="jquery.validate.unobtrusive.js" type="text/javascript"></script>
模型
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(x => x.FromDate)
.NotEmpty()
.WithMessage("Date is required!")
.Must(BeAValidDate)
.WithMessage("Invalid Date");
}
private bool BeAValidDate(String value)
{
DateTime date;
return DateTime.TryParse(value, out date);
}
}
控制器
public class PersonController : Controller
{
public ActionResult Index()
{
return View(new Person { FromDate = DateTime.Now.AddDays(2).ToString()});
}
[HttpPost]
public ActionResult Index(Person p)
{
return View(p);
}
}
查看
@using (Html.BeginForm("Index", "Person", FormMethod.Post))
{
@Html.LabelFor(x => x.FromDate)
@Html.EditorFor(x => x.FromDate)
@Html.ValidationMessageFor(x => x.FromDate)
<input type="submit" name="Submit" value="Submit" />
}
答案 0 :(得分:6)
使用Greater Then或Equal To Validator进行欺骗。适合我。
Global.asax - 应用程序启动事件
FluentValidationModelValidatorProvider.Configure(x =>
{
x.Add(typeof(GreaterThanOrEqualValidator),
(metadata, Context, rule, validator) =>
new LessThanOrEqualToFluentValidationPropertyValidator
(
metadata, Context, rule, validator
)
);
});
<强>模型强>
[Validator(typeof(MyViewModelValidator))]
public class MyViewModel
{
[Display(Name = "Start date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime StartDate { get; set; }
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime DateToCompareAgainst { get; set; }
}
<强>规则强>
public class MyViewModelValidator : AbstractValidator<MyViewModel>
{
public MyViewModelValidator()
{
RuleFor(x => x.StartDate)
.GreaterThanOrEqualTo(x => x.DateToCompareAgainst)
.WithMessage("Invalid start date");
}
}
<强> FluentValidationPropertyValidator 强>
public class GreaterThenOrEqualTo : FluentValidationPropertyValidator
{
public GreaterThenOrEqualTo(ModelMetadata metadata,
ControllerContext controllerContext,
PropertyRule rule,
IPropertyValidator validator)
: base(metadata, controllerContext, rule, validator)
{
}
public override IEnumerable<ModelClientValidationRule>
GetClientValidationRules()
{
if (!this.ShouldGenerateClientSideRules())
{
yield break;
}
var validator = Validator as GreaterThanOrEqualValidator;
var errorMessage = new MessageFormatter()
.AppendPropertyName(this.Rule.GetDisplayName())
.BuildMessage(validator.ErrorMessageSource.GetString());
var rule = new ModelClientValidationRule{
ErrorMessage = errorMessage,
ValidationType = "greaterthanorequaldate"};
rule.ValidationParameters["other"] =
CompareAttribute.FormatPropertyForClientValidation(
validator.MemberToCompare.Name);
yield return rule;
}
}
控制器操作方法
public ActionResult Index()
{
var model = new MyViewModel
{
StartDate = DateTime.Now.AddDays(2),
DateToCompareAgainst = default(DateTime) //Default Date
};
return View(model);
}
[HttpPost]
public ActionResult Index(Practise.Areas.FluentVal.Models.MyViewModel p)
{
return View(p);
}
查看强>
@using (Html.BeginForm("Index", "Person", FormMethod.Post,
new { id = "FormSubmit" }))
{
@Html.Hidden("DateToCompareAgainst", Model.DateToCompareAgainst);
@Html.LabelFor(x => x.StartDate)
@Html.EditorFor(x => x.StartDate)
@Html.ValidationMessageFor(x => x.StartDate)
<button type="submit">
OK</button>
}
<强>脚本强>
<script src="jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="jquery.validate.js" type="text/javascript"></script>
<script src="jquery.validate.unobtrusive.js" type="text/javascript"></script>
<script type="text/javascript">
(function ($) {
$.validator.unobtrusive.adapters.add('greaterthanorequaldate',
['other'], function (options) {
var getModelPrefix = function (fieldName) {
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
};
var appendModelPrefix = function (value, prefix) {
if (value.indexOf("*.") === 0) {
value = value.replace("*.", prefix);
}
return value;
}
var prefix = getModelPrefix(options.element.name),
other = options.params.other,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input[name=" + fullOtherName +
"]")[0];
options.rules['greaterthanorequaldate'] = element;
if (options.message != null) {
options.messages['greaterthanorequaldate'] = options.message;
}
});
$.validator.addMethod('greaterthanorequaldate',
function (value, element, params) {
var date = new Date(value);
var dateToCompareAgainst = new Date($(params).val());
if (isNaN(date.getTime()) || isNaN(dateToCompareAgainst.getTime())) {
return false;
}
return date >= dateToCompareAgainst;
});
})(jQuery);
</script>
答案 1 :(得分:0)
有些事我对你的设置和不起作用的东西都不了解。您是说日期必须有效的验证不起作用,或者日期所需的事实不起作用?
Fluent验证能够为不引人注目的验证发出代码,因此所需的约束应该正常工作。 日期有效这一事实完全是另一回事。如果你将FromDate指定为DateTime(你把它声明为DateTime还是字符串?),日期正确性的验证是由Mvc框架中包含的其他验证器自动执行的,所以你不需要在流利的情况下重复它验证规则。但是,在Mvc4之前,此验证检查仅在服务器端执行。通过Mvc 4,Asp.net Mvc团队解决了这个问题并在客户端扩展了检查。 但是,在客户端,一切只能用于en-US日期格式,因为不显眼的验证不能处理全球化。如果您需要在其他文化中使用日期,则需要使用Globalize library,并且您需要在客户端设置全球化。如果您对全球化感兴趣,可能会看到this post of my blog。 要向Mvc 3添加自动日期校正。您必须定义一个扩展的ClientDataTypeModelValidatorProvider,如Mvc4。代码下方:
public class ClientDataTypeModelValidatorProviderExt : ClientDataTypeModelValidatorProvider
{
public static Type ErrorMessageResources { get; set; }
public static string NumericErrorKey { get; set; }
public static string DateTimeErrorKey { get; set; }
private static readonly HashSet<Type> _numericTypes = new HashSet<Type>(new Type[] {
typeof(byte), typeof(sbyte),
typeof(short), typeof(ushort),
typeof(int), typeof(uint),
typeof(long), typeof(ulong),
typeof(float), typeof(double), typeof(decimal)
});
private static bool IsNumericType(Type type)
{
Type underlyingType = Nullable.GetUnderlyingType(type); // strip off the Nullable<>
return _numericTypes.Contains(underlyingType ?? type);
}
internal sealed class NumericModelValidator : ModelValidator
{
public NumericModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
: base(metadata, controllerContext)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
ModelClientValidationRule rule = new ModelClientValidationRule()
{
ValidationType = "number",
ErrorMessage = MakeErrorString(Metadata.GetDisplayName())
};
return new ModelClientValidationRule[] { rule };
}
private static string MakeErrorString(string displayName)
{
// use CurrentCulture since this message is intended for the site visitor
return String.Format(CultureInfo.CurrentCulture, ErrorMessageResources.GetProperty(NumericErrorKey, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).GetValue(null, null) as string, displayName);
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
// this is not a server-side validator
return Enumerable.Empty<ModelValidationResult>();
}
}
internal sealed class DateTimeModelValidator : ModelValidator
{
public DateTimeModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
: base(metadata, controllerContext)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
ModelClientValidationRule rule = new ModelClientValidationRule()
{
ValidationType = "globalizeddate",
ErrorMessage = MakeErrorString(Metadata.GetDisplayName())
};
return new ModelClientValidationRule[] { rule };
}
private static string MakeErrorString(string displayName)
{
// use CurrentCulture since this message is intended for the site visitor
return String.Format(CultureInfo.CurrentCulture, ErrorMessageResources.GetProperty(DateTimeErrorKey, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).GetValue(null, null) as string, displayName);
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
// this is not a server-side validator
return Enumerable.Empty<ModelValidationResult>();
}
}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (metadata == null)
{
throw new ArgumentNullException("metadata");
}
if (context == null)
{
throw new ArgumentNullException("context");
}
List<ModelValidator> res = null;
if (NumericErrorKey == null || ErrorMessageResources == null)
res = base.GetValidators(metadata, context).ToList();
else
{
res = new List<ModelValidator>();
if (IsNumericType(metadata.ModelType))
{
res.Add(new NumericModelValidator(metadata, context));
}
}
if ( (metadata.ModelType == typeof(DateTime) || metadata.ModelType == typeof(DateTime?)))
{
if(ErrorMessageResources != null && DateTimeErrorKey != null)
res.Add(new DateTimeModelValidator(metadata, context));
}
return res;
}
}
然后在global.asax中,你必须用这个代替标准的:
var old = ModelValidatorProviders.Providers.Where(x => x is ClientDataTypeModelValidatorProvider).FirstOrDefault();
if (old != null) ModelValidatorProviders.Providers.Remove(old);
ModelValidatorProviders.Providers.Add(new ClientDataTypeModelValidatorProviderExt());
现在你必须添加在客户端执行控制的javascript snipped:
$.validator.addMethod(
"globalizeddate",
function (value, element, param) {
if ((!value || !value.length) && this.optional(element)) return true; /*success*/
var convertedValue = Globalize.parseDate(value);
return !isNaN(convertedValue) && convertedValue;
},
"field must be a date/time"
);
我使用Globalize功能验证了正确的日期。安装它。这是使日期格式与.net格式兼容的唯一方法。此外,它适用于所有.net文化。使用标准的javascript日期解析,与某些浏览器中.Net接受的格式不兼容。
答案 2 :(得分:-1)
在下面的MVC 3中,代码应该可以正常工作。
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm("Index", "Person", FormMethod.Post))
{
@Html.LabelFor(x => x.FromDate)
@Html.EditorFor(x => x.FromDate)
@Html.ValidationMessageFor(x => x.FromDate)
<input type="submit" name="Submit" value="Submit" />
}
MVC 4中的简单工作示例
<强> _Layout.cshtml:强>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title - My ASP.NET MVC Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div id="body">
@RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
@RenderBody()
</section>
</div>
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
</body>
</html>
查看:强>
@model Mvc4Test.Models.Person
@{
ViewBag.Title = "test";
}
<h2>test</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Part</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
<强> For more details. 强>