Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Не обновлялись данные после публикации (mvc razor)

Автор вопроса: Maxim PolishchukОтветов: 2

Я использую "Composite C1" cms, mvc и движок razor view. На некоторых страницах должны отображаться элементы списка, и пользователь может фильтровать данные по некоторым критериям. Первая часть работает нормально (элементы отображаются без проблем), у меня проблема со второй частью - отфильтрованные данные не обновляются, на странице отображаются старые данные.

У меня ItemsController:

public class ItemsController : Controller
{
    [OutputCache(CacheProfile = "ZeroCacheProfile")]
    public ActionResult Filter()
    {
        // Initialize all filter comboboxes for Items page
        // ...
        return View(new MyModel());
    }

    [OutputCache(CacheProfile = "ZeroCacheProfile")]
    public ActionResult List()
    {
        // Set first default items
        ViewBag.Items = (IEnumerable)GetRandomItems(8);

        return View(new MyModel());
    }

    [HttpPost]
    [ValidateInput(true)]
    [OutputCache(CacheProfile = "ZeroCacheProfile")]
    public ActionResult List(MyModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        // Set filtered items
        // ...
        ViewBag.Items = (IEnumerable)itemList;

        return Json(new { Success = true, Filter = filter, ItemNumber = itemList.Count }, JsonRequestBehavior.AllowGet);
    }
}

И у меня есть два представления: "List.cshtml" - для отображения данных и "Filter.cshtml" - для создания критериев для фильтрации данных.

В представлении "Фильтр" есть сценарий, который запрашивает / Items / List, - для фильтрации и обновления данных.

<script type="text/javascript" language="javascript">
/* <![CDATA[ */
    $(document).ready(function () {
        $("#search_button_filter").bind('click', function() {
            var $form = $("#filter_form");
            $.ajax({
                url: '/Items/List/default.aspx',
                type: 'POST',
                data: $form.serialize(),
                success: function (data) {
                    if (data.Success) {
                        // Show report: amount of filtered items, etc.
                        // ...
                    }
                }
            });
            return false;
        });
    });
/* ]]> */
</script>

Я проверил - "ActionResult List (MyModel model)" установил правильные отфильтрованные данные в следующей строке кода.

ViewBag.Items = (IEnumerable)itemList;

Но в представлении "Список" по-прежнему отображаются предыдущие данные.

Наверное, кто-нибудь подскажет способ решения моей проблемы.

Спасибо.

Новое обновление

Я переделал свое решение, и теперь оно работает. Те же два представления "Список" и "Фильтр" на моей странице, но без каких-либо Rest / Post, только Get и QueryString:

<script type="text/javascript" language="javascript">
/* <![CDATA[ */
    $(document).ready(function () {
        $("#search_button_filter").bind("click", function() {
            var $filter1 = $("#filter1_search_filter").val();
            var $filter2 = $("#filter2_search_filter").val();
            var $filter3 = $("#filter3_search_filter").val();
            window.location.href = "@UrlUtil.ItemsPageUrl" + "?&filter1=" + $filter1 + "&filter2=" + $filter2 + "&filter3=" + $filter3;
        });
    });
/* ]]> */
</script>

Но сейчас у меня очень маленькая проблема. Количество элементов рассчитывается в методе "ActionResult List ()" (который инициализирует представление "Список"), но мне нужно отобразить это значение в представлении "Фильтр". Пробовал использовать коллекцию TempData - установил

