MVC Asp.net paging

Asked

Viewed 9,076 times

17

Currently I work with the data like this:

Context returns to me all Bank Customers

    public IEnumerable<Clientes> ListarTodos()
    {
        return contexto.Clientes.ToList();
    }

In the controller I call the Listings()

    public PartialViewResult Index()
    {
        var clientes = bdCliente.ListarTodos();
        return PartialView(clientes);
    }

And then I display in View and with Jquery mount the pagination by adding a search field that does the search on top of the already mounted table. The Jquery search process is extremely fast as it already has all the data in the table. But the time to assemble the table the first time is somewhat time consuming.

To make paging more efficient, should I use paging in context, or in the controller, or even in the View otherwise (I believe that is not the most efficient way)? And what the controller/context would look like using paging.

  • If you can do it in Controller !!! that’s the question, or you want example of how to do it... In the view is not indicated because of performance

  • But the slowness is not in context? Isn’t it a slow process I bring from the bank all, and then filter through the controller? The correct thing would not be for me to bring already filtered by the bank.

  • So @Diegozanardo, really, so I asked you if you want an example, because the way you did giving a Tolist there iron the performance issue has to be otherwise so you just bring what you need and mount the pagination. Your question did not ask for example, just clarification!!!

  • If you could give me an example it would be good. I edited the question!

  • you will have to suit your model!

  • The performance will depend on your needs. For example bank paging may be more performative but will give you more work to sort/filter because in this case you would have to make a call to the BD whenever the user navigates the pages, reorder or filter. Paging in the controller is a middle ground and the worst performance "usually" is paging in the view but hence neither a call to the controller you need when browsing, sorting, filtering

Show 1 more comment

2 answers

18


Download by the Nuget o Pagedlist (Pagelist and Pagedlist.Mvc)

inserir a descrição da imagem aqui

After installation do the following:

Change this method to IQueryable and take out the ToList()

Method

public IQueryable<Clientes> ListarTodos()
{
    return contexto.Clientes;
}

No Controller:

using PagedList;
public PartialViewResult Index(int? page, String filtro)
{
        IQueryable<Clientes> clientes = bdCliente.ListarTodos();
        IPagedList<Clientes> model = !string.IsNullOrEmpty(filtro) ?
            clientes.Where(x => x.Nome.Contains(filtro)).OrderBy(x => x.Nome).ToPagedList(page ?? 1, 10) :
            clientes.OrderBy(x => x.Nome).ToPagedList(page ?? 1, 10);
        return PartialView(model);
}

Note: Orderby is mandatory when using Topagedlist.

Na View

@using PagedList;
@using PagedList.Mvc;
@model IPagedList<Clientes>
@{ Layout = "~/Views/Shared/_LayoutPageAdm.cshtml"; }
<nav class="navbar navbar-default" role="navigation">
    <div class="navbar-header">
        <a class="navbar-brand" href="#">Configurações</a>
    </div>
    <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
            <input name="filtro" value="@ViewBag.Filtro" id="filtro" type="text" class="form-control input-sm" placeholder="Digite a descrição...">
        </div>
        <button type="submit" class="btn btn-default">Filtro</button>        
    </form>
</nav>
<table class="table table-hover table-condensed">
    <tr>
        <th style="width: 75%">
            @Html.Raw("Nome Completo")
        </th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Nome)
            </td>            
        </tr>
    }
</table>
@if (Model.HasNextPage || Model.HasPreviousPage)
{
    <div style="text-align: center">
        @Html.PagedListPager(Model, (page) => Url.Action("Index", new { page = page, filtro = @ViewBag.filtro }), PagedListRenderOptions.Classic)
    </div>
}
  • But this method is performatic?

  • Yes, because it calculates what is going to be sent on the screen, and only brings what it needs, and assembles pagination with record calculation. @user3218869. The way he’s doing it there yes the performance is low. So improve and much the information traffic.

  • +1 Good! Only one note: @Html.Raw("Nome Completo") is completely unnecessary. You can write the column name in HTML in the hand without any problem.

11

Just for the record, as an alternative for those who want to learn how to do it in the hand, in a simple way (not that the PagedList not be, just does not reveal what it does behind the scenes), just create a method that accepts the current page and the amount of items per page and use the methods Skip() and Take() of the Ligurian:

public IEnumerable<Clientes> ListarPagina(int paginaAtual, int itensPorPagina)
{
    return contexto.Clientes.Skip((paginaAtual - 1) * itensPorPagina).Take(itensPorPagina).ToList();
}

If you want to assemble the pagination links and have a ViewModel specific to what you need to work with, you can modify the case a little and create a generic template for your paged lists, which accepts the total records, the current page, the amount of items per page and the collection of items:

public class ListaPaginada<T>
{
    public int TotalItens { get; private set; }
    public int ItensPorPagina { get; private set; }
    public int PaginaAtual { get; private set; }

    public int TotalPaginas
    {
        get { return Math.Ceiling(TotalItens / ItensPorPagina); }
    }

    public List<T> Itens { get; private set; }

    public ListaPaginada(List<T> itens, int totalItens, int itensPorPagina, int paginaAtual)
    {
        this.Itens = itens;
        this.TotalItens = totalItens;
        this.ItensPorPagina = itensPorPagina;
        this.PaginaAtual = paginaAtual;
    }
}



public ListaPaginada<Clientes> ListarPagina(int paginaAtual, int itensPorPagina)
{
    var clientes = contexto.Clientes;
    var totalClientes = clientes.Count();
    var clientesDaPagina = clientes.Skip((paginaAtual - 1) * itensPorPagina).Take(itensPorPagina).ToList();

    return new ListaPaginada<Clientes> (clientesDaPagina, totalClientes, itensPorPagina, paginaAtual);
}

In your view, you will have a single object with the properties to make the loops and generate the pagination and list as you wish:

@model ListaPaginada<Clientes>

if (Model.TotalItens > 0)
{
    foreach(var item in Model.Itens)
    {
        <li>@item.Nome</li>
    }

    if (Model.TotalPaginas > 1)
    {
        <div class="paginacao">
            @for(var i = 1; i < Model.TotalPaginas; i++)
            {
                Url.Action("Index", new { pagina = i })
            }
        </div>
    }
}
else
{
    <p>Nenhum item disponível no momento!</p>
}

I do not recommend replacing the component, I just present a way to do the same in a personalized way, with good performance and, probably what the component does behind the scenes, without the unnecessary additions.

  • friend, could you help me make this idea, see if you can help me: http://answall.com/questions/101913/d%C3%Bavida-com-pagina%C3%A7%C3%A3o-em-Asp-net? noredirect=1#comment208104_101913

  • Excuse me. I believe there was a typo in the method Math.Ceil. In fact it is Math.Ceiling. Corrected in the example.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.