Hvis man har arbejdet lidt med ASP.NET MVC3 og formularer,
kender man givetvis "validationattributes", der bla. giver let
adgang til validering af om et felt er udfyldt eller om værdien
ligger indenfor et interval osv. Der findes en håndfuld i MVC3 som
man får serveret på et sølvfad.
Hvis du er i tvivl om hvad jeg snakker om, så ser det nogenlunde
således ud i modellen:
public class Person
{
[Required]
public string Navn { get; set; }
[Required]
public string Adresse { get; set; }
}
Formularen kunne se således ud i View:
@model Person
@using(Html.BeginForm())
{
@Html.LabelFor(m => m.Navn)<br/>
@Html.EditorFor(m => m.Navn)<br/>
@Html.ValidationMessageFor(m => m.Navn)<br/>
@Html.LabelFor(m => m.Adresse)<br/>
@Html.EditorFor(m => m.Adresse)<br/>
@Html.ValidationMessageFor(m => m.Adresse)<br/>
<br/>
<button type="submit">Gem</button>
}
Dette vil, ved postback, resultere i en validering, på serveren,
af om Navn og Adresse indeholder noget (som ikke er en tom streng
eller mellemrum). Hvis den ikke er gyldig, vises
standardfejlbeskeden for Required i de felter som
Html.ValidationMessageFor genererer.
Hvis man ønsker at få valideret sin formular på klienten, kan
man blot inkludere jQuery basis biblioteket, samt jquery.validate
og jquery.validate.unobtrusive i forbindelse med formularen, eller
i basis-layoutet, hvis man har mange formularer på sit site. Noget
i stil med dette:
<script src="/scripts/jquery-1.7.2.min.js"></script>
<script src="/scripts/jquery.validation.min.js"></script>
<script src="/scripts/jquery.validation.unobtrusive.min.js"></script>
Med disse inkluderet i siden med formularen, skulle valideringen
allerede ske inden data sendes til serveren og det er jo ofte en
god ting (for brugeren og for din server).
Der findes, som standard, 5 valideringsatributter i MVC,
der spiller sammen med jquery.validate. Disse er:
- Required (som vist tidligere)
- StringLength
- Range
- RegularExpression
- Compare.
jquery.validate har yderligere 6 i værktøjskassen,
nemlig:
- Email
- Url
- Date
- Number
- Digits
- Creditcard
Disse er dog ikke umiddelbart tilgængelige som server
validationatributter, så hvis man vil have mere
valideringsfunktionalitet end de 5 første, må man til at strikke
sine egne atributter sammen. Det er nu heller ikke så galt
endda!
Egne klient/server valideringsatributter
Alle valideringsatributter bør nedarve fra ValidationAttribute,
det kommer dem jeg laver i det mindste til. Hvis vi gør det, kan vi
lave en ny regel, der validerer om et felt indeholder en
emailadresse, med følgende kode:
public class EmailAddressAttribute : ValidationAttribute
{
private static readonly Regex rxEmail =
new Regex("^\\S+@(\\S+\\.)+\\S+$");
public EmailAddressAttribute()
{
ErrorMessage = "Please enter a valid email address.";
}
public override bool IsValid(object value)
{
if (value == null)
return false;
string v = (value as string).Trim();
return !String.IsNullOrEmpty(v) && rxEmail.IsMatch(v);
}
}
Med dette kode, har vi en validationattribute vi kan bruge i
vores model og dermed få validering af e-mailadresser.
public class Person
{
[Required]
public string Navn { get; set; }
[Required]
public string Adresse { get; set; }
[EmailAddress]
public string Email { get; set; }
}
Som man kan se er der sat validering på det nye Email-felt i
Person-klassen. Der er dog ikke klientvalidering på Email-feltet
endnu, så det må vi hellere få lagt på.
Dette gøres ved at implementere interfacet IClientValidatable,
hvilket kunne gøres nogenlunde således:
public class EmailAddressAttribute : ValidationAttribute
, IClientValidatable
{
// ... valideringskoden fra før ...
public IEnumerable<ModelClientValidationRule>
GetClientValidationRules(
ModelMetadata metadata,
ControllerContext context
)
{
return new List<ModelClientValidationRule> {
new ModelClientValidationRule {
ValidationType = "email",
ErrorMessage = this.ErrorMessage
}
};
}
}
Med denne kode kan vi nu forvente at der sker en validering af
Email-feltet på formularen, både på klienten og på serveren
(forudsat vi har placeret feltet på vores View efter samme metode
som for Navn og Adresse).
Hvis man har særlige valideringsbehov, kan man også udvide
jquery.validator med nye valideringsrutiner. Dette vil jeg dog lade
vente til en anden artikel.
NB: Beklager den lidt spøjse formatering af koden, men
sidelayoutet bød mig at gøre et eller andet for at holde styr på
den kodeeksemplerne :-)