Tommy Cawley
Tommy Cawley

Reputation: 185

How Do I Use A Tuple Properly in ASP.NET MVC 4

I'm trying to use two models in one view using a tuple but I'm getting this error: Server Error in '/' Application.

The model item passed into the dictionary is of type 'PagedList.PagedList1[S00117372CA3.Product]', but this dictionary requires a model item of type 'System.Tuple2[PagedList.IPagedList1[S00117372CA3.Product],System.Collections.Generic.IEnumerable1[S00117372CA3.Order]]'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'PagedList.PagedList1[S00117372CA3.Product]', but this dictionary requires a model item of type 'System.Tuple2[PagedList.IPagedList1[S00117372CA3.Product],System.Collections.Generic.IEnumerable1[S00117372CA3.Order]]'.

Here is my code:

    @*@model PagedList.IPagedList<S00117372CA3.Product>*@
@model Tuple<PagedList.IPagedList<S00117372CA3.Product>, IEnumerable<S00117372CA3.Order>>
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].ProductName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].Supplier.CompanyName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].Category.CategoryName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].QuantityPerUnit)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].UnitPrice)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].UnitsInStock)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].UnitsOnOrder)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].ReorderLevel)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Item1[0].Discontinued)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model.Item1) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ProductName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Supplier.CompanyName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Category.CategoryName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.QuantityPerUnit)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UnitPrice)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UnitsInStock)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UnitsOnOrder)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ReorderLevel)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Discontinued)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProductID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ProductID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProductID })
        </td>
    </tr>
}

</table>

<div>
    Page @(Model.Item1.PageCount < Model.Item1.PageNumber ? 0 : Model.Item1.PageNumber) of @Model.Item1.PageCount
    @if (Model.Item1.HasPreviousPage)
    {
        @Html.ActionLink("<<", "Index", new { page = 1})
        @Html.Raw(" ");
        @Html.ActionLink("< Prev", "Index", new {page = Model.Item1.PageNumber - 1})
    }
    else{
     @:<<
     @Html.Raw(" ");
        @:< Prev   
    }

    @if (Model.Item1.HasNextPage)
    {
        @Html.ActionLink("Next >", "Index", new {page = Model.Item1.PageNumber + 1})
        @Html.Raw(" "); 
        @Html.ActionLink(">>", "Index", new {page = Model.Item1.PageCount})
    }
    else{
     @:Next >
     @Html.Raw(" ")
@:>>   
    }
</div>

@foreach (var item in Model.Item2)
{
    @Html.Partial("_Orders")
}

Here is my controller code as requested:

var q = (from o in db.Order_Details
                     where o.ProductID == id
                     join ord in db.Orders
                     on o.OrderID equals ord.OrderID
                     orderby o.Quantity descending
                     select ord);
            var qm = q.Take(3);
            return PartialView("_Orders", qm.ToList());

Upvotes: 3

Views: 10374

Answers (1)

John H
John H

Reputation: 14655

Essentially, you're just trying to pass multiple models to your view. As you can only pass one type to a view, the way to do what you want is to wrap your models in a view model and pass that to your view instead. Something like:

public class ProductViewModel
{
    public IPagedList<Product> Products { get; set; }
    public IEnumerable<Order> Orders { get; set; }
}

public ActionResult Index()
{
    var model = new ProductViewModel();
    model.Products = // ... fetch from database
    model.Orders = // ... fetch from database

    return View(model);
}

The view can now be strongly-typed to the view model:

@model ProductViewModel

Upvotes: 7

Related Questions