title: How to get a list of filter criteria from View to Controller in ASP.Net MVC
body: <p>Ok, so I have a database of objects called Contacts:</p>
  
  <pre><code>public class Contact
  {
      public Contact()
      {
          Interests = new List&lt;Interest&gt;();
      }
  
      public int Id { get; set; }
  
      public string Email { get; set; }
  
      public virtual IList&lt;Interest&gt; Interests { get; set; }
  
      public string AllInterests
      {
          get
          {
              string allInterests = "";
              foreach (Interest i in this.Interests)
              {
                  allInterests += "[" + i.Name.ToString() + "] ";
              }
  
              return allInterests;
          }
      }
  }
  </code></pre>
  
  <p>Which, as you can see, each contain a list of Interest objects:</p>
  
  <pre><code>public class Interest
  {
      public int Id { get; set; }
  
      public string Name { get; set; }
  
      public virtual ICollection&lt;Contact&gt; Contacts { get; set; }
  }
  </code></pre>
  
  <p>This is important, because I intend to include the ability to filter which Contacts from the database get sent to the Index view to be displayed in a table by whether or not their individual Interests contain one or more of the Interests chosen from the full list of Interests (or just show all of them if no Interests were selected. I cannot yet get this to work, but I imagine the code would look a little something like this:</p>
  
  <pre><code>public ActionResult Index(List&lt;InterestViewModel&gt; filterList)
  {
      List&lt;Contact&gt; allContacts = db.Contacts.ToList();
      List&lt;Contact&gt; filteredContacts = new List&lt;Contact&gt;();
      foreach(var filter in filterList.Where(f =&gt; f.IsSelected))
      {
          foreach(var contact in allContacts.Where(c =&gt; c.Interests.Any(i =&gt; i.Id == filter.Id)))
          {
              if (!filteredContacts.Contains(contact))
                  filteredContacts.Add(contact);
          }
      }
      return View(filteredContacts);   
      //return View(db.Contacts.ToList());
  }
  </code></pre>
  
  <p>There are probably a few reasons why this code isn't working, but first and foremost is the fact that I cannot for the life of me figure out how to actually return a list of Interests from a contact view, let alone get a working UI element to populate such a list from within the Index view itself. Could anyone here perhaps give some pointers for how to make something like this possible?</p>
  
  <p>P.S. If it helps, I already know how to <em>create</em> a Contact with a user-populated list of Interests using these ViewModels:</p>
  
  <pre><code>public class ContactViewModel
  {
      public int Id { get; set; }
  
      public string Email { get; set; }
  
      public virtual ICollection&lt;ChosenInterests&gt; Interests { get; set; }
  }
  
  
  
  public class ChosenInterests
  {
      public int Id { get; set; }
  
      public string Name { get; set; }
  
      public bool Selected { get; set; }
  }
  </code></pre>
  
  <p>And this Partial View for creating a UI element that lets you select a subset of Interests from the full list:</p>
  
  <pre><code>@model ContactExperiment.ViewModels.ChosenInterests
  @using ContactExperiment.ViewModels
  
  &lt;div&gt;
      @Html.HiddenFor(model =&gt; model.Id)
      @Html.CheckBoxFor(model =&gt; model.Selected)
      @Html.DisplayFor(model =&gt; model.Name)
  &lt;/div&gt;
  </code></pre>
  
  <p>(Which so far I have only gotten to work in the Create view here:)</p>
  
  <pre><code>@model ContactExperiment.ViewModels.ContactViewModel
  @using ContactExperiment.ViewModels;
  
  @{
      ViewBag.Title = "Create";
  }
  
  &lt;h2&gt;Create&lt;/h2&gt;
  
  
  @using (Html.BeginForm()) 
  {
      @Html.AntiForgeryToken()
  
  &lt;div class="form-horizontal"&gt;
      &lt;h4&gt;Contact&lt;/h4&gt;
      &lt;hr /&gt;
      @Html.ValidationSummary(true, "", new { @class = "text-danger" })
      &lt;div class="form-group"&gt;
          @Html.LabelFor(model =&gt; model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
          &lt;div class="col-md-10"&gt;
              @Html.EditorFor(model =&gt; model.Email, new { htmlAttributes = new { @class = "form-control" } })
              @Html.ValidationMessageFor(model =&gt; model.Email, "An email address is required", new { @class = "text-danger" })
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;div class="form-group"&gt;
          @Html.LabelFor(model =&gt; model.Interests, htmlAttributes: new { @class = "control-label col-md-2" })
          &lt;div class="col-md-10"&gt;
              @Html.EditorFor(model =&gt; model.Interests, new { htmlAttributes = new { @class = "form-control" } })
              @*@Html.ValidationMessageFor(c =&gt; c.Interests, "Must select at least one Interest", new { @class = "text-danger" })*@
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;div class="form-group"&gt;
          &lt;div class="col-md-offset-2 col-md-10"&gt;
              &lt;input type="submit" value="Create" class="btn btn-default" /&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  }
  
  &lt;div&gt;
      @Html.ActionLink("Back to List", "Index")
  &lt;/div&gt;
  
  @section Scripts {
      @Scripts.Render("~/bundles/jqueryval")
  }
  </code></pre>
  
  <p>But I have yet to successfully re-purpose these for anything other than the creation of a new Contact and the population of its list of Interests.</p>
  
  <p>EDIT: I suppose I should have included the code for the Index View itself, too. So far it just shows a list of all the Contacts and their relevant details just fine, but nothing else related to the filtering actions works or has been implemented:</p>
  
  <pre><code>@model IEnumerable&lt;ContactExperiment.Models.Contact&gt;
  @using ContactExperiment.ViewModels;
  @{
      ViewBag.Title = "Index";
  }
  
  &lt;h2&gt;Index&lt;/h2&gt;
  
  &lt;p&gt;
      @Html.ActionLink("Create New", "Create")
  &lt;/p&gt;
  
  
  &lt;div class="pull-right"&gt;
      @*@Html.EditorFor((ViewBag.InterestFilter as ICollection&lt;ChosenInterests&gt;).)*@
  &lt;/div&gt;
  
  &lt;table class="table"&gt;
      &lt;tr&gt;
          &lt;th&gt;
              @Html.DisplayNameFor(model =&gt; model.Email)
          &lt;/th&gt;
          &lt;th&gt;
              @Html.DisplayNameFor(model =&gt; model.Interests)
          &lt;/th&gt;
      &lt;/tr&gt;
  
      @foreach (var item in Model)
      {
          &lt;tr&gt;
              &lt;td&gt;
                  @Html.DisplayFor(modelItem =&gt; item.Email)
              &lt;/td&gt;
              &lt;td&gt;
                  @*@Html.ListBox("Id", new SelectList(item.Interests, "Id", "Name"))*@
                  @Html.DisplayFor(modelItem =&gt; item.AllInterests)
              &lt;/td&gt;
              &lt;td&gt;
                  @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                  @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                  @Html.ActionLink("Delete", "Delete", new { id = item.Id })
              &lt;/td&gt;
          &lt;/tr&gt;
      }
  
  &lt;/table&gt;
  </code></pre>