为什么MVC4 validate js会自动给datetime添加数字验证?
Why does MVC4 validate js auto adds number validation to datetime?
我最近升级到 MVC 4 并使用 validate.js 和 validate.unobtrosive.js 进行客户端验证。从 MVC 4 开始,我注意到 html 输出发生了变化。
MVC3:
<input class="dutchDate date_datepicker hasDatepicker" id="FirstDate" name="FirstDate" type="text" value="18-02-2015">
MVC4:
<input class="dutchDate date_datepicker hasDatepicker" data-val="true" data-val-number="Waarde moet numeriek zijn" id="FirstDate" name="FirstDate" type="text" value="18-02-2015">
所以现在日期时间字段通过我的自定义验证和数字验证得到验证。我不明白为什么要将数字验证添加到输入标签中。有人有过同样的经历吗?我不想对我的日期输入进行数字验证。
型号:
public class TripFilter : IResultFilter
{
...
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime? FirstDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime? UntilDate { get; set; }
...
}
渲染:
@Html.TextBox("", dt.ToString("dd-MM-yyyy"), new { @class = ViewData["class"] + " dutchDate date_datepicker", @type = "text" }
编辑
在全局 asax 中进行一些检查后,我注意到以下行:
ModelValidatorProviders.Providers.Add(new ClientNumberValidatorProvider());
执行以下操作:
public class ClientNumberValidatorProvider : ClientDataTypeModelValidatorProvider
{
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
bool isNumericField = base.GetValidators(metadata, context).Any();
if (isNumericField)
yield return new ClientSideNumberValidator(metadata, context);
}
}
public class ClientSideNumberValidator : ModelValidator
{
public ClientSideNumberValidator(ModelMetadata metadata,
ControllerContext controllerContext)
: base(metadata, controllerContext) { }
public override IEnumerable<ModelValidationResult> Validate(object container)
{
yield break; // Do nothing for server-side validation
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
yield return new ModelClientValidationRule
{
ValidationType = "number",
ErrorMessage = Resources.Global.InvalidField
};
}
}
看来这是添加号码验证的原因。现在让我困惑的是,为什么这只发生在 DateTime 字段而不是 String 字段?
我遇到了类似的问题,通过添加
解决了
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
到 Application_Start
在 Global.asax.cs
这适用于所有值类型 - string
不是值类型,DateTime
是。您不需要更改 ClientNumberValidatorProvider
MVC 4 正在生成这些属性,因为您使用的是在您 web.config:
中设置的非侵入式验证
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
您可以在 web.config 中将这些属性设置为 false :
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />
但我想你真的想在客户端验证你的日期所以你必须使用 @Html.TextBoxFor
而不是 @Html.TextBox
@Html.TextBoxFor(m=>m.FirstDate)
或者甚至更好地在 Views/Shared/EditorTemplates
下创建一个名为 DateTime.cshtml
的模板,然后使用 @Html.EditorFor(m=>m.FirstDate)
模板可能是这样的(带有适当的标记和属性):
@model DateTime?
@{
var value = "";
const string format = "{0:yyyy-MM-dd HH:mm}";
if (Model.HasValue) {
value = string.Format(format, Model.Value);
}
}
<label class="form-group">
<i class="glyphicon glyphicon-calendar"></i>
@Html.TextBox("", null,
new
{
@class = "form-control date", placeholder = ViewData.ModelMetadata.DisplayName ?? ViewData.ModelMetadata.PropertyName,
data_format = "dd/mm/yy HH:ii P",
data_initial_value = value
})
</label>
EditFor
帮助程序将自动推断您正在传递的 属性 的类型,并在本例中使用称为类型的模板 DateTime
。
请注意,模板也使用 @model DateTime?
键入,这也允许处理空日期。
我已经通过调整 ClientNumberValidatorProvider 解决了我的问题。现在看起来像这样:
public class ClientNumberValidatorProvider : ClientDataTypeModelValidatorProvider
{
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)
});
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (numericTypes.Contains(metadata.ModelType))
yield return new ClientSideNumberValidator(metadata, context);
}
}
如果模型的 属性 是 HashSet 中的一种类型,它只会 return ClientSideNumberValidator。感谢 Peter Smith 为我指出了赖特的方向。 MicroSoft 也使用 HashSet:ClientDataTypeModelValidatorProvider.cs
我最近升级到 MVC 4 并使用 validate.js 和 validate.unobtrosive.js 进行客户端验证。从 MVC 4 开始,我注意到 html 输出发生了变化。
MVC3:
<input class="dutchDate date_datepicker hasDatepicker" id="FirstDate" name="FirstDate" type="text" value="18-02-2015">
MVC4:
<input class="dutchDate date_datepicker hasDatepicker" data-val="true" data-val-number="Waarde moet numeriek zijn" id="FirstDate" name="FirstDate" type="text" value="18-02-2015">
所以现在日期时间字段通过我的自定义验证和数字验证得到验证。我不明白为什么要将数字验证添加到输入标签中。有人有过同样的经历吗?我不想对我的日期输入进行数字验证。
型号:
public class TripFilter : IResultFilter
{
...
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime? FirstDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime? UntilDate { get; set; }
...
}
渲染:
@Html.TextBox("", dt.ToString("dd-MM-yyyy"), new { @class = ViewData["class"] + " dutchDate date_datepicker", @type = "text" }
编辑
在全局 asax 中进行一些检查后,我注意到以下行:
ModelValidatorProviders.Providers.Add(new ClientNumberValidatorProvider());
执行以下操作:
public class ClientNumberValidatorProvider : ClientDataTypeModelValidatorProvider
{
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
bool isNumericField = base.GetValidators(metadata, context).Any();
if (isNumericField)
yield return new ClientSideNumberValidator(metadata, context);
}
}
public class ClientSideNumberValidator : ModelValidator
{
public ClientSideNumberValidator(ModelMetadata metadata,
ControllerContext controllerContext)
: base(metadata, controllerContext) { }
public override IEnumerable<ModelValidationResult> Validate(object container)
{
yield break; // Do nothing for server-side validation
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
yield return new ModelClientValidationRule
{
ValidationType = "number",
ErrorMessage = Resources.Global.InvalidField
};
}
}
看来这是添加号码验证的原因。现在让我困惑的是,为什么这只发生在 DateTime 字段而不是 String 字段?
我遇到了类似的问题,通过添加
解决了DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
到 Application_Start
在 Global.asax.cs
这适用于所有值类型 - string
不是值类型,DateTime
是。您不需要更改 ClientNumberValidatorProvider
MVC 4 正在生成这些属性,因为您使用的是在您 web.config:
中设置的非侵入式验证 <appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
您可以在 web.config 中将这些属性设置为 false :
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />
但我想你真的想在客户端验证你的日期所以你必须使用 @Html.TextBoxFor
而不是 @Html.TextBox
@Html.TextBoxFor(m=>m.FirstDate)
或者甚至更好地在 Views/Shared/EditorTemplates
下创建一个名为 DateTime.cshtml
的模板,然后使用 @Html.EditorFor(m=>m.FirstDate)
模板可能是这样的(带有适当的标记和属性):
@model DateTime?
@{
var value = "";
const string format = "{0:yyyy-MM-dd HH:mm}";
if (Model.HasValue) {
value = string.Format(format, Model.Value);
}
}
<label class="form-group">
<i class="glyphicon glyphicon-calendar"></i>
@Html.TextBox("", null,
new
{
@class = "form-control date", placeholder = ViewData.ModelMetadata.DisplayName ?? ViewData.ModelMetadata.PropertyName,
data_format = "dd/mm/yy HH:ii P",
data_initial_value = value
})
</label>
EditFor
帮助程序将自动推断您正在传递的 属性 的类型,并在本例中使用称为类型的模板 DateTime
。
请注意,模板也使用 @model DateTime?
键入,这也允许处理空日期。
我已经通过调整 ClientNumberValidatorProvider 解决了我的问题。现在看起来像这样:
public class ClientNumberValidatorProvider : ClientDataTypeModelValidatorProvider
{
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)
});
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (numericTypes.Contains(metadata.ModelType))
yield return new ClientSideNumberValidator(metadata, context);
}
}
如果模型的 属性 是 HashSet 中的一种类型,它只会 return ClientSideNumberValidator。感谢 Peter Smith 为我指出了赖特的方向。 MicroSoft 也使用 HashSet:ClientDataTypeModelValidatorProvider.cs