Archiv der Kategorie: Validation

AngularJS ng-pattern mit CamelCase Pattern als Beispiel


AngularJS bietet die unterschiedlichsten Direktiven zum Validieren von Eingabefeldern an und darunter befindet sich auch die Direktive “ng-pattern” mit der Eingabewerte über Reguläre Ausdrücke validiert werden können. Da ich mit Regulären Ausdrücken nicht so viel zu tun habe, habe ich mich bei der ersten Verwendung etwas schwer getan und leider gab es auch kein direktes Beispiel in der Dokumentation.

Ich habe mir einen Regulären Ausdruck erstellt der prüfen soll ob die Eingabe in “CamelCase” Schreibweise eingegeben wurde.

Regulärer Ausdruck:  /^((^[A-Z][a-z0-9]+)([A-Z][a-z0-9]+)*)$/

Wenn hier jemand eine effektiveren Ausdruck kennt dann freue ich mich sehr über einen passenden Kommentar.

In AngularJS kann der Reguläre Ausdruck direkt dem “ng-pattern” übergeben werden

<input type="text" 
             name="ccName" 
             data-ng-model="ViewModel.CamelCaseName" 
              data-ng-pattern="/^((^[A-Z][a-z0-9]+)([A-Z][a-z0-9]+)*)$/" 
              placeholder="Enter CamelCase String">

oder man speichert ihn im Controller in einer Variablen und übergibt diese dem “ng-pattern”. Achtung um das Regex Pattern keine Anführungszeichen setzen!

...
  $scope.ViewModel = {
        CamelCaseName: "TestCamleCase",
        CamelCasePattern: /^((^[A-Z][a-z0-9]+)([A-Z][a-z0-9]+)*)$/
    };
...

im “ng-pattern” die Variable setzen statt des Patterns.

<input type="text" 
             name="ccName" 
             data-ng-model="ViewModel.CamelCaseName" 
              data-ng-pattern="ViewModel.CamelCasePattern"
              placeholder="Enter CamelCase String">

Zum Erstellen und überprüfen von Regulären Ausdrücken verwende ich auch gern die folgende Webseite:

https://regex101.com/r/gM3qM0/1#javascript

Das ganze Codebeispiel findet man auch wieder in Codeplex.

MVC Custom Validation mit IValidatableObject Interface


Letzte Woche wurde ich auf ein Interface aufmerksam gemacht, welches ich bisher in MVC noch nicht benutzt habe. Dabei handelt es sich um das IValidatableObject Interface, mit diesem Interface kann man sehr einfach alle möglichen und komplexen Validierungen für sein Model einbinden. Die Daten können dann an geeigneter Stelle mit “ModelState.IsValid” geprüft werden.

Dafür muss im Model nur das Interface “IValidatableObject” eingebunden werden und mit dem Interface noch die dazu verbundene Funktion “Validate”. In dieser Funktion werden die Daten nach den eigenen Vorstellungen geprüft, nach Abfragen die die Standardattribute wie “Required”, “MinLength”, …nicht abdecken. Dazu gehört z.B. der Vergleich zweier Datumswerte oder Strings. Dazu lassen sich dann Benutzerdefinierte Fehlermeldungen angeben und bei welchen Eingabefeldern diese Fehlermeldungen angezeigt werden sollen.

public class CustomValidationModel : IValidatableObject
{
    [Required]
    public string Name { get; set; }

    [Required]
    [DataType(DataType.Date)]
    public DateTime Birthdate { get; set; }

    [Required]
    [DataType(DataType.Date)]
    public DateTime Deathdate { get; set; }

    [Required]
    public int MinValue { get; set; }

    [Required]
    public int MaxValue { get; set; }

    public void Initilize()
    {
        Birthdate = DateTime.Now.Date;
        Deathdate = DateTime.Now.Date.AddYears(100);
    }

