Home > Back-end >  MVC Core pass LINQ object to iPagedList
MVC Core pass LINQ object to iPagedList

Time:09-17

I am trying to pass a select new {} to a view using the following:

var results = 
    (from n in _context.Nodes
    join o in _context.Organizations on n.OrgId equals o.Id
    join t in _context.Organizations on n.ContractingOrgId equals t.Id

    select new
    {
        Id = n.Id,
        Name = n.Name,
        assigned_org = o.ShortName,
        con_org_short_name = t.ShortName,
        expiry = n.ExpireDate,
        lastActive = n.ActiveDate
    });
            
if (!String.IsNullOrEmpty(searchString))
{
    results = results.Where(s => s.con_org_short_name.Contains(searchString)
                            || s.Id.ToString().StartsWith(searchString));
}

switch (sortOrder)
{
    case "Client_desc":
        results = results.OrderByDescending(s => s.con_org_short_name);
        break;
    case "Client":
        results = results.OrderBy(s => s.con_org_short_name);
        break;
    case "Assigned":
        results = results.OrderBy(s => s.assigned_org);
        break;
    case "Assigned_desc":
        results = results.OrderByDescending(s => s.assigned_org);
        break;
    case "Expires":
        results = results.OrderBy(s => s.expiry);
        break;
    case "Expires_desc":
        results = results.OrderByDescending(s => s.expiry);
        break;
    case "LastActive":
        results = results.OrderBy(s => s.lastActive);
        break;
    case "LastActive_desc":
        results = results.OrderByDescending(s => s.lastActive);
        break;
    case "Id_desc":
        results = results.OrderByDescending(s => s.Id);
        break;
    default:
        results = results.OrderBy(s => s.Id);
        break;
};
int pageSize = 12;
int pageNumber = (page ?? 1);
return View(await results.ToPagedListAsync(pageNumber, pageSize));

This throws an error at return View()

"InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'X.PagedList.StaticPagedList1[<>f__AnonymousType26[System.Int32,System.String,System.String,System.String,System.Nullable1[System.DateTime],System.Nullable1[System.DateTime]]]', but this ViewDataDictionary instance requires a model item of type 'X.PagedList.IPagedList`1[AdminPortal.Models.Node]'.

And I get a build error on these lines:

if (!String.IsNullOrEmpty(searchString))
{
    results = results.Where(s => s.con_org_short_name.Contains(searchString)
                            || s.Id.ToString().StartsWith(searchString));
}

In the ienumerable visualiser on 'results' the object is shown in the first column as an anonymous type and it looks like an array but it has the expected output.

The question is, how to I access just that object and pass it to the return View() in the correct type?

This is the view to which the results are supposed to be passed:

@model X.PagedList.IPagedList<AdminPortal.Models.Node>
@using X.PagedList;
@using X.PagedList.Mvc.Core;
<link href="~/css/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewData["Title"] = "Index";
}

<div >
    <div >
        <h2 >Node List</h2>
    </div>
</div>

