ASP.NET MVC - объединение результатов Json с ViewResult

Могу ли я вернуть результат Json, который также содержит визуализированный вид?

Мне нужно, чтобы он возвращал новый идентификатор отправленной формы вместе с ее HTML и некоторыми другими свойствами.

Также это может быть полезно, когда мне нужно вернуть два (или более) результата просмотра одного действия внутри объекта Json.

Спасибо!

4 ответа

Решение

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

Вы можете увидеть это в этом посте: http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/.

Я создал расширение, чтобы сделать его проще:

public static class MvcHelpers
{
    public static string RenderPartialView(this Controller controller, string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = controller.ControllerContext.RouteData.GetRequiredString("action");

        controller.ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            ViewEngineResult 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);

            return sw.GetStringBuilder().ToString();
        }
    }
}

В моем контроллере я называю это следующим образом:

const string msg = "Item succesfully updated!";
return new JsonResult
           {
               Data = new
                          {
                              success = true, 
                              message = msg,
                              view = this.RenderPartialView("ProductItemForm", model)
                          },
               JsonRequestBehavior = JsonRequestBehavior.AllowGet
           };

Где "this" - это контроллер в данном случае, "ProductItemForm" - это мой взгляд, а "model" - мой объект productItem:)

Надеюсь это поможет;)

Я долго думал об этой проблеме. Мое решение похоже на возврат частичного представления HTML в виде строки JSON, но наоборот. Вернуть частичное представление со встроенным JSON. Мне не нравился этот подход, пока jQuery 1.4.3 не объединил их метод.data() с атрибутом данных HTML 5. Это значительно упрощает генерацию JSON в представлении ASP.NET MVC и чтение его через jQuery.

Посмотрите пример... Это не идеально, но мне нравится это гораздо лучше, чем создавать скрытые входные данные или помощники, которые отображают частичное представление перед его возвратом.

Частичный вид:

<div id="content">
  <h1>Some Title</h1>
  <p>Ipsum Lorem</p>
</div>
<div id="dataDiv" data-stuff='{ "name": "Jason", "color": "Blue"}'></div>

JavaScript, который читает JSON

$(document).ready(function () {
  var name = $('#dataDiv').data('stuff').name;
  var color = $('#dataDiv').data('stuff').color;
  alert(name + ' ' + color);
});

Может показаться, что это идет вразрез с "принципом единой ответственности" (если вы применяете его к представлениям). Однако, если ваше приложение требует, чтобы обе части данных передавались в ответе, я не вижу в этом ничего плохого. И пока ваша модель построена правильно, она не будет противоречить каким-либо принципам проектирования.

В первом случае, я думаю, вы можете просто вернуть HTML, но вставить данные в возвращенную форму. Используйте jQuery для доступа к данным в вашем обратном вызове.

$.ajax({
    url: '<%= Url.Action( "MyAction" )',
    dataType: 'html',
    data: $('form').serialize(),
    success: function(data) {
                $('form').html(data);
                var id = $('form').find('input#formId[type=hidden]').val();
             }
});

Во втором случае общий вид, который принимает два или более ViewNames и использует RenderPartial, вероятно, является лучшим решением, возвращающим HTML через JSON.

Multiview.aspx

 ...
<% foreach (string viewName in Model.Views)
   {
       Html.RenderPartial( viewName );
   }
%>

Тогда в ваших действиях:

public ActionResult MyAction(...)
{
     ... set up model with data
     model.Views = new List<string> { "View1", "View2" };

     return View( "Multiview", model );
}

Это может быть немного хакерски (и я пишу о своей голове), но вы можете создать свой собственный подкласс ActionResult, а также реализовать ResultFilter, который будет перехватывать эти конкретные типы ActionResult и отображать соответствующие представления и заполнять JsonResult и вернуть его.

Например, вы можете определить:

public CompoundResult: ActionResult
{
    public string ViewName { get; set; }
    public JsonResult JsonResult { get; set; }
    public CompoundResult(string viewName, JsonResult jsonResult)
    {
       ViewName = viewName;
       JsonResult = jsonResult;
    }
}

а затем в ResultFilter визуализируйте соответствующий вид и объедините его с соответствующим местом в JsonResult и, наконец, верните JsonResult клиенту.

Помимо всего этого, вы можете изменить свой подход в том, как вы это делаете, например. вы можете попытаться вернуть полное представление (т. е. HTML) из вашего действия, частью которого является представление, которое вы хотите вернуть, но которое также включает некоторую дополнительную информацию, которая в противном случае была бы в вашем объекте JSON. Вы можете извлечь соответствующие компоненты из возвращенного HTML, используя простые операции jQuery на стороне клиента.

Другие вопросы по тегам