    /// 
    /// Die Custom Validate Methode die durch das Interface eingebunden wird.
    /// 
    public IEnumerable Validate(ValidationContext validationContext)
    {
        if (Birthdate.Date < DateTime.Now)
        {
            yield return new ValidationResult("Das Geburtsdatum muss in der Zukunft liegen", new[] { "Birthdate" });
        }

        if (MinValue  10 && MinValue > 10)
        {
            //Ausgeben der passenden Fehlermeldung und angeben bei welchen Werten die Fehlermeldung angezeigt werden soll
            yield return new ValidationResult("MaxValue und MinValue dürfen nicht größer wie 10 sein.", new[] { "MinValue", "MaxValue" });
        }

        if (Name.Trim().Length > 3 && !Name.StartsWith("Sq"))
        {
            yield return new ValidationResult("Wenn der Name länger wie 3 Zeichen ist, muss dieser mit 'Sq' beginnen.", new[] { "Name" });
        }
    }
}

Dazu muss im Controller nur noch “ModelState.IsValid” geprüft werden und schon haben wir unsere eigene Validierung eingebunden.

public ActionResult CustomValidation()
{
    CustomValidationModel model = new CustomValidationModel();
    model.Initilize();
    return View("CustomValidation", model);
}

[HttpPost]
public ActionResult CustomValidation(CustomValidationModel model)
{
    if (ModelState.IsValid)
    {
        //TODO Valides Model - Aufgaben ausführen
    }

    return View("CustomValidation", model);
}

Im View selbst können die Fehlermeldungen wie gewohnt direkt über “Html.ValidationMessageFor()” bei jedem Eingabefeld ausgegeben werden oder über das “Html.ValidationSummary()” global angezeigt werden.

</pre>
<div class="control-group">@Html.LabelFor(model => model.Name, new { @class = "control-label" })
<div class="controls">@Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name)</div>
</div>
<pre>

 

Der Nachteil an dieser Lösung ist, das leider keine direkte Möglichkeit besteht die Serverseitige Validierung mit der Clientseitigen Validierung zu verbinden. Wer also Serverseitige und Clientseitige Validierung in MVC mit Bordmitteln verbinden möchte, der sollte sich zum ValidationAttribute und dem zugehörigen Interface IClientValidatable z.B. hier belesen.

Codeplex:

Dann unter “Source Code” –> “Browse” –> “Testprojekte” –> “Mvc4WebApiKoTb” hier findet Ihr dann die Wichtigsten Dateien im Webprojekt unter “Views/Home/CustomValidation”, “Models/HomeModels/CustomValidationModel”.

MVC Client Datenvalidierung für “dd.MM.yyyy” mit jQuery Globalize


Ich hatte bei meiner MVC Anwendung das Problem, das die Clientseitige Validierung eines Datums aus meinem Model als nicht “richtig” erkannt wurde und damit ist die Clientseitige Validierung fehlgeschlagen. Dabei wurde das Datumsformat in Browser als “dd.MM.yyyy” angezeigt und als ungültiges Datum erkannt, trotz eines gültigen Datums.

Model:

[Required]
[Display(Name = "Jobstartdate", ResourceType = typeof(WorktimeViews))]
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }

Fehlermeldung im Browser:

image

Als erstes habe ich das NuGet Package “jquery-globalize” zu meinem Projekt hinzugefügt, hier habe ich aber nur einige der “Sprachen” im Projekt behalten.

image

Dann habe ich das Bundle für die JavaScript Bibliotheken angepasst und die Globalize Funktionen nach meinen anderen jQuery Bibliotheken eingefügt.

  bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*", 
                        "~/Scripts/jquery.globalize/globalize.js",
                        "~/Scripts/jquery.globalize/cultures/globalize.culture.de-DE.js",
                        "~/Scripts/_myjQueryExtensions.js"));

und in meiner eigenen “_myjQueryExtensions.js” noch die folgenden Zeilen an Code hinzugefügt. In der Document Ready Funktion gibt man noch an welche Sprache aktuell für die Validierung genutzt werden soll.

jQuery.validator.methods.date = function(value, element) {
    return Globalize.parseDate(value);
};

$.validator.methods.number = function(value, element) {
    if (Globalize.parseFloat(value)) {
        return true;
    }
    return false;
};

jQuery(document).ready(function () {
    Globalize.culture("de-DE");
});

