So if you were like me before I knew what Data Annotations were, you most likely would be thinking, “What are Data Annotations?”. Well I’m glad I can read your mind and therefore I am glad you asked.
Now the fun part about this post is that I might have to admit I was wrong. Why would that be? Well in this post I suggested that validation rules would be set in the controller. Turns out, there is possibly a better place, on the model itself. How can this be done??? Well that’s what you’re about to find out.
Say you have a user create model:
public class AddUserModel { public String UserName { get; set; } public String Password { get; set; } public String RepeatPassword { get; set; } }
Now you could have a method on the controller like:
public ActionResult AddUser(AddUserModel model) { if(IsValid(model)) { ... } }
Where you have to create the IsValid method for every model on the controller that you need to validate (And possibly on other controllers if you are sharing models between them…) Or you can have this:
public ActionResult AddUser(AddUserModel model) { if(ModelState.IsValid) { ... } }
And that is already built in so no validation method needed. But how is that possible? Attributes on the model or namely the ValidationAttribute class.
First off you have to include the System.ComponentModel dll in the project. Simple enough. Please say you know how to do that or do me a favor and remind yourself to blink. OK done? Good.
Now you can use some of the built in attributes which is good. Things like required are nice:
public class AddUserModel { [Required] public String UserName { get; set; } ... }
There you go. Now if the UserName is null or empty, the ModelState will no longer be valid and will fail this check:
ModelState.IsValid
Now you might wonder what the error message will be for that? Honest answer: I have no f–king clue. That’s why you can actually set it. Those guys at Microsoft thought of everything.
public class AddUserModel { [Required(ErrorMessage = "ENTER A USERNAME IDIOT!"] public String UserName { get; set; } ... }
The guys in the legal department have told me I have to note that your error message should change depending on your use and you shouldn’t use the one above. Whatever.
Now you might want to actually pass the errors back, and why wouldn’t you? You’re a fine, upstanding, and thoughtful person and I lie like a crook. The errors, if there are any, are in here:
ViewData.ModelState.Values
And you can use two loops to get to all of them, but I think the parent loop will only run once.
foreach (ModelState state in ViewData.ModelState.Values) { foreach (ModelError error in state.Errors) { messageList.Add(error.ErrorMessage); } }
Pretty nice huh? Maybe if you’re an idiot who just learned about this. For cool people like me, it’s old news.
What’s the point this? If “this” is data annotations: Well it helps move some of the validation off the controller if you are looking for a more “Fat model, skinny controller” design which I’m told is a good idea. This also gets rid of all the validation methods and saves time because of it.
If “this” is your life? I have no idea. But if you’re to the point that you’re asking me about the meaning of your life, you are in some serious trouble.
Nice, but how would I implement uniqueness?