2011-10-13 2 views
0

J'essaie d'écrire une méthode de validation personnalisée dans mon application - je l'ai côté serveur de travail, mais j'essaie d'étendre cela pour qu'il s'installe aussi dans la validation discrète du côté client javascript. J'utilise aussi un viewmodel pour plus de plaisir.ASP.Net MVC 3 ViewModel, JavaScript discret et validation personnalisée

Voici ce que j'ai comme un test trivial - c'est assez simple - un objet enfant a trois champs - la validation personnalisée que j'écris est qu'au moins un des champs doit être rempli (évidemment mon application réelle a un modèle beaucoup plus complexe que cela):

modèle:

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; } 
} 

Controller:

public ActionResult Create() 
    { 
     var childViewModel = new PeopleAgeGroups.ViewModels.ChildViewModel(); 
     return View(childViewModel); 
    } 

J'ai suivi ce que documentatation je peux trouver en ligne et fouetté un validateur personnalisé qui ressemble à ceci:

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) }; 
    } 
} 

Good stuff, mes travaux de validation côté serveur . Ensuite j'ai la règle de validation client modèle:

public class MustHaveFavourite : ModelClientValidationRule 
{ 
    public MustHaveFavourite(string errorMessage, string firstotherfavourite, string secondotherfavourite) 
    { 
     ErrorMessage = errorMessage; 
     ValidationType = "musthavefavourite"; 
     ValidationParameters.Add("firstotherfavourite", firstotherfavourite); 
     ValidationParameters.Add("secondotherfavourite", secondotherfavourite); 
    } 
} 

et enfin, mon habitude javascript pour lier ensemble:

(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)); 

Le problème qui se produit est que le dans le code HTML généré, je reçois mes éléments de texte qui ont un identifiant qui est préfixé "theChild_" - cela est logique puisque mon viewmodel déclare un objet Child, cependant, ma fonction personnalisée n'a pas le préfixe sur les noms des éléments. Est-il possible de passer ce préfixe à travers le javascript sans réellement le piratage il à ressembler à ceci:

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

qui, à mon avis défaites genre de l'idée de créer ma validation Serverside puis accrochage tout cela gumf supplémentaire jusqu'à passer à travers la validation discrète depuis que j'ai créé un morceau de javascript qui ne peut vraiment être utilisé avec cette combinaison de combinaison formulaire/viewmodel.

Répondre

0

Vous pouvez modifier votre validateur pour vérifier tout préfixe et ajouter le préfixe au sélecteur pour les éléments à vérifier, comme je l'indique dans ma réponse à cette question: MVC3 custom validation: compare two dates. Vous devrez soit (1) changer les sélecteurs pour rechercher par nom, au lieu de par id, soit (2) diviser l'identifiant en utilisant _ au lieu de ..