Question

Je suis nouveau à ASP.Net MVC 3, face à des problèmes tout en essayant de mettre en œuvre la validation côté client discret pour un modèle d'éditeur que j'ai créé pour montrer la date d'une manière personnalisée.

UI Je dois montrer ce jour dans un trois TexBox UI format

entrer image description ici


Je l'ai mis en place un EditorTemplate pour afficher la date dans trois parties

@model DateTime?

<table class="datetime">
<tr>
    <td>@Html.TextBox("Day", (Model.HasValue ? Model.Value.ToString("dd") : string.Empty)) </td>
    <td class="separator">/</td>
    <td>@Html.TextBox("Month", (Model.HasValue ? Model.Value.ToString("MM") : string.Empty))</td>
    <td class="separator">/</td>
    <td>@Html.TextBox("Year", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty))</td>
</tr>
<tr>
    <td class="label">dd</td>
    <td/>
    <td class="label">mm</td>
    <td/>
    <td class="label">yyyy</td>
</tr>
</table>

Modèle
Je dois lier un champ Date de naissance qui est une propriété dans un subobject de mon modèle à cette propriété, dans cette structure

MyModel
    --> MySubModel
          --> DateOfBirth

public class MySubModel
{
    ...

    [DataType(DataType.Date)]
    [Display(Name = "Date of birth")]
    [DateTimeClientValidation()]
    public DateTime DateofBirth { get; set; }

    ...
}

ClientSide Validation

Je l'ai mis en place un attribut de validation personnalisé qui implémente IClientValidatable comme

public class DateTimeClientValidationAttribute : ValidationAttribute, IClientValidatable
{
    ...

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        List<ModelClientValidationRule> clientRules = new List<ModelClientValidationRule>();

        //Combined date should be valid
        ModelClientValidationRule validDateRule = new ModelClientValidationRule
        {
            ErrorMessage = "Please enter a valid date.",
            ValidationType = "validdate"
        };
        validDateRule.ValidationParameters.Add("dayelement", metadata.PropertyName + ".Day");
        validDateRule.ValidationParameters.Add("monthelement", metadata.PropertyName + ".Month");
        validDateRule.ValidationParameters.Add("yearelement", metadata.PropertyName + ".Year");
        clientRules.Add(validDateRule);

        return clientRules;
    }
    ...
}

Je suis en train d'émettre les noms d'éléments de jour, mois et année textboxes ici à des éléments de validation côté client, de sorte que je vais écrire un côté client méthode de validation jquery et un adaptateur plus tard qui consomment ces éléments et faire la validation au côté client.

Afficher
Maintenant, pour utiliser ce modèle d'éditeur, je mets dans Voir les lignes suivantes

@model MyModel
...
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.MySubModel.DateofBirth)
    </td>
    <td class="editor-field">
        @Html.EditorFor(m => m.MySubModel.DateofBirth)
        @Html.ValidationMessageFor(m => m.MySubModel.DateofBirth)
    </td>
</tr>
...

Ajout tous les fichiers de validation jquery pertinents dans la vue comme référence

Questions

  1. Ce n'émet pas les attributs discrets de validation de javascript dans le code HTML, bien que je l'ai mis en œuvre IClientValidatable . Pour des fins de test quand je mets le même attribut ( DateTimeClientValidation ) sur une autre propriété dans le modèle qui n'a pas été en utilisant ce modèle de l'éditeur, puis il a émis sur les attributs de validation, il ne l'émettre uniquement pour cette modèle de l'éditeur. Où pourrait avoir je passé?
  2. En ce qui concerne la durée de validation de message pour le modèle de l'éditeur, est-il juste que je l'ai mis dans la vue seulement ou devrais-je le mettre directement dans le modèle de l'éditeur ( @ Html.ValidationMessageFor (m => m.MySubModel.DateofBirth) )
  3. Dans cet exemple, suis-je droit dans la conception, je l'ai mis en DateTimeClientValidationAttribute , qui est en fait un attribut que je mets sur le modèle, mais cette composante connaît un peu l'interface utilisateur (car il tente pour émettre les éléments jour, mois et année nom au client), ce qui rend le modèle connaît un peu View, suis-je casse les principes de conception ici?
  4. DateTimeClientValidationAttribute , je suis en train d'émettre vers le client le jour, mois et année des éléments noms, de sorte que le script client peut faire sur elle des validations. Mais puisque la propriété modèle dateOfBirth est dans un sous-objet, le nom réel de l'élément dans le script est MySubObject.DateOfBirth , ce qui rend le nom textbox jour pour être MySubObject. DateofBirth.Day , comment puis-je trouver que le nom du modèle complet dans le GetClientValidationRules méthode, afin que je puisse émettre le nom du client?

