MVC de validation personnalisée: comparer deux dates
J'ai créé une coutume ValidationAttribute qui compare les 2 dates et permet de s'assurer que la deuxième date est supérieure à la première:
public sealed class IsDateAfter : ValidationAttribute, IClientValidatable
{
private readonly string testedPropertyName;
private readonly bool allowEqualDates;
public IsDateAfter(string testedPropertyName, bool allowEqualDates = false)
{
this.testedPropertyName = testedPropertyName;
this.allowEqualDates = allowEqualDates;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName));
}
var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (value == null || !(value is DateTime))
{
return ValidationResult.Success;
}
if (propertyTestedValue == null || !(propertyTestedValue is DateTime))
{
return ValidationResult.Success;
}
//Compare values
if ((DateTime)value >= (DateTime)propertyTestedValue)
{
if (this.allowEqualDates)
{
return ValidationResult.Success;
}
if ((DateTime)value > (DateTime)propertyTestedValue)
{
return ValidationResult.Success;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessageString,
ValidationType = "isdateafter"
};
rule.ValidationParameters["propertytested"] = this.testedPropertyName;
rule.ValidationParameters["allowequaldates"] = this.allowEqualDates;
yield return rule;
}
CalendarEntry classe:
...
public virtual DateTime StartDate { get; set; }
[IsDateAfter("StartDate", true, ErrorMessage="End date needs to be after start date")]
public virtual DateTime EndDate { get; set; }
VUE:
$.validator.unobtrusive.adapters.add(
'isdateafter', ['propertytested', 'allowequaldates'], function (options) {
options.rules['isdateafter'] = options.params;
options.messages['isdateafter'] = options.message;
});
$.validator.addMethod("isdateafter", function(value, element, params) {
alert(params.propertytested);
var startdatevalue = $('input[name="' + params.propertytested + '"]').val();
if (!value || !startdatevalue) return true;
return (params.allowequaldates) ? Date.parse(startdatevalue) <= Date.parse(value) : Date.parse(startdatevalue) < Date.parse(value);
}, '');
Cela fonctionne très bien lorsque l' CalendarEntry n'est pas appliqué à l'intérieur d'une autre classe. CEPENDANT, lorsque j'utilise un modèle d'affichage comme suit:
public class TrainingDateEditViewModel
{
#region Properties
///<summary>
///Gets or sets CalendarEntry.
///</summary>
public CalendarEntry CalendarEntry { get; set; }
....
La validation du client ne fonctionne plus à cause de la sortie html produite est: est-ce
<input type="text" value="" name="CalendarEntry.EndDate" id="CalendarEntry_EndDate" data-val-isdateafter-propertytested="StartDate" data-val-isdateafter-allowequaldates="True" data-val-isdateafter="End date needs to be after start date" data-val="true">
Et la
data-val-isdateafter-propertytested="StartDate" and IT SHOULD BE: "CalendarEntry.StartDate".
Comment pourrais-je faire pour qu'elle sait à lier à "CalendarEntry.StartDate"
la règle.ValidationParameters["propertytested"] = ce.testedPropertyName; //ICI, IL convient de NOM COMPLET??? COMMENT??
grâce
- merci pour ce code, j'ai mis en œuvre avec succès dans ma validation
- Merci à vous, pour cela, et @counsellorben pour la mise à jour.
- Peut-être une bonne idée de le Suffixe de votre classe avec
Attribute
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin de modifier votre script côté client pour vérifier l'essai de l'élément préfixe, et ajouter le préfixe (le cas échéant) à votre sélecteur, comme suit:
N'oubliez pas d'inclure le côté client à l'intérieur de ce code. Il y me des heures à trouver que ce qui manquait!
Juste pour corriger une petite erreur dans counsellorben javascript: l' "(params.allowequaldates)" sera interprété comme une chaîne de caractères (qui ont une valeur "False" ou "True"), mais que la chaîne sera toujours vraie, donc ce qui permet à l'égalité des dates.
Si vous aussi vous souhaitez autoriser pour plus de niveaux d'imbrication de vos objets de seulement 1, alors vous obtiendrez:
Dans la dernière réponse il y avait, il manque des parenthèses lors de l'appel à toLowerCase, ici est une version mise à jour du document prêt et le $.programme de validation.discrète...-partie: