検証するモデルがあり、問題は生年月日フィールドです。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);
}
質問:
- サーバー側 : どうすれば改善できますか? (生年月日、月、年のプロパティRegistrationModelを追加し、DateOfBirthに属性を追加してそれらのプロパティを確認することを考えています)
- クライアント側:カスタム属性のクライアント側検証の実行を見ていましたが、混乱しました。それを作る方法は何ですか?
LE: 次のような日付のカスタム モデル バインダーを作成しました。
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)
DateOfBirth は適切にバインドされます。
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;
});
});
クライアントの検証が機能していないようです。どうすれば修正できますか?これらのアダプターの動作方法にちょっと混乱しています。