ASP.Net MVC 3 ViewModel, ненатрапчив JavaScript и персонализирано валидиране

Опитвам се да напиша персонализиран метод за валидиране в моето приложение - имам го работещ от страната на сървъра, но се опитвам да го разширя, така че да се внедри и в ненатрапчивото валидиране от страна на клиента на 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_" - това има смисъл, тъй като моят изгледмодел декларира Child обект, но моята персонализирана функция няма префикса върху имената на елементите. Има ли някакъв начин да прехвърлите този префикс към javascript, без всъщност да го хакнете, за да изглежда така:

jQuery.validator.addMethod("musthavefavourite", function (value, element, params) {
    var $firstOtherFavouriteObject = $('#theChild_' + params.firstotherfavourite);
    var firstOtherFavourite = $firstOtherFavouriteObject.val(); 

което според мен проваля идеята да създам моя сървър за валидиране и след това да закача всички тези допълнителни глупости, за да премина през ненатрапчивото валидиране, тъй като създадох част от javascript, който наистина може да се използва само с тази комбинация от форма/модел на изглед комбинация.


person slapthelownote    schedule 13.10.2011    source източник


Отговори (1)


Можете да промените своя валидатор, за да проверява за всеки префикс, и да добавите префикса към селектора за елементите, които ще бъдат проверени, както посочвам в отговора си на този въпрос: MVC3 персонализирано валидиране: сравнете две дати. Ще трябва или (1) да промените селекторите, за да търсите по име, вместо по идентификатор, или (2) да разделите идентификатора, като използвате _ вместо ..

person counsellorben    schedule 13.10.2011