[RESOLVED]List<SelectListItem> does not retain on httppost

Below is the dropdownlist i use for Clients. When the user clicks Save and it POST.

When an error occurs and go back to the View. The DropDownList list values are disposed…It requires me to fill it in again before return to View?

This can’t be normal right? How come it doesn’t retain the list?

public ActionResult Create()
{
OrderViewModel model = new OrderViewModel();
model.ClientList = ListHelper.GetClientList();

return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "OrderId,ClientId,OrderType,OrderDate,Comments,OrderStatus")] OrderViewModel orderVM)
{
if (ModelState.IsValid)
{
var order = Mapper.Map<OrderViewModel, Order>(orderVM);

_orderRepository.Insert(order);
_orderRepository.Save();
//return RedirectToAction("Index");
return RedirectToAction("Edit", "Order", new { id = order.OrderId});

}

orderVM.ClientList = ListHelper.GetClientList();  —why i need to do this????

return View(orderVM);

}

This is normal.

SelectList values are not all going to be persisted between any posts that occur (unlike DropDownList values within Web Forms) since MVC is modeled more closely to the general HTTP protocol. When your form is posted, only the selected value(s) for
your particular element populated by your SelectList are going to be posted up and the rest will be disposed of.

The line that you see below :

// This is to handle something wrong, since your Model wasn't valid. You'll need to re-display the View (and show your options again)
orderVM.ClientList = ListHelper.GetClientList();  
return View(orderVM);

It’s the same exact reason that you have to populate these values prior to showing the View originally in your non-POST action :

public ActionResult Create()
{
    OrderViewModel model = new OrderViewModel();
    model.ClientList = ListHelper.GetClientList();
    return View(model);
}

So I would need to populate them in the httpget and httppost method?
Sounds like a lot of repeating code. Is there any elegant way of doing this?

alphabeatsco

So I would need to populate them in the httpget and httppost method?

Yes. But if you won’t be displaying the same view again in your httppost, then there’s no need.

alphabeatsco

Sounds like a lot of repeating code. Is there any elegant way of doing this?

In your case, I only see one line of code to populate the list so for me it’s not really "a lot". Maybe if it gets longer in the future, you can create a function. Then just call that function in your get and post.

alphabeatsco

So I would need to populate them in the httpget and httppost method?
Sounds like a lot of repeating code. Is there any elegant way of doing this?

Well technically, you only need to populate it when you will be presenting your Create View (e.g. the one returned from your HttpGet action). This is because you will need to present the user with their various options. So you’ll need to present
it every time the following action is called :

public ActionResult Create()
{
        return View(new OrderViewModel(){ ClientList = ListHelper.GetClientList()});
}

And you’ll only need to present it within the HttpPost when an error occurs (since you’ll basically be presenting the same exact View as the user will need to correct errors) :

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "OrderId,ClientId,OrderType,OrderDate,Comments,OrderStatus")] OrderViewModel orderVM)
{
     if (ModelState.IsValid)
     {
          // Everything is good, you'll be redirecting somewhere else
     }

     // If you are at this point, something is wrong so you'll need to present your previous View
     orderVM.ClientList = ListHelper.GetClientList();
     return View(orderVM);
}

This is really a generally acceptable way of handling this. I mean you could use some type of persistent storage to populate these values (such as calling ListHelper.GetClientList() within your View or storing it within the Session or something similar)
but the current code that you have should be fine for most situations as you’ll only be calling the values when you need them.

Leave a Reply