<div >
    <div  style="padding-bottom:10px">
        <div >
            @using (Html.BeginForm("Index", "Nodes", FormMethod.Get))
            {
               <p>
                    Find by name/id: @Html.TextBox("SearchString",ViewBag.CurrentFilter as string, htmlAttributes: new  {style="background-color:#cef2eb"})
                    <input type="submit" value="Search"  />
               </p>

                
            }
        </div>

        <div >
            <a asp-controller="Nodes" asp-action="Create" >
                <i ></i> &nbsp; Create Node
            </a>
        </div>
    </div>
    <table  width="100%" cellspacing="0">
    <thead>
            <tr style="color:#126E75; background-color:lightcyan">
            <th class=col-sm-1 style="text-align:left">
                @Html.ActionLink("ID", "Index", new { sortOrder = ViewBag.IDSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th class=col-sm-2 style ="text-align:left">
                Node Name
            </th>
            <th class=col-sm-1 style="text-align:left">
                Mode
            </th>
            <th class=col-sm-2 style ="text-align:left">
                @Html.ActionLink("Assigned To", "Index", new { sortOrder = ViewBag.AssignedSortParm, currentFilter=ViewBag.CurrentFilter })
             </th>
            <th class=col-sm-2 style ="text-align:left">
                @Html.ActionLink("Contracting Org", "Index", new { sortOrder = ViewBag.ClientSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th class=col-sm-1 style ="text-align:left">
                @Html.ActionLink("Expires", "Index", new { sortOrder = ViewBag.ExpiresSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th class=col-sm-1 style ="text-align:left">
                    @Html.ActionLink("LastActive", "Index", new { sortOrder = ViewBag.LastActiveSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th scope="col" colspan="2" style=" width:10%; text-align:center">
                Action
            </th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr >
            <td align="left">
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.IsStudy)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.Org.ShortName)
            </td>
            <td align ="left">
                @Html.DisplayFor(modelItem => item.ContractingOrg.ShortName)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.ExpireDate)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.ActiveDate)
            </td>
            <td style="text-align: center">
                <a asp-action="Edit" asp-route-id="@item.Id">
                    <i ></i>
                </a>
            </td>
            <td style="text-align: center">
                <a asp-action="Details" asp-route-id="@item.Id">
                    <i  style="color:blue"></i>
                </a>
            </td>
        </tr>
    }
    </tbody>
</table>
</div>
<div >
    Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount  @Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
</div>

CodePudding user response:

There is one solution for your problem.

View Model

NodeViewModel.CS

public class NodeViewModel
{
  public int Id {get;set;}
  public string Name {get;set;}
  public string assigned_org {get;set;}
  public string con_org_short_name {get;set;}
  public string expiry  {get;set;}
  public string lastActive  {get;set;}
}

Controller method:

var results = 
    (from n in _context.Nodes
    join o in _context.Organizations on n.OrgId equals o.Id
    join t in _context.Organizations on n.ContractingOrgId equals t.Id

    select new NodeViewModel
    {
        Id = n.Id,
        Name = n.Name,
        assigned_org = o.ShortName,
        con_org_short_name = t.ShortName,
        expiry = n.ExpireDate,
        lastActive = n.ActiveDate
    });
    if (!String.IsNullOrEmpty(searchString))
{
    results = results.Where(s => s.con_org_short_name.Contains(searchString)
                            || s.Id.ToString().StartsWith(searchString));
}

switch (sortOrder)
{
    case "Client_desc":
        results = results.OrderByDescending(s => s.con_org_short_name);
        break;
    case "Client":
        results = results.OrderBy(s => s.con_org_short_name);
        break;
    case "Assigned":
        results = results.OrderBy(s => s.assigned_org);
        break;
    case "Assigned_desc":
        results = results.OrderByDescending(s => s.assigned_org);
        break;
    case "Expires":
        results = results.OrderBy(s => s.expiry);
        break;
    case "Expires_desc":
        results = results.OrderByDescending(s => s.expiry);
        break;
    case "LastActive":
        results = results.OrderBy(s => s.lastActive);
        break;
    case "LastActive_desc":
        results = results.OrderByDescending(s => s.lastActive);
        break;
    case "Id_desc":
        results = results.OrderByDescending(s => s.Id);
        break;
    default:
        results = results.OrderBy(s => s.Id);
        break;
};
int pageSize = 12;
int pageNumber = (page ?? 1);
return View(await results.ToPagedListAsync(pageNumber, pageSize));

View

@model X.PagedList.IPagedList<NodeViewModel>
@using X.PagedList;
@using X.PagedList.Mvc.Core;
<link href="~/css/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewData["Title"] = "Index";
}

<div >
    <div >
        <h2 >Node List</h2>
    </div>
</div>

<div >
    <div  style="padding-bottom:10px">
        <div >
            @using (Html.BeginForm("Index", "Nodes", FormMethod.Get))
            {
               <p>
                    Find by name/id: @Html.TextBox("SearchString",ViewBag.CurrentFilter as string, htmlAttributes: new  {style="background-color:#cef2eb"})
                    <input type="submit" value="Search"  />
               </p>

                
            }
        </div>

        <div >
            <a asp-controller="Nodes" asp-action="Create" >
                <i ></i> &nbsp; Create Node
            </a>
        </div>
    </div>
    <table  width="100%" cellspacing="0">
    <thead>
            <tr style="color:#126E75; background-color:lightcyan">
            <th class=col-sm-1 style="text-align:left">
                @Html.ActionLink("ID", "Index", new { sortOrder = ViewBag.IDSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th class=col-sm-2 style ="text-align:left">
                Node Name
            </th>
            <th class=col-sm-1 style="text-align:left">
                Mode
            </th>
            <th class=col-sm-2 style ="text-align:left">
                @Html.ActionLink("Assigned To", "Index", new { sortOrder = ViewBag.AssignedSortParm, currentFilter=ViewBag.CurrentFilter })
             </th>
            <th class=col-sm-2 style ="text-align:left">
                @Html.ActionLink("Contracting Org", "Index", new { sortOrder = ViewBag.ClientSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th class=col-sm-1 style ="text-align:left">
                @Html.ActionLink("Expires", "Index", new { sortOrder = ViewBag.ExpiresSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th class=col-sm-1 style ="text-align:left">
                    @Html.ActionLink("LastActive", "Index", new { sortOrder = ViewBag.LastActiveSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th scope="col" colspan="2" style=" width:10%; text-align:center">
                Action
            </th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr >
            <td align="left">
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.IsStudy)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.Org.ShortName)
            </td>
            <td align ="left">
                @Html.DisplayFor(modelItem => item.ContractingOrg.ShortName)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.ExpireDate)
            </td>
            <td align="left">
                @Html.DisplayFor(modelItem => item.ActiveDate)
            </td>
            <td style="text-align: center">
                <a asp-action="Edit" asp-route-id="@item.Id">
                    <i ></i>
                </a>
            </td>
            <td style="text-align: center">
                <a asp-action="Details" asp-route-id="@item.Id">
                    <i  style="color:blue"></i>
                </a>
            </td>
        </tr>
    }
    </tbody>
</table>
</div>
<div >
    Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount  @Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
</div>

after making all above changes your view will be working like charm

  • Related