Merci d'être patient à lire tout cela, et pour les réponses

Était-ce utile?

La solution

Après un certain effort, je fis le contrôle au travail, la mise en s'il est utile à tout le monde là-bas.

Le premier point est d'avoir le contrôle définie comme

@model DateTime?

<table class="datetime">
<tr>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("dd") : string.Empty)) </td>
    <td class="separator">/</td>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("MM") : string.Empty))</td>
    <td class="separator">/</td>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty))</td>
</tr>
<tr>
    <td class="label">dd</td>
    <td/>
    <td class="label">mm</td>
    <td/>
    <td class="label">yyyy</td>
</tr>
</table>

Assurez-vous, vous donnez chaînes vides comme nom à tous les trois zones de texte, cette force le framework MVC de générer même nom correspondant au modèle dateOfBirth pour tous les trois champs de saisie du côté client. En outre, les paramètres discrets de validation javascript seraient générés pour la première zone de texte dans la liste, car il est la première occurence d'un contrôle d'édition avec le nom du modèle.

Du côté client, sur tout état de cause sur l'une de ces zones de texte se déclenche tous les événements de validation pertinents, puisque tous ces 3 zones de texte ont le même nom.

En plus des réguliers comme nécessaire validations, .... nous devons écrire une routine de validation client personnalisé qui combinerait ces trois valeurs et vérifie si la valeur combinée constitue une date valide. Ceci peut être réalisé que dans le réponse donnée par Jeff .

Autres conseils

Ok, donc quelques petites choses. Tout d'abord - si possible, ne fend pas la date en trois champs. Vous vous épargnerez un monde de maux de tête en fixant simplement comme un seul champ avec une validation et DatePicker de jQueryUI peut-être.

Ensuite, dans votre code d'attribut personnalisé à l'intérieur DateTimeClientValidationAttribute, vous vérifiez jamais vraiment à voir si la date est valide en mettant en œuvre IsValid:

protected override ValidationResult IsValid(object value, 
    ValidationContext validationContext) 
{
   ...
   // Put date parts together and check is valid...
   if (DateTime.TryParse(year+"/"+month+"/"+day, out dateResult))
      return ValidationResult.Success;

   // Not valid
   return new ValidationResult(String.Format(ErrorMessageString, 
      validationContext.DisplayName));
}

Ensuite, vous devrez créer un adaptateur de validation discrète et une méthode de validateur jQuery qui met les params ensemble et tente d'analyser la date:

jQuery.validator.unobtrusive.adapters.add(
    'validdate', // notice this is coming from how you named your validation rule
    ['dayelement'],
    ['monthelement'],
    ['yearelement']
    function (options) {
        options.rules['datepartcheck'] = options.params;
        options.messages['datepartcheck'] = options.message;
    }
);
jQuery.validator.addMethod('datepartcheck', function (value, element, params) {
    var year = params[2];
    var month = params[1];
    var day = params[0];

    var birthDate = year + '/' + month-1 + '/' + day;
    var isValid = true;

    try {
        // datepicker is a part of jqueryUI.
        // include it and you can take advantage of .parseDate:
        $.datepicker.parseDate('yy/mm/dd', birthDate);
    }
    catch (error) {
        isValid = false;
    }
    return isValid;
}, '');
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top