Я пытаюсь написать собственный метод проверки в своем приложении - у меня он работает на стороне сервера, но я пытаюсь расширить его, чтобы он также реализовывал ненавязчивую проверку на стороне клиента на JavaScript. Я также использую viewmodel, для дополнительного удовольствия.
Вот что я имею в виду в качестве тривиального теста - это довольно просто - у дочернего объекта есть три поля - настраиваемая проверка, которую я пишу, заключается в том, что по крайней мере одно из полей должно быть заполнено (очевидно, мое реальное приложение имеет значительно более сложная модель, чем эта):
Модель:
public class Child
{
public int Id { get; set; }
[MustHaveFavouriteValidator("FavouritePudding", "FavouriteGame")]
public string FavouriteToy { get; set; }
public string FavouritePudding { get; set; }
public string FavouriteGame { get; set; }
}
ViewModel:
public class ChildViewModel
{
public Child theChild { get; set; }
}
Контроллер:
public ActionResult Create()
{
var childViewModel = new PeopleAgeGroups.ViewModels.ChildViewModel();
return View(childViewModel);
}
Я проследил, какую документацию я могу найти в Интернете, и создал специальный валидатор, который выглядит следующим образом:
public class MustHaveFavouriteValidator:ValidationAttribute, IClientValidatable
{
private const string defaultError = "You must have one favourite";
public string firstOtherFavourite { get; set; }
public string secondOtherFavourite { get; set; }
public MustHaveFavouriteValidator(string firstFave, string secondFave)
: base(defaultError)
{
firstOtherFavourite = firstFave;
secondOtherFavourite = secondFave;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name, firstOtherFavourite, secondOtherFavourite);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var aFavouriteObject = validationContext.ObjectInstance.GetType().GetProperty(firstOtherFavourite);
var bFavouriteObject = validationContext.ObjectInstance.GetType().GetProperty(secondOtherFavourite);
var aFavourite = aFavouriteObject.GetValue(validationContext.ObjectInstance, null);
var bFavourite = bFavouriteObject.GetValue(validationContext.ObjectInstance, null);
if(value==null && aFavourite ==null && bFavourite == null){
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName), new[] { validationContext.MemberName, aFavouriteObject.Name, bFavouriteObject.Name });
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
return new[] { new MustHaveFavourite(FormatErrorMessage(metadata.GetDisplayName()), firstOtherFavourite, secondOtherFavourite) };
}
}
Хорошие вещи, моя проверка на стороне сервера работает.
Далее у меня есть правило проверки модели клиента:
public class MustHaveFavourite : ModelClientValidationRule
{
public MustHaveFavourite(string errorMessage, string firstotherfavourite, string secondotherfavourite)
{
ErrorMessage = errorMessage;
ValidationType = "musthavefavourite";
ValidationParameters.Add("firstotherfavourite", firstotherfavourite);
ValidationParameters.Add("secondotherfavourite", secondotherfavourite);
}
}
и, наконец, мой пользовательский javascript, чтобы связать все вместе:
(function ($) {
jQuery.validator.addMethod("musthavefavourite", function (value, element, params) {
var $firstOtherFavouriteObject = $('#' + params.firstotherfavourite);
var firstOtherFavourite = $firstOtherFavouriteObject.val();
var $secondOtherFavouriteObject = $('#' + params.secondotherfavourite);
var secondOtherFavourite = $secondOtherFavouriteObject.val();
if (value == '' && firstOtherFavourite == '' && secondOtherFavourite == '') {
return false;
} else {
return true;
}
});
$.validator.unobtrusive.adapters.add("musthavefavourite", ["firstotherfavourite", "secondotherfavourite"],
function (options) {
options.rules['musthavefavourite'] = {
firstotherfavourite: options.params.firstotherfavourite,
secondotherfavourite: options.params.secondotherfavourite
};
options.messages['musthavefavourite'] = options.mesage;
}
);
} (jQuery));
Проблема, которая возникает, заключается в том, что в сгенерированном HTML я получаю свои текстовые элементы с идентификатором с префиксом "theChild_" - это имеет смысл, поскольку моя viewmodel объявляет объект Child, однако моя пользовательская функция не иметь префикс в именах элементов. Есть ли способ передать этот префикс в javascript, не взломав его, чтобы он выглядел так:
jQuery.validator.addMethod("musthavefavourite", function (value, element, params) {
var $firstOtherFavouriteObject = $('#theChild_' + params.firstotherfavourite);
var firstOtherFavourite = $firstOtherFavouriteObject.val();
, что, на мой взгляд, отчасти противоречит идее создания моей серверной части проверки, а затем подключает все это дополнительное средство для прохождения ненавязчивой проверки, поскольку я создал фрагмент javascript, который действительно может использоваться только с этой комбинацией комбинация форма / видмодель.