tags:

views:

754

answers:

4

I created a stongly typed view in an ASP.Net MVC project I'm working on, the view is just an index page that lists the contents of a SQL table in a grid.

I now want to add the functionality to filter this list. I've tried to do this by creating a form in the view with a drop down list containing the values you can filter by. The idea being that when the user submits that form it triggers the controllers Post index method which will grab the selected value the dropdown list from the FormCollection passed into the method.

For example my 2 index methods look like this

 public ActionResult Index()
    {
        DevAdminEntities db = new DevAdminEntities();
        ViewData["StatusDropDown"] = new SelectList(db.TaskStatuses, "TaskStatusId", "StatusName");
        return View(db.Tasks);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection formValues)
    {
        DevAdminEntities db = new DevAdminEntities();
        ViewData["StatusDropDown"] = new SelectList(db.TaskStatuses, "TaskStatusId", "StatusName");
        return View(from t in db.Tasks where t.Projects.ProjectId == int.Parse(Request.Form["StatusDropDown"]) new { t, t.Projects});
    }

The page displays fine when it loads in its unfiltered form but when I click the submit button to apply a filter I get the following error

"The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery1[System.Int32]' but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[DevAdmin.Models.Tasks]'."

The view looks like this

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<DevAdmin.Models.Tasks>>" %>    
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    <title>Index</title>
</asp:Content>    
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">    
    <h2>Tasks</h2>        
    <%= Html.ValidationSummary() %>
    <% using (Html.BeginForm()) {%>
        <fieldset>
            <legend>Filters</legend>           
            <p>
               <%= Html.DropDownList("StatusDropDown") %>
                <input type="submit" value="Filter" />
            </p>                    
        </fieldset>
    <% } %>            
    <table>
        <tr>
            <th></th>
            <th>
                TaskId
            </th>
            <th>
                Subject
            </th>
            <th>
                Description
            </th>
        </tr>    
    <% foreach (var item in Model) { %>        
        <tr>
            <td>
                <%= Html.ActionLink("Edit", "Edit", new {  id=item.TaskId }) %> |
                <%= Html.ActionLink("Details", "Details", new { id = item.TaskId })%>
            </td>
            <td>
                <%= Html.Encode(item.TaskId) %>
            </td>
            <td>
                <%= Html.Encode(item.Subject) %>
            </td>
            <td>
                <%= Html.Encode(item.Description) %>
            </td>
        </tr>        
    <% } %>    
    </table>    
    <p>
        <%= Html.ActionLink("Create New", "Create") %>
    </p>    
</asp:Content>

Any idea what I'm doing wrong?

+4  A: 

Well, it kinda says in the errormessage what you do wrong.

The view expects a IEnumerable1<Tasks> passed to it as Model, but you're passing a new { t, t.Projects}

Also, put some breathing room in your code..

replace

return View(*hard to read code here*);

with

int currentStatus = int.Parse(Request.Form["StatusDropDown"];
var tasks = db.Tasks.Where(t => t.ProjectId.Equals(currentStatus));
return View("Index", tasks.AsEnumerable());
Thomas Stock
A: 

The signature for the ActionResult expects

public ActionResult Index(FormCollection formValues)

Where FormCollection Iis an IEnumerable type. However, in your view you are posting back the selected index from the drop down which is an Int32:

<%= Html.DropDownList("StatusDropDown") %>
<input type="submit" value="Filter" />

You should change the ActionResult signature to accept an int.

aleemb
A: 

the form is posting the value attached to the drop down, change the method parameter from FormCollection to int[]

Rony
A: 

1) return View(db.Tasks); returns an IEnumerable

2) return View(from t in db.Tasks where t.Projects.ProjectId == int.Parse(Request.Form["StatusDropDown"]) new { t, t.Projects}); return an IQueryable.

So you have to options: Either change 1) into return View(db.Tasks).AsQueryable() and in your view change the type into IQueryable.

Or change 2) into return View(from t in db.Tasks where t.Projects.ProjectId == int.Parse(Request.Form["StatusDropDown"]) new { t, t.Projects}).AsEnumerable();

IEnumerable is for Linq to Object.
IQueryable is for Linq to SQL and other entitities.

Gidon