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?

Raklos
quelle

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>
Darin Dimitrov
quelle
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.

jwaliszko
quelle
Du hast meinen Tag mit deiner Bibliothek gerettet. So einfach zu bedienen und sehr nützlich. Vielen Dank
Maco