RJP
RJP

Reputation: 4116

How can a persist an IEnumerable value during a post

I have the following ViewModel:

 public class ViewModel
    {
        public Address Address {get;set;}
        [DisplayName("State")]
        public IEnumerable<SelectListItem> StateSelect { get; set; }
        public string StateID { get; set; }


        public ViewModel()
        {
        }

        public ViewModel(Stuff s, IDataContext dc)
        {
            StateSelect = dc.States.ToList().Select(x => new SelectListItem
                                                             {
                                                                 Value = x.Id.ToString(),
                                                                 Text = x.Name
                                                             });
           Address = s.Address;


        }

And in my Edit View:

<div class="display-field">
                @Html.DropDownListFor(model => model.Address.StateID, Model.StateSelect,)
                @Html.ValidationMessageFor(model => model.StateSelect)
            </div>

My controller:

public ActionResult Edit(int id)
        {
            var stuff = context.Stuff.Find(id);
            if (stuff== null)
            {
                throw new Exception("Stuff not found.");
            }
            return View(new ViewModel(stuff, context));
        }

        [HttpPost]
        public ActionResult Edit(ViewModel model)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    //deeper logic, adds to ModelState.AddModelError
                    if(stillNotValid)
                         return View(model)
                }
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

Now, in my Edit view the dropdown list populates correctly. However, when I post to Edit in my controller, my model always has a null StateSelect.

How can I make sure StateSelect is pushed to my Edit post so that if there are validation errors I can re-populate the dropdown?

Upvotes: 0

Views: 330

Answers (3)

Suhas
Suhas

Reputation: 8458

I would avoid persisting data across browser requests like this for variety of reasons

  1. HTTP is designed to be state-less and it scales well if your develop your forms to be as stateless as possible
  2. Adding state information in the form like that means generating unnecessary HTML which takes time to build on server, takes time to transfer to client and takes time to render in the browser, overall taking a big hit on the performance (though you can argue against it using things like "request compression")
  3. If you have got jQuery like things running on client side, then DOM parsing becomes inefficient because your DOM has too much of HTML

Having said that, you can implement some amount of data persistence in the form of hidden variables in cookies given it's small amount of data and used to track how your user ended on your form, or how much of a wizard user has completed etc.

Upvotes: 0

Kirill Bestemyanov
Kirill Bestemyanov

Reputation: 11964

To post StateSelect to controller, you must write its elements to hidden fields with special names (look at this how to do it). But you can refill this IEnumerable in controller action Edit after post. It will be right decision.

Upvotes: 0

Dima
Dima

Reputation: 6741

You need to put you collection inside the <form /> to post it to the server with request. In this case, most likely, you'll have to build markup "by hands" using hidden inputs or put your markup inside hidden block to hide it from user.

Are you sure you want to send this list back and forth only to have this collection in view model? There is another solution - send this list to the View in ViewBag and bind it in your Actions. This will keep you from <form /> modelling and reduce post request size.

Upvotes: 1

Related Questions