Dann wurde mein Datum “dd.MM.yyyy” als gültiges Datum erkannt und es gab KEINEN Validation Error mehr. Selbiges geht wohl auch für Zahlenwerte ob Komma oder Punkt als Tausendertrennzeichen verwendet werden soll. Das ganze lässt sich auch ausbauen, damit die richtige Sprache verwendet wird, je nach Client der sich die Webseite anzeigen lässt in meinem Beispiel habe ich hier hart die “de-DE.js” verwendet.

Probleme gab es bei mir im Chrome v23.xx mit dem Datum hier wurde vom Chrome ein “falsch” formatiertes Datum an die parseDate Methode übergeben. Außerdem gibt es Probleme mit der Range Validation Methode im MVC und Double werten.

Quellen:

http://blog.brainnovative.com/2010/12/globalizing-aspnet-mvc-unobtrusive.html

http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-validation-to-the-model

MVC 3 und Remote Validation Attribute


wie bereits in einem anderen Post von mir “versprochen” noch eine Anleitung dazu wie man Remote Validation unter MVC 3 nutzt. Remote Validation bedeutet das vom JavaScript auf der Webseite bei der Eingabe eine Controllermethode aufgerufen wird, welche den Inhalt auf Richtigkeit prüft. Das könnte wie in meinem Falle z.B. sein ob der Nutzer bereits existiert wenn man sich neu auf einer Webseite registrieren möchte.

image

Wir befinden uns im  passenden Model und betrachten hier einfach ein Property, was bereits mehrere Attribute besitzt. Der Erste Parameter im Remote Attribute ist der Methodenname der aufgerufen werden soll und der zweite ist der Controllername in dem sich die Methode befindet, dies sind die beiden wichtigsten Parameter, mit den restlichen Parametern kann wie immer die Fehlermeldung angepasst werden.

Es ist auch noch möglich das die Remote Validation von einem weiteren Feld abhängig ist dies kann mit der Eigenschaft “AdditionalFields” im Remote Attribute mit angegeben werden und unsere Methode wird dann mit zwei Strings statt einem aufgerufen.

Die zugehörige Methode wird dann im passenden Controller definiert und erhält als Übergabeparameter unseren Eingabewert und als Rückgabewert wird Json verwendet, hier ist der zweite Parameter “JsonRequestBehavior.AllowGet” wichtig, ohne diesen Parameter wird unsere Methode nicht aufgerufen.

image

Das war alles was für Remote Validation benötigt wird.

Damit Remote Validation auch funktioniert muss in der web.config auch JavaScript aktiviert sein.

image

Hinweis: Wenn entweder in der web.config oder beim Nutzer im Browser JavaScript ausgeschalten ist, dann funktioniert auch unser Remote Validation Attribute nicht mehr. Bei diesem Attribut gibt es auch keine Serverseitige Validierung die dann automatisch einspringt, d.h. man muss immer noch im Controller selbst eine Serverseitige Validierung mit einbauen!

RegularExpression Attribut–Email


Wenn man unter ASP.NET MVC 3 zur Validierung eines Eintrages das RegularExpression Attribut verwendet, muss darauf geachtet werden das auch der Reguläre Ausdruck der verwendet wird auch von JavaScript Interpretiert werden kann. Denn wenn man hier einen ungültigen Regulären Ausdruck verwendet, kann es sein das auch z.B. ein Remote Attribute was auf dem Property gesetzt wurde nicht mehr funktioniert und nicht mehr aufgerufen wird.

Folgender Regex Ausdruck für eine Gültige Mailadresse geht nicht im RegularExpression Attribut:

