Подтвердить что ты не робот

Возврат частичного просмотра и JSON из ASP.NET MVC Action

Я представляю KnockoutJS в существующее приложение. Мой план состоит в том, чтобы изменить/использовать существующие частичные представления, которые мы уже создали, и связать их с моделями просмотра JS с декларативными атрибутами нокаута. Когда я делаю вызов AJAX для действия, в идеале я хотел бы, чтобы действие возвращало как HTML частичный вид, так и объект JSON. Затем я могу заполнить div HTML, преобразовать JSON в объект Knockout и связать его с HTML. Но я не могу понять, как вернуть оба из действия.

Мне нужна модель полного представления, потому что я буду ее обновлять и, в конечном итоге, отправлять обратно на сервер.

Я думал о том, что действие возвращает частичный вид (уже привязанный к модели), а в частичном представлении включает javascript для преобразования .Net-модели в объект Knockout. Но я чувствую, что рассеяние JS вокруг, как будто это беспорядочно и неподвластно. Я бы предпочел, чтобы все было близко к исходному вызову ajax.

Я предполагаю, что другой вариант состоит в том, чтобы сделать два вызова действий. Один для JSON, а другой для частичного просмотра. Но должен быть скользкий способ.

Любые идеи о том, как лучше всего это сделать?

4b9b3361

Ответ 1

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

Это сохраняет обязанности каждого объекта. Представления все еще расположены с использованием механизма просмотра, и их можно использовать повторно. Контроллер мало знает о представлении помимо имени и типа модели.

Ручное рендеринг

public static class RenderHelper
{
    public static string PartialView( Controller controller, string viewName, object model )
    {
        controller.ViewData.Model = model;

        using( var sw = new StringWriter() )
        {
            var viewResult = ViewEngines.Engines.FindPartialView( controller.ControllerContext, viewName );
            var viewContext = new ViewContext( controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw );

            viewResult.View.Render( viewContext, sw );
            viewResult.ViewEngine.ReleaseView( controller.ControllerContext, viewResult.View );

            return sw.ToString();
        }
    }
}

В вашем методе действий:

object model = null; // whatever you want
var obj = new { 
    someOtherProperty = "hello", 
    view = RenderHelper.PartialView( this, "_PartialName", model ) 
};

return Json( obj );

Обратите внимание, что я возвращаю анонимный тип. Вы можете вернуть любой (сериализуемый) тип, который вы хотите, до тех пор, пока он имеет свойство string для визуализированного представления.

Тестирование

Тестирование действия, использующего ручной рендеринг, требует небольшой модификации. Это связано с тем, что представление было немного раньше, чем это было бы показано в конвейере MVC.

Ручное рендеринг

  • Введите метод действий
  • Render view явно < - это затруднит проверку вызывающего действия
  • Метод действия выхода

Автоматическое рендеринг

  • Введите метод действий
  • Создать результат просмотра
  • Метод действия выхода
  • Результат просмотра процесса (таким образом, отображение представления)

Другими словами, процесс ручного рендеринга запускает множество других операций, которые затрудняют тестирование (например, взаимодействие с менеджером сборки для компиляции представления).

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

    public static string PartialView( Controller controller, string viewName, object model )
    {
        // returns false from a VS 2013 unit test, true from IIS
        if( !HostingEnvironment.IsHosted )
        {
            // return whatever you want here
            return string.Empty;
        }

        // continue as usual
     }

Проверка HostingEnvironment.IsHosted является недорогой (под капотом это просто нулевая проверка).

Ответ 2

Вы можете создать скрытый <input> для частичного со значением, установленным в строку JSON в ViewModel. Затем перед рендерингом частичного представления возьмите значение JSON из этого поля и проанализируйте его. Затем удалите его из частичного представления, вставьте его в свою страницу и сделайте ko.applyBindingsToDescendants(viewModel, $("#parentElement")[0])

Я не совсем уверен, как я отношусь к этому подходу, и это просто теория. Я не проверял это, но я подозреваю, что это сработает. Одна из загрузочная ловушка, на которую вы должны обратить внимание, - это браузер, который пытается кэшировать ваш запрос GET. В запросе ajax, который вы хотите сделать:

$.ajax({
  url: "/",
  type: 'GET',
  cache: 'false'
});

Или просто выполните запрос $.post. (ссылка)

Итак, один вариант.