Я не уверен, что "пенсии" в вашем коде, я предполагаю, что это ДИВ окружающий каждую форму, образованную петлю ? Если это так, ваша проблема следующая:
Во-первых, если ни один из элементов не связаны между собой (то есть, вызывая некоторое обновление на элементе вызывает еще один пункт для обновления, а), вы не должны тратить ресурсы чтобы отправить весь список обратно в браузер - подумайте о том, чтобы просто отправить обратно обновленное отображение затронутой «записи» и просто обновить соответствующий элемент с ответом.
Что вызывает вопросы, которые будут дублироваться: AjaxOptions
класса имеет свойство InsertionMode
, и я помню, его значение по умолчанию InsertionMode = InsertionMode.InsertAfter
, что приводит к дубликатам появляться. Зачем? Вы отправляете на сервер запрос Ajax, который отправляет обратно фрагмент HTML, заполненный всем списком, вместо одного элемента, тогда браузер добавляет этот фрагмент к существующим записям.
Решение
Если вы переделать свой проект просто отправить обратно одну запись, а не все из них, просто добавьте однозначно идентифицирован (= имеет уникальный id
атрибут) <div>
элемент вокруг блока using(...)
, установите InsertionMode
на InsertionMode=InsertionMode.Replace
и установите UpdateTargetId
на id
этого <div>
, например:
<div id="[email protected]">
@using (Ajax.BeginForm("SaveItem", "Controller", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "record-" + i.ToString(), InsertionMode = InsertionMode.Replace }))
{
// ...
}
</div>
Это вызовет отклик Ajax заменить содержимого контейнера, с которого отправляется запрос (по содержания Я имею в виду, что сама упаковка элемент не будет заменен! Для этого вам нужно использовать InsertionMode.ReplaceWith
). Если вы допустили ошибку, вы в конечном итоге сбросили сумасшедшие количества вложенных элементов внутри контейнера-хоста, возможно, нарушив скрипты и/или стили, которые используют очень специфические селектора.
Если вы будете придерживаться отправок целой коллекции элементов обратно, а затем просто обернуть цикл с <div>
тегом, дать ему id
, установите InsertionMode
в InsertionMode=InsertionMode.Replace
и UpdateTargetId
собственности на id
этого <div>
.
--------- Обновление -----------
Чтобы ответить на ваш комментарий:
Предположим, у вас есть представление, которое - для ради простоты - отображает записи в табличном формате. Затем, результат выглядит следующим образом:
Name | Age | Salary | Hide
------------------------------------
Peter | 32 | $15k | Hide button
Eva | 28 | $12k | Hide button
Предположим, что вы изменить с просьбой Ajax является то, что всякий раз, когда вы скрываете запись, вы посылаете назад один строку таблицы с кнопкой, которая теперь отображает «шоу» вместо " hide 'и те же данные о человеке, который принадлежит кнопке, вызвавшей запрос. Затем, когда вы делаете запрос на прямой (= не Аякса, когда вы непосредственно перейти к странице), вы делаете это:
@model PeopleCollection
...
<table>
<thead>
<tr>
<td>Name</td>
<td>Age</td>
<td>Salary</td>
<td>Hide</td>
</tr>
</thead>
<tbody>
@foreach (Person record in Model) {
@Html.Partial("TableRow_Partial",record)
}
</tbody>
Вид «TableRow_Partial» выглядит следующим образом:
@model Person
@{
AjaxOptions opts = new AjaxOptions() {
UpdateTargetId = "person-row-" + Model.Id.ToString(),
InsertionMode = InsertionMode.ReplaceWith
// etc
};
}
...
<tr id="[email protected]">
<td>@Model.Name</td>
<td>@Model.Age</td>
<td>@Model.Salary</td>
<td>
<!-- configure the BeginForm(..) call with the action name and a routeValue anonymous object as "new { id = Model.Id}" -->
@using (Ajax.BeginForm(...)) {
<input type="submit" value="@(Model.IsHidden ? "Show" : "Hide")" />
}
</td>
</tr>
Это просто извлечет конструкцию петель в отдельный частичный вид. Процессия метода действия вашего Ajax-запрос будет просто возвращать эту точку зрения, наполненная одной записи, которую вы обновили, например, так:
public ActionResult UpdateRecord(Int64 id)
{
var _record = Repository.Get(id);
// logic to hide and update record
return PartialView("TableRow_Partial",_record);
}
Для этого, чтобы работать, вы должны установить InsertionMode
в InsertionMode.ReplaceWith
. Все, что вы делаете, заключается в том, что когда вы отправляете запрос ajax, чтобы сделать что-то только с одной записью, вы обновляете только один элемент - тот, который вызвал вызов ajax, а затем вы просто возвращаете новую строку (одну строку!) И заменяете старый один с этим новым.
Если вы действительно хотите, чтобы вся коллекция элементов возвращалась клиенту каждый раз, когда вы делаете что-то с записями, просто отправьте всю визуализированную таблицу клиенту и замените старую на новую в подобный способ.
Спасибо, но немного смущен возвратной моделью. Если я использую код из вашего решения, я могу передать одну модель контроллеру и обновить эту модель в базе данных, но по мере того, как контроллер вернет список элементов, этот список затем заменит одну строку в записи - @ i будет весь список, используемый для итерации цикла For, и все равно приведет к дублированию. «Пенсии» на самом деле являлись обертыванием всего частичного представления этого цикла. –
Richter84
Ответ обновлен. –