Question

My MVC application was working fine - it displayed a list of people on the page using EF as the back end.

I now have to add the ability to refine the search.

So, I updated my Model to contain 2 properties, 1 for the results (called AllMyPeople), the other for the search value (called SearchMyPeople).

The results still show on the webpage, but I'm having issues with the refine your search, in particular, a DropDownListFor()

This is the code I'm using

 @Html.DropDownListFor(a=> a.SearchMyPeople.Gender, Model.SearchMyPeople.Gender, "---Select---")

The Gender is of type List<SelectListItem>

In the controller, I have the following

    public ActionResult ShowPeople()
    {
        var model = this._myPeople;
        return View(model);
    }

    [HttpPost]
    public ActionResult ShowPeople(MyPeople people)
    {
        return View(people);
    }

When the page first loads, my dropdownlist is populated as desired. The issue is when I submit.

I put a break point in the second method, and I can see in the debug window people.SearchMyPeople.Gender has 0 items. This means the model is updating, just not as I wanted... I would have hoped it had 1 item (the value selected from the HTML page)

I am using 2 Html.BeginForm() on the page if that matters?

Any clues as to what I'm doing wrong?

Was it helpful?

Solution

Http is stateless. your state won't stay between your requests (in webforms, it is posssibel thru viewstate, but in MVC there is no viewstate). You need to reload the collection(Genders) before sending the model back the view.

Looks like you are using your domain models in your view. I would personally create a simple viewmodel to handle this.

public class PersonSearchVM
{
  public string SelectedGender { set;get;}
  public List<SelectListItem> Genders { set;get;}
  public List<Person> Results { set;get;}

  public PersonSearchVM()
  {
     Genders=new List<SelectListItem>();
     Results =new List<Person>();
  }
}

And your action methods, create an object of your viewmodel, load the Genders collection and send the view model to the view which is strongly typed to our view model.

public ActionResult Search()
{
  var vm=new PersonSearchVM { Genders=GetGenders()};
  return View(vm);
}
[HttpPost]
public ActionResult Search(PersonSearchVM model)
{
  string selectedVal=model.SelectedGender;
  if(!String.IsNullOrEmpty(selectedVal)
  {
    model.Results=GetSearchResultsFromSomeWhere(selectedVal);
  }
  model.Genders=GetGenders(); //reload dropdown items
  model.SelectedGender=selected;
  return View(model);
}
private List<SelectListItem> GetGenders()
{
  return new List<SelectListItem> { 
     new SelectListItem { Value="Male",Text="Male"},
     new SelectListItem { Value="Female",Text="Female"},
  };
}

In your Search view, Use Html.DropDownListFor html helper method.

@model PeopleSearchVM
@using(Html.BeginForm())
{
   @Html.DropDownListFor(s=>s.SelectedGender,Model.Genders,"Select")
   <input type="submit" value="Filter" />
   @foreach(var person in Model.Results)
   {
     <p>@person.FirstName</p>
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top