Multiple postbacks in an MVC page
With my limited (but growing) experience in MVC, I’ve come up with a way to handle multiple postbacks to the same page in MVC. Here’s a simple application:
- User selects a category from a dropdownlist – causes postback and loads subcategories
- User selects a sub category and clicks on the submit button
- A confirmation message appears on the view
Here’s how I’ve implemented it. Created an MVC project and added two classes – Category and SubCategory:
1: public class Category
2: {
3: public int CategoryID { get; set; }
4: public string CategoryName { get; set; }
5: }
6:
7: public class SubCategory
8: {
9: public int SubCategoryID { get; set; }
10: public string SubCategoryName { get; set; }
11: public int CategoryID { get; set; }
12: }
In the HomeController’s Index method (GET version):
1: public ActionResult Index()
2: {
3: var categories = GetCategories();
4: var subCategories = GetSubCategories(0);
5:
6: ViewData["PreviousCategoryID"] = 0;
7:
8: ViewData["CategoryID"] = new SelectList(categories, "CategoryID", "CategoryName");
9: ViewData["SubCategoryID"] = new SelectList(subCategories, "SubCategoryID", "SubCategoryName");
10: return View();
11: }
The GetSubCategories(0) returns a dummy list taking zero as the default value for the categoryID. I’ll let you know what the ‘PreviousCategoryID’ is in a few. My View looks like this:
1: <h2>Movie Guide</h2>
2: <% using(Html.BeginForm()) { %>
3: <%= Html.Hidden("PreviousCategoryID", ViewData["PreviousCategoryID"]) %>
4: <p>
5: <%= Html.DropDownList("CategoryID", (SelectList)ViewData["Categories"],
6: new { onchange = "this.form.submit();" })%>
7: <p />
8: <%= Html.DropDownList("SubCategoryID", ViewData["SubCategories"] as SelectList)%>
9: <p />
10: <input type="submit" value="Submit" />
11: <p />
12: <%= ViewData["Message"] %>
13: </p>
14: <% } %>
So, the user selects a category from the list and post back occurs. Now, here’s the issue I want cleared off.
In order to determine which control caused the postback, in my Index method (POST version), I check the value of the CategoryID dropdownlist against the PreviousCategoryID. If they are different, I know the postback was caused by the dropdownlist and I populate the SubCategories list based on categoryID.
However, if they are same, I assume the postback was caused by the button click and hence I display the message to the user.
Is this the best way to do the check or am I missing something?
1: [AcceptVerbs(HttpVerbs.Post)]
2: public ActionResult Index(FormCollection formCollection)
3: {
4: var categoryID = int.Parse(formCollection["CategoryID"]);
5: var previousCategoryID = int.Parse(formCollection["PreviousCategoryID"]);
6:
7: // if these are different, then postback was caused by the category dropdownlist
8: if(categoryID != previousCategoryID)
9: {
10: var categories = GetCategories();
11: var subCategories = GetSubCategories(categoryID);
12:
13: ViewData["PreviousCategoryID"] = categoryID;
14:
15: var categoryList = new SelectList(categories, "CategoryID", "CategoryName", categoryID);
16:
17: ViewData["Categories"] = categoryList;
18: ViewData["SubCategories"] = new SelectList(subCategories, "SubCategoryID", "SubCategoryName");
19: return View();
20: }
21: // if not, assume a button click and show message to user
22: else
23: {
24: var categories = GetCategories();
25: var subCategories = GetSubCategories(0);
26:
27: ViewData["PreviousCategoryID"] = 0;
28:
29: ViewData["Categories"] = new SelectList(categories, "CategoryID", "CategoryName");
30: ViewData["SubCategories"] = new SelectList(subCategories, "SubCategoryID", "SubCategoryName");
31: ViewData["Message"] = "Your selected has been noted.";
32: return View();
33: }
34: }
Line 8 is where I check for the difference. If true, PreviousCategorID gets updated with the latest categoryID (line 13) and I can use it in the next postback.
This no doubt works, but seems a little ‘icky’ (sorry for the choice of words.. English IS my second language). Please let me know if there’s a better way to handle this situation.
Thanks
Arun