- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个模型需要验证,问题是出生日期字段。它必须由 3 个下拉菜单组成(日、月、年)。
<div id="dob-editor-field" class="model-field-editor">
@Html.LabelFor(m => m.DateOfBirth, new { @class = "label-div" })
@Html.Telerik().DropDownList().Name("DobDay").BindTo((SelectList)ViewData["Days"]).HtmlAttributes(new {id = "DobDaySel"})
@Html.Telerik().DropDownList().Name("DobMonth").BindTo((SelectList)ViewData["Months"]).HtmlAttributes(new { id = "DobMonthSel"})
@Html.Telerik().DropDownList().Name("DobYear").BindTo((SelectList)ViewData["Years"]).HtmlAttributes(new { id = "DobYearSel" })
@Html.ValidationMessageFor(m => m.DateOfBirth)
</div>
在服务器端我这样做
[HttpPost]
public ActionResult Register(RegistrationModel regInfo, int DobDay, int DobMonth, int DobYear)
{
SetRegisterViewData(DobDay, DobMonth, DobYear);
if (DobDay == 0 || DobMonth == 0 && DobYear == 0)
{
ModelState.AddModelError("DateOfBirth", "Date of birth is required");
}
else
{
DateTime dt = new DateTime(DobYear, DobMonth, DobDay);
long ticks = DateTime.Now.Ticks - dt.Ticks;
int years = new DateTime(ticks).Year;
if (years < 18)
{
ModelState.AddModelError("DateOfBirth", "You must be at least 18");
}
}
if (ModelState.IsValid)
{
//register user
return RedirectToAction("Index", "Home");
}
return View(regInfo);
}
问题:
LE:我为日期创建了一个自定义模型 Binder ,如下所示:
public class DobModelBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.Name == "DateOfBirth")
{
DateTime dob = DateTime.MinValue;
var form = controllerContext.HttpContext.Request.Form;
int day = Convert.ToInt32(form["DobDay"]);
int month = Convert.ToInt32(form["DobMonth"]);
int year = Convert.ToInt32(form["DobYear"]);
if (day == 0 || month == 0 || year == 0)
{
SetProperty(controllerContext, bindingContext, propertyDescriptor, DateTime.MinValue);
}
else
{
SetProperty(controllerContext, bindingContext, propertyDescriptor, new DateTime(year, month, day));
}
}
else
{
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
}
我是这样注册的:
ModelBinders.Binders.Add(typeof(DateTime), new DobModelBinder());
我是这样使用的:
public ActionResult Register([ModelBinder(typeof(DobModelBinder))]RegistrationModel regInfo)
出生日期绑定(bind)得很好。
LE2:
我为出生日期创建了验证属性,如下所示:
public override bool IsValid(object value)
{
DateTime date = Convert.ToDateTime(value);
return date != DateTime.MinValue;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "dateRequired"
};
}
}
public class DateGraterThanEighteen : ValidationAttribute, IClientValidatable
{
public override bool IsValid(object value)
{
DateTime date = Convert.ToDateTime(value);
long ticks = DateTime.Now.Ticks - date.Ticks;
int years = new DateTime(ticks).Year;
return years >= 18;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "dateGraterThanEighteen"
};
}
}
我应用了这样的属性
[DateGraterThanEighteen(ErrorMessage="You must be at least 18")]
[DateRequired(ErrorMessage = "Date of birth is required")]
public DateTime DateOfBirth { get; set; }
LE3:
在客户端我这样做:
$(function () {
jQuery.validator.addMethod('dobRequired', function (value, element, params) {
if (!/Invalid|NaN/.test(new Date(value))) {
return true;
}
else {
return false;
}
}, '');
jQuery.validator.unobtrusive.adapters.add('dateRequired', {}, function (options) {
options.rules['dobRequired'] = true;
options.messages['dobRequired'] = options.message;
});
});
客户端验证似乎不起作用。我该如何修复它?我对这些适配器的工作方式有点困惑。
最佳答案
您可以使用自定义编辑器模板。
在讨论实现细节之前,让我们先看看最终的解决方案是什么样子的。
因此,我们可以有一个 View 模型(一如既往),用一些数据注释属性来装饰,指示我们想要附加到它的元数据:
public class MyViewModel
{
[DisplayName("Date of birth:")]
[TrippleDDLDateTime(ErrorMessage = "Please select a valid DOB")]
[Required(ErrorMessage = "Please select your DOB")]
[MinAge(18, ErrorMessage = "You must be at least 18 years old")]
public DateTime? Dob { get; set; }
}
那么我们就可以有一个 Controller :
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
return Content(
string.Format(
"Thank you for selecting your DOB: {0:yyyy-MM-dd}",
model.Dob
)
);
}
}
一个 View (~/Views/Home/Index.cshtml
):
@model MyViewModel
@using (Html.BeginForm())
{
@Html.EditorFor(x => x.Dob)
<button type="submit">OK</button>
}
以及相应的编辑器模板,它允许我们显示 3 个用于编辑日期时间字段的下拉列表,而不是简单的文本框 (~/Views/Shared/EditorTemplates/TrippleDDLDateTime.cshtml
):
@{
var now = DateTime.Now;
var years = Enumerable.Range(0, 150).Select(x => new SelectListItem { Value = (now.Year - x).ToString(), Text = (now.Year - x).ToString() });
var months = Enumerable.Range(1, 12).Select(x => new SelectListItem { Value = x.ToString("00"), Text = x.ToString() });
var days = Enumerable.Range(1, 31).Select(x => new SelectListItem { Value = x.ToString("00"), Text = x.ToString() });
var result = ViewData.ModelState[ViewData.TemplateInfo.HtmlFieldPrefix];
if (result != null)
{
var values = result.Value.RawValue as string[];
years = new SelectList(years, "Value", "Text", values[0]);
months = new SelectList(months, "Value", "Text", values[1]);
days = new SelectList(days, "Value", "Text", values[2]);
result.Value = null;
}
}
<div class="trippleddldatetime">
@Html.Label("")
@Html.DropDownList("", years, "-- year --")
@Html.DropDownList("", months, "-- month --")
@Html.DropDownList("", days, "-- day --")
@Html.ValidationMessage("")
</div>
现在让我们看看如何实现 [TrippleDDLDateTime]
属性:
public class TrippleDDLDateTimeAttribute : ValidationAttribute, IMetadataAware
{
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.TemplateHint = "TrippleDDLDateTime";
}
public override bool IsValid(object value)
{
// It's the custom model binder that is responsible for validating
return true;
}
}
注意该属性如何实现 IMetadataAware
接口(interface)允许我们将 View 模型属性与我们编写的自定义编辑器模板关联起来 (TrippleDDLDateTime.cshtml
)。
接下来是[MinAge]
属性:
public class MinAgeAttribute : ValidationAttribute
{
private readonly int _minAge;
public MinAgeAttribute(int minAge)
{
_minAge = minAge;
}
public override bool IsValid(object value)
{
if (value == null)
{
return true;
}
DateTime date = Convert.ToDateTime(value);
long ticks = DateTime.Now.Ticks - date.Ticks;
int years = new DateTime(ticks).Year;
return years >= _minAge;
}
}
最后一个难题是编写一个自定义模型绑定(bind)器,该绑定(bind)器将与用 [TrippleDDLDateTime]
属性修饰的属性关联,以便执行解析:
public class TrippleDDLDateTimeModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var metadata = bindingContext.ModelMetadata;
var trippleDdl = metadata.ContainerType.GetProperty(metadata.PropertyName).GetCustomAttributes(typeof(TrippleDDLDateTimeAttribute), true).FirstOrDefault() as TrippleDDLDateTimeAttribute;
if (trippleDdl == null)
{
return base.BindModel(controllerContext, bindingContext);
}
var prefix = bindingContext.ModelName;
var value = bindingContext.ValueProvider.GetValue(prefix);
var parts = value.RawValue as string[];
if (parts.All(string.IsNullOrEmpty))
{
return null;
}
bindingContext.ModelState.SetModelValue(prefix, value);
var dateStr = string.Format("{0}-{1}-{2}", parts[0], parts[1], parts[2]);
DateTime date;
if (DateTime.TryParseExact(dateStr, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
bindingContext.ModelState.AddModelError(prefix, trippleDdl.ErrorMessage);
return null;
}
}
请注意,如果字段未使用自定义属性修饰,绑定(bind)器如何简单地使用默认绑定(bind)器。这样,它就不会干扰我们不希望出现三重 ddl 行为的其他 DateTime 字段。模型绑定(bind)器将简单地与 Application_Start
中的 DateTime?
类型关联:
ModelBinders.Binders.Add(typeof(DateTime?), new TrippleDDLDateTimeModelBinder());
好的,到目前为止我们已经有了一个执行服务器端验证的解决方案。这始终是您应该开始的。因为在那里您也可以停下来并仍然拥有一个安全且工作的场所。
当然,如果您有时间,您现在可以通过实现客户端验证来改善用户体验。客户端验证不是强制性的,但它可以节省带宽并避免服务器往返。
因此,我们首先让 2 个自定义属性实现 IClientValidatable
接口(interface),这是启用不显眼的客户端验证的第一步。
[TrippleDDLDateTime]
:
public class TrippleDDLDateTimeAttribute : ValidationAttribute, IMetadataAware, IClientValidatable
{
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.TemplateHint = "TrippleDDLDateTime";
}
public override bool IsValid(object value)
{
// It's the custom model binder that is responsible for validating
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule();
rule.ErrorMessage = ErrorMessage;
rule.ValidationType = "trippleddldate";
yield return rule;
}
}
[最小年龄]
:
public class MinAgeAttribute : ValidationAttribute, IClientValidatable
{
private readonly int _minAge;
public MinAgeAttribute(int minAge)
{
_minAge = minAge;
}
public override bool IsValid(object value)
{
if (value == null)
{
return true;
}
DateTime date = Convert.ToDateTime(value);
long ticks = DateTime.Now.Ticks - date.Ticks;
int years = new DateTime(ticks).Year;
return years >= _minAge;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule();
rule.ErrorMessage = ErrorMessage;
rule.ValidationType = "minage";
rule.ValidationParameters["min"] = _minAge;
yield return rule;
}
}
好的,我们已经在这两个属性上实现了 GetClientValidationRules
。剩下的就是编写相应的不引人注目的适配器。
当然,这应该在单独的 javascript 文件中完成。例如,它可能是 tripddlAdapters.js
:
(function ($) {
$.fn.getDateFromTrippleDdls = function () {
var year = this.find('select:nth(0)').val();
var month = this.find('select:nth(1)').val();
var day = this.find('select:nth(2)').val();
if (year == '' || month == '' || day == '') {
return NaN;
}
var y = parseInt(year, 10);
var m = parseInt(month, 10);
var d = parseInt(day, 10);
var date = new Date(y, m - 1, d);
var isValidDate = date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d;
if (isValidDate) {
return date;
}
return NaN;
};
$.validator.unobtrusive.adapters.add('trippleddldate', [], function (options) {
options.rules['trippleddldate'] = options.params;
if (options.message) {
options.messages['trippleddldate'] = options.message;
}
});
$.validator.addMethod('trippleddldate', function (value, element, params) {
var parent = $(element).closest('.trippleddldatetime');
var date = parent.getDateFromTrippleDdls();
console.log(date);
return !isNaN(date);
}, '');
$.validator.unobtrusive.adapters.add('minage', ['min'], function (options) {
options.rules['minage'] = options.params;
if (options.message) {
options.messages['minage'] = options.message;
}
});
$.validator.addMethod('minage', function (value, element, params) {
var parent = $(element).closest('.trippleddldatetime');
var birthDate = parent.getDateFromTrippleDdls();
if (isNaN(birthDate)) {
return false;
}
var today = new Date();
var age = today.getFullYear() - birthDate.getFullYear();
var m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age >= parseInt(params.min, 10);
}, '');
})(jQuery);
最后,我们在页面中添加了 3 个必要的脚本,以启用不显眼的客户端验证:
<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 src="@Url.Content("~/Scripts/trippleddlAdapters.js")" type="text/javascript"></script>
关于jquery - 如何使用 3 个下拉列表(日、月、年)使用 jquery 非侵入性验证来验证日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11475670/
在 Windows 世界中,什么是正确的名称。具有导出函数的老式 C++ DLL?不是 COM DLL,也不是 .NET DLL。我们以前通过调用 LoadLibrary() 和 GetProcAdd
目前我正在使用javaEE7,我有一个场景如下。在我的 JSF Web 应用程序中,我有一个事件监听器(不是 JSF 事件),当事件调用时,它会执行某些操作,然后将这些信息更新到我的 Web 应用程序
这不是 AJAX 请求/响应回调问题... 我正在使用 Dojo 1.5 构建网格。我正在尝试 dojo.connect具有功能的扩展/收缩按钮。我的问题是 grid.startup()在创建实际 D
非 Webkit Opera 是 very specific在某些功能中,因此通常通过 JavaScript 检测到 the following way . 但是,Opera Next 几乎是 Goo
我已查看以下链接中给出的所有日志,但未能找到 IP 地址: https://developer.couchbase.com/documentation/server/3.x/admin/Misc/Tr
我有一个命令行程序,它根据一组源文件生成一个我想在我的 Android gradle 构建 (A) 中使用的 jar 文件。这个命令行程序只是将一个 jar 文件存储在磁盘上的一个目录中。 我如何创建
下面的 htaccess 命令将所有非 www 转移到 http www RewriteEngine On RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^
我正在使用自定义链接器脚本将内核镜像分为两部分。第一个是普通代码和数据,第二个是初始化代码和不再需要时将被丢弃的数据。初始化部分也不像内核本身那样在地址空间之间共享,因此如果 fork() 仍然存在(
这个问题在这里已经有了答案: Several unary operators in C and C++ (3 个答案) What is the "-->" operator in C++? (29
假设我有一个类设置如下: class A { public: virtual void foo() { printf("default implementation\n"); } }; c
#include using namespace std; int main(int argc, char *argv[]) { int i=-5; while(~(i)) {
近期,百度搜索引擎变化无常,很多企业站、行业站、门户站、论坛等站点遭到了降权,特别是比比贴分类信息网直接遭到了拔毛,这对于广大站长来说是一种打击,也是各个企业、行业的打击。 至今,很多网站已经恢复
我现在正在使用 IBM TPM v1332 + IBM TSS v1470 并尝试将一些基本关键字/密码存储到 TPM 上的非 volatile 内存中。我找到了两种方法。一种是创建一个密封对象并使用
我的 PHP 脚本中有一个正则表达式,如下所示: /(\b$term|$term\b)(?!([^)/iu 这与 $term 中包含的单词匹配,只要前后有单词边界并且它不在 HTML 标记内即可。 但
我想显示用户名称地址(请参阅 www.ipchicken.com ),但我唯一能找到的是 IP 地址。我尝试了反向查找,但也没有用: IPAddress ip = IPAddress.Parse(th
只有 UI 线程能够显示到屏幕上,还是其他线程也可以这样做? 最佳答案 不,您只能直接从 UI 线程访问 UI,但您可以编码来自其他线程的结果,例如使用 Control.Invoke 或 contro
我正在使用现代 Excel 滚动条(不是旧的 ActiveX 类型,即开发人员 > 插入 > 表单控件 > 滚动条)并且想检测它的值何时更改。我找不到有关此类对象的更改事件的任何信息。您可以在单击时分
当我使用这段代码时 IE 6 确实正确使用了指定的样式表,但所有其他浏览器在应该使用基本上声明的样式表时会忽略这两种样式表,如果您不是 IE,请使用此样式表。 有什么想法吗? 最佳答案 n
我想指定 2 mssql 表之间的关系。 付款类别和付款。 paymentcategory.id 加入 payout.category 列。 在 payout.json 模型中 我指定为外键:id,
我正在尝试制作非 volatile UDF,但似乎不可能。因此,这是我非常简单的test-UDF: Option Explicit Dim i As Integer Sub Main() i = 0
我是一名优秀的程序员,十分优秀!