In the last article we learned how to create the navigation aspect of the wizard using ASP.NET MVC Framework. In this article we are going to make sure that our user input is persisted when we move between different steps.
ViewState to the Rescue:
In WebForms environment the ASP.NET wizard control used to maintain the state of the user input by using the ViewState. The ViewState was persisted in the form of hidden field which was part of the page. For our ASP.NET wizard scenario we have to use the same concept to persist the user data for the wizard steps.
Creating Serialize and Deserialize Methods:
Our first task is to create Serialize and Deserialize methods which will be responsible for the compact ASCII format serialization to hold user input data. The serialized object will work as ViewState and will be injected into the page. We have implemented our methods as extension methods but you can choose any path you like. The code is shown below:
The next step is to override the controller's OnActionExecuting and OnResultExecuted methods which is covered in the next section.
Overriding OnActionExecuting and OnResultExecuted Methods:
The purpose of overriding these methods is to update the model which in this case is Customer with the new data. Every time a page is submitted we deserialize a hidden field and try to update the model. The implementation of both the methods is shown below:
Inside the OnActionExecuting method we deserialize the Request.Form["Customer"] parameter. If Request.Form["Customer"] is null then we look into the TempData dictionary. If the TempData["Customer"] is null then we create a new Customer.
It is always a good idea to use ViewModel approach when building MVC applications. ViewModel will add another layer on top of the actual domain model and will more clearly reflect the interaction of the user with the user interface layer. In the future articles we will look into how to use the ViewModel approach while building MVC applications.
The above code will only work if we have element named "Customer" in the Form collection. The next section shows how to add a hidden field which is responsible for serializing the object.
Adding Hidden Field to the Page:
In order to create a ViewState effect we need to store the serialized information of the object in the hidden field. The implementation is shown below:
For the class "Customer" to be serialize it must be marked with the Serializable attribute as shown below:
Also, mark the Address class with the Serializable attribute. The Model object in the View gets populated by the following code:
The code has been altered to return View(_customer) which makes sure that the View always has the updated model to work with.
If you run the above code you will notice that the BasicDetails view is persisting the changes but the AddressDetails is not. The AddressDetails HTML code looks like the following:
Can you point out the mistake? Yes, you are right the problem lies in the binding of the Street, City and the State fields. Since, the view only knows about the Customer object we need to help the view to find the fields used in the AddressDetails view. The correct way is to use the HomeAddress property in the Customer object to access the Street, City and State fields. The implementation is shown below:
Now, if you run the above code it will work as expected.
References:
1) Pro ASP.NET MVC Framework by Steven Sanderson
Recommended Reading:
1) Creating Wizard Using ASP.NET MVC Framework Part 1
2) Populating Hierarchical Data Using Model Binders in ASP.NET MVC
Conclusion:
In this article we learned how to persist the user input while moving across different steps in the wizard. In the next article we will focus on how to handle the validation errors in the wizard.
[Download Sample]