Domanda

Sono nuovo in ASP.NET MVC 3, affrontando alcuni problemi mentre provo a implementare la convalida discreta del lato client per un modello di editor che ho creato per mostrare la data in modo personalizzato.

Ui
Devo mostrare la data in un file Tre interfaccia utente di Texbox formato come

enter image description here


Ho messo su un EDITTemPlate per la visualizzazione della data in tre parti come

@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>

Modello
Devo legare una data di nascita che è una proprietà in a Subject del mio modello a questa proprietà, in questa struttura

MyModel
    --> MySubModel
          --> DateOfBirth

public class MySubModel
{
    ...

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

    ...
}

Convalida dei clienti

Ho creato un attributo di validazione personalizzato che implementa IclientValidable come

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

Sto cercando di emettere i nomi degli elementi delle caselle di testo di giorno, mese e anno qui agli elementi di convalida del lato client, in modo che scriverò un metodo di validazione e adattatore a un lato del cliente che consumerebbe quegli elementi e faranno la convalida sul lato client.

Visualizzazione
Ora, per usare questo modello di editor, ho inserito Visualizzazione le seguenti righe

@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>
...

Aggiunti tutti i file di convalida jQuery pertinenti nella vista come riferimenti

Domande

  1. Questo non sta emettendo gli attributi di validazione JavaScript discreti nell'HTML, sebbene io abbia implementato Iclientvalidable. Ai fini del test quando metto lo stesso attributo (DateTimeClientValidation) su un'altra proprietà nel modello che non utilizzava questo modello di editor, quindi ha emesso quegli attributi di convalida, non lo sta emettendo solo per questo modello di editor. Dove avrei potuto andare storto?
  2. Per quanto riguarda il messaggio di convalida per il modello dell'editor, è giusto che lo metta solo in vista o dovrei metterlo direttamente nel modello dell'editor (@Html.validationMessageFor (M => M.MysubModel.DateofBirth))
  3. In questo esempio, sono proprio nel design, ho inserito DateTimeClientValidationAttribute, che in realtà è un attributo che ho inserito sul modello, ma questo componente sa un po 'dell'interfaccia utente (dal momento che sta cercando di emettere il nome degli elementi del giorno, del mese e dell'anno), questo fa conoscere un po' di vista sul modello, AM Rompendo qualche principi di design qui?
  4. In DateTimeClientValidationAttribute, Sto cercando di emettere nomi di elementi del giorno, del mese e dell'anno, in modo che lo script client possa fare convalide su di esso. Ma da quando la proprietà del modello Data di nascita è in un subject, il nome dell'elemento effettivo nello script è MysuBobject.dateofbirth, il che rende il nome del giorno della casella di testo MysuBobject.dateofbirth.day, come posso trovare quel nome modello completamente qualificato in Getclientvalidationrules Metodo, in modo che io possa emettere il nome al client?

Grazie per essere stato paziente a leggere tutto questo e per le risposte

È stato utile?

Soluzione

Dopo un po 'di sforzo, ho fatto il controllo per lavorare, mettendo se è utile a chiunque là fuori.

Il primo punto è avere il controllo definito come

@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>

Assicurati, dai stringhe vuote come nome A tutte e tre le caselle di testo, questo costringe il framework MVC a generare lo stesso nome corrispondente al modello Data di nascita Per tutte e tre le caselle di testo nel lato client. Inoltre, i parametri di convalida JavaScript discreti verrebbero generati per la prima casella di testo nell'elenco, poiché è la prima occorrenza di un controllo di modifica con il nome del modello.

Sul lato client, su qualsiasi evento su una di queste caselle di testo attiva tutti gli eventi di convalida pertinenti, poiché tutte queste 3 caselle di testo hanno lo stesso nome.

Oltre alle validazioni regolari come richieste, .... dobbiamo scrivere una routine di convalida del client personalizzata che combini tutti e tre questi valori e verificherebbe se il valore combinato costituisce una data valida. Questo può essere ottenuto come in Rispondere dato da Jeff.

Altri suggerimenti

Ok quindi alcune cose. Primo: se possibile, non dividere la data in tre campi. Ti risparmierai un mondo di mal di testa semplicemente impostandolo come un singolo campo con un po 'di convalida e forse il datapicker di JQueryui.

Successivamente, nel codice attributo personalizzato all'interno di DateTimeClientValidationAttribute, non si verifica mai effettivamente vedere se la data è valida implementando 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));
}

Successivamente dovrai creare un adattatore di validazione discreto e un metodo di validatore jQuery che mette insieme i parametri e cerca di analizzare la data:

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;
}, '');
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top