Führen Sie eine clientseitige Überprüfung für benutzerdefinierte Attribute durch


74

Ich habe ein benutzerdefiniertes Validierungsattribut erstellt:

public class FutureDateAttribute : ValidationAttribute
    {
        public override bool IsValid(object value) 
        {
            if (value == null|| (DateTime)value < DateTime.Now)
                return false;

            return true;
        }

    }

Wie kann ich dies mit jquery auch auf Client-Seite zum Laufen bringen?

Antworten:


165

So gehen Sie vor:

Definieren Sie zunächst das benutzerdefinierte Validierungsattribut:

public class FutureDateAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        if (value == null || (DateTime)value < DateTime.Now)
            return false;

        return true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "futuredate"
        };
    }
}

Beachten Sie, wie IClientValidatable implementiert wird . Als nächstes schreiben wir unser Modell:

public class MyViewModel
{
    [FutureDate(ErrorMessage = "Should be in the future")]
    public DateTime Date { get; set; }
}

Dann ein Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            // intentionally put in the past
            Date = DateTime.Now.AddDays(-1)
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

und zum Schluss noch ein Blick:

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.Date)
    @Html.TextBoxFor(x => x.Date)
    @Html.ValidationMessageFor(x => x.Date)
    <input type="submit" value="OK" />
}

Der letzte Teil, in dem die Magie stattfinden kann, besteht darin, den benutzerdefinierten Adapter zu definieren:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    // we add a custom jquery validation method
    jQuery.validator.addMethod('greaterThan', function (value, element, params) {
        if (!/Invalid|NaN/.test(new Date(value))) {
            return new Date(value) > new Date($(params).val());
        }
        return isNaN(value) && isNaN($(params).val()) || (parseFloat(value) > parseFloat($(params).val()));
    }, '');

    // and an unobtrusive adapter
    jQuery.validator.unobtrusive.adapters.add('futuredate', { }, function (options) {
        options.rules['greaterThan'] = true;
        options.messages['greaterThan'] = options.message;
    });
</script>

1
@raklos, das hängt von den Lokalisierungseinstellungen des Browsers und des Servers ab. Wenn Sie Unterschiede haben, werden die Dinge kompliziert, da ein Format die Client-Validierung bestehen kann, nicht jedoch die Server-Validierung und umgekehrt. Es liegt auch an Ihnen zu entscheiden, in welchem ​​Format Ihre Daten sein sollen.
Darin Dimitrov

aaah ich könnte dich dafür küssen
Shekhar

2
gutes Beispiel. Um die Client - Seite Arbeit für mich zu bekommen benötigt der Adapter Wechsel return new Date(value) > new Date($(params).val()); zu return new Date(value) > new Date();. neues Datum ($ (params) .val ()) bis neues Datum ()
PhilW

Ich habe ein Problem damit, dass die Clientseite mit Ajax.BeginForm anstelle von Html.BeginForm funktioniert. Würde es in diesem Szenario ein Problem geben?
user1790300

1
@kehrk, ja, wenn Sie ASP.NET 4-Bundles verwenden, ist es am besten, sie zu einem Teil eines Bundles zu machen.
Darin Dimitrov

5

Es hat eine Weile gedauert, bis Ihre Frage gestellt wurde. Wenn Sie jedoch immer noch Metadaten mögen und immer noch offen für vereinfachte Alternativen sind, können Sie Ihr Problem mithilfe der folgenden Anmerkungen lösen:

[Required]
[AssertThat("Date > Now()")]
public DateTime? Date { get; set; }

Es funktioniert sowohl für Server als auch für Clients. Weitere Informationen finden Sie in der ExpressiveAnnotations- Bibliothek.


Du hast meinen Tag mit deiner Bibliothek gerettet. So einfach zu bedienen und sehr nützlich. Vielen Dank
Maco
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.