在客户端验证 MVC 字段
Validate MVC field at client side
我在客户端验证一个字段时遇到问题,这是我的代码:
型号:
public class Registration
{
public int Id { get; set; }
[IsUserExistAttribute(ErrorMessage = "Email already exists!")]
[EmailAddress(ErrorMessage = "Please enter valid Email")]
[Required(ErrorMessage = "Email is required")]
public string Email
{
get; set;
}
[MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")]
public bool TermsAndConditions { get; set; }
}
验证属性:
public class IsUserExistAttribute : ValidationAttribute,IClientValidatable
{
public override bool IsValid(object email)
{
DemoDbContext demoContext=new DemoDbContext();
string emailString = Convert.ToString(email);
if (demoContext.Registrations.Any(a=>a.Email.Contains(emailString)))
{
return false;
}
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "emailvalidate"
};
}
}
查看:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Registration</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TermsAndConditions, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.TermsAndConditions)
@Html.ValidationMessageFor(model => model.TermsAndConditions, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
一切都很好,但我的问题是这个 IsUserExistAttribute 没有在客户端验证它,在服务器端它验证并给出消息 电子邮件已经存在!
但是,我也希望它能验证客户端。那么,实现这一目标的好方法是什么?也欢迎其他方法:)
我试过类似这样的方法似乎没有成功:
$.validator.addMethod("emailvalidate", function (value, element) {
var is_valid = false;
$.ajax({
// as before...
async: false,
success: function (data) {
is_valid = data === 'True';
}
});
return is_valid;
}, "Username not available.");
MVC 已经带有用于客户端验证的 RemoteAttribute
(请参阅 How to: Implement Remote Validation in ASP.NET MVC),因此您尝试重新发明轮子没有什么意义。 (作为旁注,您目前缺少添加客户端验证规则所需的 $.validator.unobtrusive.adapters.add()
方法)。
但是您当前的验证属性存在一些问题。验证属性不应访问数据库,并且您无法对代码进行单元测试。并且您将在 ajax 函数调用的控制器方法中再次重复属性中的代码,这违反了 DRY 原则并使代码更难维护。
相反,在您的控制器中为您的数据库代码创建一个私有方法(或在单独的服务中创建一个 public 方法),例如
private bool IsEmailUnique(string email)
{
return !db.Registrations.Any(a => a.Email.Contains(email)))
}
然后为了客户端验证,用 RemoteAttribute
装饰你 属性
[Remote("IsEmailValid", "ControllerName", ErorMessage = "...")]
public string Email { get; set; }
并添加控制器方法
public JsonResult IsEmailValid(string email)
{
bool isValid = IsEmailUnique(email);
return Json(isValid, JsonRequestBehavior.AllowGet);
}
然后如果您还想在提交表单时进行服务器端验证,请调用相同的方法,如果无效,请添加 ModelStateError
public ActionResult Register(Registration model)
{
bool isValid = IsEmailUnique(model.Email);
if (!isValid)
{
ModelState.AddModelError("Email", "...");
}
if (!ModelState.IsValid)
{
return View(model);
}
// save and redirect
}
我在客户端验证一个字段时遇到问题,这是我的代码:
型号:
public class Registration
{
public int Id { get; set; }
[IsUserExistAttribute(ErrorMessage = "Email already exists!")]
[EmailAddress(ErrorMessage = "Please enter valid Email")]
[Required(ErrorMessage = "Email is required")]
public string Email
{
get; set;
}
[MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")]
public bool TermsAndConditions { get; set; }
}
验证属性:
public class IsUserExistAttribute : ValidationAttribute,IClientValidatable
{
public override bool IsValid(object email)
{
DemoDbContext demoContext=new DemoDbContext();
string emailString = Convert.ToString(email);
if (demoContext.Registrations.Any(a=>a.Email.Contains(emailString)))
{
return false;
}
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "emailvalidate"
};
}
}
查看:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Registration</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TermsAndConditions, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.TermsAndConditions)
@Html.ValidationMessageFor(model => model.TermsAndConditions, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
一切都很好,但我的问题是这个 IsUserExistAttribute 没有在客户端验证它,在服务器端它验证并给出消息 电子邮件已经存在!
但是,我也希望它能验证客户端。那么,实现这一目标的好方法是什么?也欢迎其他方法:)
我试过类似这样的方法似乎没有成功:
$.validator.addMethod("emailvalidate", function (value, element) {
var is_valid = false;
$.ajax({
// as before...
async: false,
success: function (data) {
is_valid = data === 'True';
}
});
return is_valid;
}, "Username not available.");
MVC 已经带有用于客户端验证的 RemoteAttribute
(请参阅 How to: Implement Remote Validation in ASP.NET MVC),因此您尝试重新发明轮子没有什么意义。 (作为旁注,您目前缺少添加客户端验证规则所需的 $.validator.unobtrusive.adapters.add()
方法)。
但是您当前的验证属性存在一些问题。验证属性不应访问数据库,并且您无法对代码进行单元测试。并且您将在 ajax 函数调用的控制器方法中再次重复属性中的代码,这违反了 DRY 原则并使代码更难维护。
相反,在您的控制器中为您的数据库代码创建一个私有方法(或在单独的服务中创建一个 public 方法),例如
private bool IsEmailUnique(string email)
{
return !db.Registrations.Any(a => a.Email.Contains(email)))
}
然后为了客户端验证,用 RemoteAttribute
[Remote("IsEmailValid", "ControllerName", ErorMessage = "...")]
public string Email { get; set; }
并添加控制器方法
public JsonResult IsEmailValid(string email)
{
bool isValid = IsEmailUnique(email);
return Json(isValid, JsonRequestBehavior.AllowGet);
}
然后如果您还想在提交表单时进行服务器端验证,请调用相同的方法,如果无效,请添加 ModelStateError
public ActionResult Register(Registration model)
{
bool isValid = IsEmailUnique(model.Email);
if (!isValid)
{
ModelState.AddModelError("Email", "...");
}
if (!ModelState.IsValid)
{
return View(model);
}
// save and redirect
}