Self-AJAX-обновление частичного представления/контроллера в ASP.Net MVC и дублирующий div

У меня есть частичный вид в MVC, который выглядит примерно так:

<div id="comments">
    ...
</div>

Внутри этого div есть форма, которая вызывает контроллер с использованием AJAX и возвращает тот же частичный вид. Проблема в том, что результаты вызова представления заменяют содержимое div, а не всего div, и я получаю:

<div id="comments">
    <div id="comments">
        ...
    </div>
</div>

Единственное решение, о котором я могу думать с моей неделей опыта в ASP.Net MVC и AJAX, заключается в том, чтобы поместить div вне частичного представления и сделать частичное представление только внутренней частью, но тогда форма будет ссылаться на id вне представления, где находится форма, разбирая небольшую инкапсуляцию, которую я оставил там. Есть ли лучшее решение?

Ответ 1

В ненавязчивой библиотеке Ajax, которая поставляется с .NET MVC 3, используются обратные вызовы, основанные на четырех обратных вызовах из jQuery.ajax. Однако метод InsertionMode = InsertionMode.Replace из метода Ajax.BeginForm не приводит к вызову jQuery replaceWith. Вместо этого .html(data) используется для замены содержимого целевого элемента (а не самого элемента).

Я описал решение этой проблемы в своем блоге: http://buildingwebapps.blogspot.com/2011/11/jquerys-replacewith-and-using-it-to.html

Ответ 2

Используете ли вы AjaxHelper.Form или jQuery. Если вы используете jQuery, попробовали ли вы использовать replaceWith()? Используя AjaxHelper, вы используете AjaxOptions { InsertionMode = InsertionMode.Replace }? Я бы подумал, что используя либо вы могли бы заменить весь DIV на результаты частичного просмотра.

Ответ 3

Используя

AjaxOptions { UpdateTargetId = "myDiv", InsertionMode = InsertionMode.Replace } 

должно заменить все содержимое элемента '#myDiv', как говорит tvanfosson. Ваша проблема в том, где находится "#myDiv". Вот пример:

<div id="myDiv">
    <% Html.RenderPartial("MyPartialView"); %>
</div>

где MyPartialView:

<div id="comments">
    <% using (Ajax.BeginForm(new AjaxOptions() { UpdateTargetId = "myDiv", InsertionMode = InsertionMode.Replace } )) {%>        
    ...
    <input type="submit" value="Submit comment" />
    <% } %>
</div>

Если вы включаете div '#myDiv' внутри частичного представления, он будет отображаться сразу после получения ответа (вместе с его содержимым), а затем его содержимое будет заменено на ответ, который является одним и тем же частичным видом (включая его собственный '#myDiv' div), и поэтому вы всегда получаете 2 вложенных div.

Вы всегда должны использовать контейнер для частичных представлений, а затем установить UpdateTargetId в идентификатор контейнера.

Изменить: Я обновил код, чтобы представить точную ситуацию, которую вы описываете в своем вопросе.

Ответ 4

У меня была такая же проблема в Asp.Net MVC 5.

Я не хотел, чтобы PartialView обладал некоторыми знаниями о том, какой div он может содержаться внутри, поэтому я не принимал эту работу.

Затем я заметил другие ответы, относящиеся к ReplaceWith, и нашел простое решение:

InsertionMode = InsertionMode.ReplaceWith

Теперь частичный вид mvc может полностью заменить себя помощниками ajax без каких-либо зависимостей от имен вне себя.

Ответ 5

Также следует попробовать с jQuery (из моего ответа на MS MVC формы AJAXifying методы):

<script type="text/javascript">
    $(document).ready(function() {
        ajaxify($('div#comments'));
    });

    function ajaxify(divWithForm) {
        var form = $('form', divWithForm);
        $(':submit', form).click(function (event) {
            event.preventDefault();
            $.post(form.attr('action'), form.serialize(),
                function(data, status) {
                    if(status == 'success') {
                        var newDivWithForm = $(data);
                        ajaxify(newDivWithForm);
                        divWithForm.after(newDivWithForm).remove();
                    }
                }
            );
        });
    }
</script>