I've been playing around with the ASP.NET MVC Framework and the one thing that's really confusing me is how I'm meant to do server side validation of posted form data. I presume I don't post back to the same URL, but if I don't, how do I redisplay the form with the entered data and error messages? Also, where should the validation logic go? In the model or the controller? This seems to be one of the few areas where web forms are much stronger (I miss the validation controls).
Have you taken a look at this? http://www.codeplex.com/MvcValidatorToolkit
Quoted from the page
The Validator Toolkit provides a set of validators for the new ASP.NET MVC framework to validate HTML forms on the client and server-side using validation sets.
I'm afraid that someone more MVC-savvy than me would have to speak to where in the architecture you should put things.
I did take a look at the CodePlex project, but I wasn't impressed with what I saw (at the time). Maybe it's better now. I'll take another look.
Obviously, Jeff and the team must be validating the form data in StackOverflow. When I look at the HTML for the Ask a Question page, it looks like the page posts back to itself. I wonder how they are implementing the validation.
I'm just learning the MVC framework too so I'm not sure how off this is, but from what I understand you would have a form on a View such as Edit.aspx. This form would then post to the controller to another action method such as Update() passing in the contents of the form that you set in Edit.aspx as parameters.
Update(int id, string name, string foo)
You could do the validation within that method. If all is ok,
return View("Item", yourObject)
Here's an overview of the flow in MVC:
- /new - render your "New" view containing a form for the user to fill out
- User fills out form and it is posted to /create
- The post is routed to the Create action on your controller
- In your action method, update the model with the data that was posted.
- Your Model should validate itself.
- Your Controller should read if the model is valid.
- If the Model is valid, save it to your db. Redirect to /show to render the show View for your object.
- If the Model is invalid, save the form values and error messages in the TempData, and redirect to the New action again. Fill your form fields with the data from TempData and show the error message(s).
The validation frameworks will help you along in this process. Also, I think the ASP.NET MVC team is planning a validation framework for the next preview.
Lance, is the TempData bucket specific to that request? Obviously it would create problems if it was session based and multiple requests were trying to store data in the same bucket.
Also, is using TempData a hack? Is this the way other MVC frameworks solve the problem?
There is Castle.Components.Validator module in Castle project. It's very agile and powerfull. It generates validation rules based on model attributes (or any other source) and even able to generate JS validation using jQuery, Prototype Validation, fValidate and other. Of course it's wise to abstract validator away behind IValidationEngine interface.
You might want to take a look at ScottGu's latest post for ASP.Net prev 5. It walks through a validation sample that is very interesting:
As far as I can tell everyone is still trying to figure out the "standard" way of doing it. That said definitely check out Phil Haack and Scott Guthrie's latest posts on MVC and you'll find some interesting info on how they did. When I was just playing around with it for myself I created a ModelBinder for the LinqToSql data class that I had generated. You can check out this post to find out how to put together a basic ModelBinder:
The in your action if you had created a "Product" ModelBinder you would just declare the action like so:
public ActionResult New(Product prod)
And the model binder will take care of assigning posted data to the objects properties as long as you've built it right anyway.
After that within your GetValue() method you can implement whatever validation you want, whether using exception's, regex's, or whatever you can make a call like:
(ModelStateDictionary_name).AddModelError("form_element_id", "entered_value", "error_message");
Then you can just throw a <%= Html.ValidationSummary() %> in your view to display all your errors.
For client-side validation I just used jQuery. After you get a basic sample set up though you can start doing some interesting things combining all that with Partial Views and Ajax calls.