Frage

Ich bin neu bei ASP.NET MVC 3 und kann einige Probleme haben, während ich versuche, die nicht auffällige Validierung der Client -Seite für eine Editor -Vorlage zu implementieren, die ich für die Anzeige des Datums auf benutzerdefinierte Weise erstellt habe.

UI
Ich muss das Datum in einem zeigen Drei Texbox UI Format als

enter image description here


Ich habe a aufgestellt EditorTemplate zum Anzeigen des Datums in drei Teilen als

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

Modell
Ich muss ein Geburtsdatum binden, das eine Eigenschaft in a ist Unterobjekt meines Modells zu dieser Eigenschaft in dieser Struktur

MyModel
    --> MySubModel
          --> DateOfBirth

public class MySubModel
{
    ...

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

    ...
}

Clientside -Validierung

Ich habe ein benutzerdefiniertes Validierungsattribut erstellt, das iClientValidatable als implementiert

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

Ich versuche, die Elementnamen der Textboxen von Tages-, Monats- und Jahr an die Client -Seiten -Validierungselemente auszugeben, damit ich eine Client -Seite JQuery -Validierungsmethode und Adapter später schreibe, die diese Elemente konsumieren und die Validierung auf der Client -Seite durchführen würde.

Aussicht
Um diese Editor -Vorlage zu verwenden, habe ich nun eingebracht Aussicht die folgenden Zeilen

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

Alle relevanten jQuery -Validierungsdateien in der Ansicht als Referenzen fügte hinzu

Fragen

  1. Dies gibt nicht die unauffälligen JavaScript -Validierungsattribute in der HTML aus, obwohl ich implementiert habe IclientValidatable. Zum Testzweck, wenn ich dasselbe Attribut einsetze (DATETIMECLIENTVALIDATION) Auf einer anderen Eigenschaft in dem Modell, die diese Editor -Vorlage nicht verwendete, dann emittiert es diese Validierungsattribute, sie wird nicht nur für diese Editor -Vorlage ausgestrahlt. Wo hätte ich mich falsch machen können?
  2. In Bezug auf die Validierungsmeldungspanne für die Editor -Vorlage ist es richtig, dass ich sie nur in Ansicht stelle oder sollte ich sie direkt in die Editor -Vorlage einfügen (@Html.validationMessagefor (m => m.mysubmodel.dateofbirth))
  3. In diesem Beispiel habe ich Recht im Design, ich habe eingesetzt DateTimeClientValidationAttribute, was eigentlich ein Attribut ist, das ich auf ein Modell einbrachte, aber diese Komponente weiß etwas über die Benutzeroberfläche (da es versucht, den Namen Tag, Monat und Jahr an den Kunden auszugeben) Ich breche hier Designprinzipien?
  4. Im DateTimeClientValidationAttribute, Ich versuche, die Namen von Tag-, Monats- und Jahrsnamen an den Kunden auszugeben, damit das Client -Skript Validierungen dazu erledigen kann. Aber seit der Modelleigenschaft Geburtsdatum befindet Mysubobject.dateofBirth, was den Tag des Textboxsnamens zu sein macht Mysubobject.dateofbirth.day, wie kann ich diesen voll qualifizierten Modellnamen in der finde GetClientvalidationrules Methode, damit ich den Namen an den Client ausgeben kann?

Danke, dass du geduldig bist, all dies vorzulesen und für die Antworten

War es hilfreich?

Lösung

Nach einiger Anstrengungen habe ich die Kontrolle über die Arbeit geleistet und einsetzt, wenn es für jemanden da draußen hilfreich ist.

Der erste Punkt besteht darin, die Kontrolle definiert zu haben

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

Stellen Sie sicher, dass Sie geben leere Saiten als Name Dadurch zwingt dies dem MVC Name entsprechend dem Modell Geburtsdatum Für alle drei Textboxen auf der Clientseite. Außerdem würden unauffällige JavaScript -Validierungsparameter für das erste Textfeld in der Liste generiert, da dies das erste Ereignis eines Bearbeitungssteuerers mit dem Namen des Modells ist.

Auf der Clientseite füllt auf jedem Ereignis auf einer dieser Textboxen alle relevanten Validierungsereignisse, da alle diese 3 Textboxen denselben Namen haben.

Zusätzlich zu den regulären Validierungen wie erforderlich .... Wir müssen eine benutzerdefinierte Client -Validierungsroutine schreiben, die alle diese drei Werte kombinieren und prüft, ob das kombinierte Wert ein gültiges Datum formuliert. Dies kann wie in der erreicht werden Antworten gegeben durch Jeff.

Andere Tipps

Ok also ein paar Dinge. Erstens - wenn möglich, teilen Sie das Datum nicht in drei Felder auf. Sie sparen sich eine Welt voller Kopfschmerzen, indem Sie sie einfach als einzelnes Feld mit einiger Validierung und vielleicht JQueryui -Dattelpicker einrichten.

In Ihrem benutzerdefinierten Attributcode innerhalb von DateTimeClientValidationAttribute überprüfen Sie nie tatsächlich, ob das Datum durch die Implementierung von ISValid gültig ist:

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

Als nächstes müssen Sie einen unauffälligen Validierungsadapter und eine JQuery Validator -Methode erstellen, die die Parameter zusammenstellt und versucht, das Datum zu analysieren:

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;
}, '');
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top