Проверьте поле MVC на стороне клиента
У меня проблема с проверкой одного поля на стороне клиента. Вот мой код:
Модель:
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; }
}
ValidationAttribute:
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.");
1 ответ
MVC уже поставляется с RemoteAttribute
для проверки на стороне клиента (см. Практическое руководство. Реализация удаленной проверки в ASP.NET MVC), поэтому нет смысла пытаться изобретать колесо. (Как примечание, ваш в настоящее время отсутствует $.validator.unobtrusive.adapters.add()
метод, необходимый для добавления правил проверки на стороне клиента).
Но есть несколько проблем с вашим текущим атрибутом проверки. Атрибут проверки не должен иметь доступ к базе данных, и вы сделали невозможным модульное тестирование своего кода. И вы будете повторять код в атрибуте снова в методе контроллера, который вызывается функцией ajax, нарушая принцип DRY и усложняя поддержание вашего кода.
Вместо этого создайте приватный метод в вашем контроллере (или публичный метод в отдельной службе) для вашего кода базы данных, например
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
}