@“^(?(„“)(„“.+?““@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&’\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$“

Aber dafür geht der Folgende Regex Ausdruck:

@“^([\w\!\#$\%\&\’\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\’\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-zA-Z0-9]{1}[a-zA-Z0-9\-]{0,62}[a-zA-Z0-9]{1})|[a-zA-Z])\.)+[a-zA-Z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$“

Quelle: http://tdryan.blogspot.com/2010/12/aspnet-mvc-3-custom-validation.html

Messages in MVC zwischen Views bzw. Controllern “übergeben/anzeigen”


Zum übermitteln von Nachrichten zwischen den Views gibt es die unterschiedlichsten Möglichkeiten, man könnte z.B. die Meldungen auch in der URL übergeben, was den Nachteil hat, die URL sieht “unsauber” aus und der Fehler kann evtl. mehrfach angezeigt werden. Denn mit den Methoden die bereits in MVC bereitgestellt werden “ModelState.AddModelError” lassen sich nur Fehler auf dem aktuellen View und Controller ausgeben, sobald man eine Fehlermeldung auf einer anderen Seite ausgeben möchte, ist dies nicht mit “Bordmitteln” von MVC möglich.

Daher habe ich mich für das Abspeichern der Nachrichten im Controller TempData entschieden, da diese Daten nach dem ersten Abrufen wieder aus TempData gelöscht werden. Dazu muss man einmal eine Klasse erstellen auf die man im Controller zugreift und am besten noch einen HTML-Helper der einem die Nachricht dann ganz einfach im View ausgibt.

Außerdem wollte ich gerne unterschiedliche Nachrichtentypen haben, und nicht nur Fehler ausgeben, denn es gibt ja z.B. auch noch Bestätigungen das das Speichern erfolgreich war oder Warnungen.

Als erstes erstellen wie eine Nachrichtenklasse:

image

Die wir später als Grundlage für die Nachricht nehmen die wir übermitteln wollen und dann benötigen wir noch eine Klasse für die Logik, damit wir die Nachrichten so einfach wie möglich unserem TempData hinzufügen können. Am besten mit einem Singleton Pattern, damit wir weniger schreiben müssen beim Hinzufügen der Message.

Im Folgenden also die Logikklasse, welche im Konstruktor den aktuellen Controller benötigt, damit auf TempData zugegriffen werden kann und die Message abgelegt wird.

image

(Leider habe ich bisher noch keine andere Lösung gefunden wie man evtl. noch auf TempData zugreifen kann ohne den Controller übergeben zu müssen, denn dann wäre der Aufruf noch kürzer, über Hinweise freue ich mich sehr!)

Hinzufügen einer Message in Controller oder einer anderen Klasse, hier muss nur jeweils der aktuelle Controller mit übergeben werden.

image

image

Die Anzeige der Fehlermeldung ist, dann ganz Einfach über eine HTML-Helper Extension gelöst und kann in jedem View zum Einsatz kommen, dabei spielt es keine Rolle in welchem Controller oder View die Meldung hinzugefügt wurde.

image

Es müssen dann natürlich noch für die jeweiligen MessageTypes die passenden Css Klassen angelegt werden, damit die Messages auch in der passenden Farbe angezeigt werden können.

Im View reicht es dann einfach nur an der passenden Stelle wo der Fehler angezeigt werden soll den Helper aufzurufen und schon funktioniert das ganze einwandfrei:

image

MVC 3 und Benutzerdefinierte Überprüfung der Eingaben mit dem “ValidationAttribute”


Unter ASP.NET MVC 3 ist es sehr einfach sich ein eigenes Validation Attribut zu erstellen, welches dann im Model verwendet werden kann. Ich wollte zum Beispiel prüfen ob ein User Bereits existiert beim Anlegen eines neuen Users.

image

Mit Hilfe meines eigenen Attributes “CheckUserExistsAttribute”, dazu einfach eine neue Klasse anlegen und diese von “ValidationAttribute” ableiten und die Funktion “IsValid” überschreiben.

image

 

Damit ist man schon fertig, wenn man jetzt z.B. auf einer Webseite schon ein Required Attribut verwendet bei einem anderen Property, dann wundert man sich warum das eigene Benutzerdefinierte Attribut nicht “geprüft” wird, in meinem Falle existierte “jr@gmx.de” bereits, wurde aber nicht angezeigt über mein Attribut.

image

Das hat den Hintergrund, das für die bereits implementierten Attribute automatisch die die Validierung per JavaScript eingestellt ist (bei MVC 3) in der web.config und mein Benutzerdefiniertes Attribut keine solche Implementierung beinhaltet und erst auf dem Server ausgewertet wird bei einem kompletten Postback.

image

Die Einbindung von Remote Validation bzw. der zusätzlichen Validierung unter der Hilfe von Javascript kann man auch hier finden:

http://highoncoding.com/Articles/767_Remote_Validation_in_ASP_NET_MVC_3.aspx

http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html

bzw. in dem folgenden Blogpost