Question

I have a simple form which saves the following entity

public class TravelInfo{
  public int ID {get;set;}
  public string CentreCode {get;set;}
  public DateTime TravelDate {get;set;}
}

I have the standard 2 create methods in my controller - 1 get 1 post and am using this viewmodel to get stuff into the view.

public class TravelInfoVM{
  public TravelInfo TravelInfo{get;set;}
  public IEnumerable<SelectListItem> Centres {get;set;}
}

Controller methods...

public ActionResult Create(){
  var CentresList = db.Centres.Select(c=> new SelectListItem {Text = c.Name, Value = c.Code}).ToList();
  TravelInfoVM = new TravelInfoVM(){Centres = CentresList};
  return View(TravelInfoVM);
}

[HttpPost]
public ActionResult Create(TravelInfoVM model){
  //the Centres part of the model at this point is empty
  if(ModelState.IsValid){
    //save
    //redirect
  }
  //do i **REALLY** have to get it again as below, or can I hold on to it somehow?
  model.Centres = db.Centres.Select(c=> new SelectListItem {Text = c.Name, Value = c.Code}).ToList();
  return View(model);
}

the question is, do I really need to do a second round trip to the DB to get the list of Centres if the ModelState comes back as invalid? or is there a better/different way to persist this list across posts, until the user correctly enters the details required to save..? or do i have completely the wrong end of the stick..

Was it helpful?

Solution

Not without adding it to the session, which is an inappropriate use of the session. Otherwise, each request is a unique snowflake, even if it seems like it's the same because you're returning the same form with errors.

I wouldn't worry about this. It's just one query, and since it's the same query already issued previously, it will very likely (or at least could be) cached, so it may not actually hit the database, anyways.

One thing I would recommend though is abstracting the query so that your GET and POST actions will simply call a function that won't change, and if you need to make a change to how the select list is created, you just do it in one place:

internal void PopulateCentreChoices(TravelInfoVM model)
{
    model.Centres = db.Centres.Select(c=> new SelectListItem {Text = c.Name, Value = c.Code}).ToList();
}

...

public ActionResult Create(){
  var model = new TravelInfoVM();
  PopulateCentreChoices(model);
  return View(model);
}

[HttpPost]
public ActionResult Create(TravelInfoVM model){
  if(ModelState.IsValid){
    //save
    //redirect
  }
  PopulateCentreChoices(model);
  return View(model);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top