[OutputCache(CacheProfile = "ZeroCacheProfile")]
public ActionResult List()
{
    TempData["AmountOfFilteredItems"] = null;

    Guid filter1;
    if (!Guid.TryParse(Request.QueryString["filter1"], out filter1))
    {
        filter1 = Guid.Empty;
    }

    Guid filter2;
    if (!Guid.TryParse(Request.QueryString["filter2"], out filter2))
    {
        filter2 = Guid.Empty;
    }

    Guid filter3;
    if (!Guid.TryParse(Request.QueryString["filter3"], out filter3))
    {
        filter3 = Guid.Empty;
    }

    List<MyModel> items;
    if ((filter1 == Guid.Empty) && (filter2 == Guid.Empty) && (filter3 == Guid.Empty))
    {
        items = GetRandomItems(8);
    }
    else
    {
        items = GetFilteredItems(filter1, filter2, filter3);
    }

    TempData["AmountOfFilteredItems"] = items.Count;

    return View(items);
}

значение в методе ActionResult List () контроллера Items и вернуть это значение в представлении Filter:

@model MyModel
@using (Html.BeginForm("Items", "Filter", FormMethod.Post, new { @id = "filter_form" }))
{
    <!-- Fill required data -->
    <!-- ... -->
    <font class="bold">@(TempData["AmountOfFilteredItems"].NotNull() ? TempData["AmountOfFilteredItems"] : 0)</font>
}

Только одна проблема: это значение всегда задерживается на один шаг / итерацию - если реальное количество элементов равно "2", тогда в представлении отображается предыдущее значение "8". И в следующий раз, когда действительное число будет "0", отобразится предыдущее действительное значение "2".

Как я могу это решить?

  • Что вы имеете в виду, говоря, что в представлении списка продолжают отображаться предыдущие данные? Вы имеете в виду после запроса ajax или если вы вернетесь в / Items / List? Danny Tuppeny 01.05.2011
  • Вы не включили код внутри if (data.Success), который выглядит важной частью, поскольку именно туда возвращаются данные? Danny Tuppeny 01.05.2011
  • Привет, я подумал, что когда я устанавливал новые (отфильтрованные) элементы в хранилище ViewBag.Items (в методе "ActionResult List (MyModel model)" во время "публикации"), то представление "Список" (которое использует это хранилище для инициализации) будет обновляться автоматически - представление "Список" будет связывать новые данные и отображать их ... Я не хотел бы связывать его внутри клиентской части if (data.Success) вручную, было бы лучше найти способ сделать это на сервере боковая сторона. Maxim Polishchuk 02.05.2011
  • Я забыл добавить, что эти два представления "Фильтр" и "Список" находятся на одной странице. Maxim Polishchuk 02.05.2011
  • Можете ли вы опубликовать полный код действия, включающего получение данных и установку переменной TempData? Danny Tuppeny 02.05.2011
  • См. Мой ответ re: TempData vs ViewData, посмотрите, решит ли это проблему Danny Tuppeny 02.05.2011

razor

Ответы

Ответ 1 · рейтинг 2 · Danny Tuppeny

HTML-код в браузере не будет обновляться, пока вы его не обновите. Код в браузере не связан с тем, что происходит на сервере. Если вы используете Ajax для отправки запроса на сервер, вам необходимо обработать ответ и что-то с ним сделать.

Если вы хотите использовать Ajax, вам необходимо убедиться, что ваш метод List (MyModel) возвращает частичное представление, а затем перезаписывает им раздел вашей DOM.

Однако проще всего удалить Ajax и обработать его как обычную обратную передачу страницы - это будет намного проще. Это немного устарело, но здесь есть некоторая информация о сообщениях формы в MVC:

http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx

Ответ 2 · Danny Tuppeny

Я только что прочитал, что цель TempData - предоставить данные для "следующего" запроса, поэтому мне интересно, видит ли "текущий" запрос только TempData из "предыдущего" запроса, следовательно, он не соответствует требованиям.

Попробуйте вместо этого перейти на ViewBag и посмотрите, решит ли это проблему.

Например. в моем действии я добавил:

ViewBag.ItemCount = 10;

(Примечание: это динамический объект, поэтому вы можете создавать свойства по ходу).

Затем, чтобы отобразить это, я добавил это в свое представление:

Count: @ViewBag.ItemCount

Кажется, работает, как ожидалось.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы