Send only object from the list that has changed to the controller

Asked

Viewed 682 times

4

I own a view who lists all my customers. Each customer has 3 checkbox where the user selects them, and sends them to the controller - through the button (Submit) - the data to change. The method is working perfectly. However, when sending, it sends all customers, even those that have not changed. Thus it updates all (even those that have not been modified). This does not cause me problems, but causes a delay (since he has to go through the entire list to change).

I would like to know if there is a way to check if the client has been modified, and send only those who have been to my controller.

My View is that way:

@using PrestacaoWeb.UI.Helpers
@model List<PrestacaoWeb.Application.ViewModels.ClientePrestacaoViewModel>

@using (Html.BeginForm("EditarMes", "Cliente", FormMethod.Post))
{
    <input type="submit" value="Salvar"/>

<table>
    <thead>
        <tr>
        <th> Cliente </th>
        <th> 1 </th>
        <th> 2 </th>
        <th> 3 </th>
        <th> Cidade </th>
        <th> Responsável </th>
        <th> Obs </th>
        </tr>
    </thead>
        <tbody>
        @for (int i = 0; i < Model.Count(); i++)
        {
            <tr>
                @Html.HiddenFor(model => model[i].ClienteId)
                <td style="width: 100px">
                    <p align="center">@Model[i].NomeCliente</p>
                </td>
                <td style="width: 20px"><p align="center"> <b>@Html.CheckBoxFor(model => Model[i].EnvioPrestacao.bJaneiro)</b> </p> </td>

                <td style="width: 20px"><p align="center"> <b>@Html.CheckBoxFor(model => Model[i].EnvioPrestacao.bFevereiro)</b> </p> </td>

                <td style="width: 20px"><p align="center"> <b>@Html.CheckBoxFor(model => Model[i].EnvioPrestacao.bMarco)</b> </p> </td>
                 <td>
                    @Model[i].Cliente.Cidade.Nome
                </td>

                <td style="width: 100px">
                    <p align="center">@Model[i].Responsavel</p>
                </td>
                    <td style="width: 210px">
                        <p align="center">@Model[i].Observacao.</p>
                    </td>

            </tr>

        }
        </tbody>
</table>
}

By clicking the button Save, it sends all objects from the list to the method Editarmes, in my Controller.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditarMes(IList<ClientePrestacaoViewModel> prestacaoViewModel)
{
    if (!ModelState.IsValid) return View("Index");
    foreach (var item in prestacaoViewModel.Where(item => item != null))
    {
        _clienteContext.Atualizar(item);
        TempData["MensagemSuccess"] = "Cliente alterado com sucesso!";

    }
    return Redirect(ControllerContext.HttpContext.Request.UrlReferrer.ToString());
}

If I change all clients, you’re right, it will take a while. Now, if I change only one customer, and it sends 30 to controller, it wouldn’t be "nice" to wait for this.

  • 1

    You could implement a custom Model Binder (Imodelbinder implementation) that would make Binding only the modified elements. This would not make the post smaller but would dispense with foreach within the controller.

  • @rcompanhoni You would have some example of any implementation?

1 answer

4


It is cheaper in processing cost to bring the original list and compare the values.

Apparently you use a repository, so I don’t know how it’s done, but using an Entity Framework context would be something like this:

var listaOriginal = contexto.ClientePrestacoes.AsNoTracking().Where(/* Condição */).ToList();

foreach (var item in prestacaoViewModel.Where(item => item != null))
{
    var itemOriginal = listaOriginal.Single(l => l.Id == item.Id);
    if (item.bJaneiro != itemOriginal.bJaneiro || item.bFevereiro != itemOriginal.bFevereiro || item.bMarco != itemOriginal.bMarco) {
        _clienteContext.Atualizar(item);
    }

    TempData["MensagemSuccess"] = "Cliente alterado com sucesso!";
}

Taking advantage, this is not good practice:

if (!ModelState.IsValid) return View("Index");

In this command, you stop implementing the default behavior of MVC, which is to return the same screen in case of invalidity of some information on screen, and do not load any data that serves to fill the screen.

  • You happen to know some way to select only some of the items from the collection to be sent to the OP Action, I think this would be a good alternative and it would be less costly in terms of processing to the server.

  • @Zignd Actually "select" which data goes to the Controller in the POST doesn’t make much sense. Either the die was written on the screen, or it wasn’t. Anyway, the Controller need to check all records to understand what was changed and what was not.

  • @Ciganomorrisonmendez I thought it would be more "Costly", because I have to fetch the data and compare. But as it is not, I will make the changes. Thanks for the help.

  • Haa... About the return, is that I’m working with a window Modal, then I return to the View previous.

Browser other questions tagged

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