web-dev-qa-db-ja.com

ASP.NETMVC-Jsonの結果をViewResultと組み合わせる

レンダリングされたビューも含むJsonの結果を返すことはできますか?

送信されたフォームの新しいIDとそのHTMLおよびその他のプロパティを返すために必要です。

また、Jsonオブジェクト内の1つのアクションから2つ(またはそれ以上)のビュー結果を返す必要がある場合にも役立ちます。

ありがとう!

29
elado

また、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オブジェクトです:)

お役に立てれば ;)

41
Diego Ponciano

私はこの問題についてしばらく考えていました。私の解決策は、部分ビューHTMLをJSON文字列として返すのと似ていますが、その逆です。 JSONが埋め込まれた部分ビューを返します。 jQuery 1.4.3が.data()メソッドをHTML 5データ属性とマージするまで、このアプローチは気に入らなかった。これにより、ASP.NET MVCビュー内でJSONを生成し、jQueryを介して読み取ることがはるかに簡単になります。

例を参照してください...完璧ではありませんが、非表示のフォーム入力や、部分ビューを返す前にレンダリングするヘルパーを作成するよりもはるかに優れています。

部分ビュー:

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

JSONを読み取るJavaScript

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

これは、「単一責任の原則」に反するように見える場合があります(ビューに適用する場合)。ただし、アプリケーションで両方のデータを応答で送信する必要がある場合は、何も問題はありません。また、モデルが適切に構築されている限り、設計原則に反することはありません。

1
Jason Capriotti

最初のケースでは、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();
             }
});

2番目のケースでは、2つ以上のViewNameを取り、RenderPartialを使用する共有ビューは、JSONを介してHTMLを返すよりもおそらく優れたソリューションです。

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 );
}
1
tvanfosson

これは少しハッキーかもしれませんが(そして私は頭のてっぺんを書いています)、ActionResultの独自のサブクラスを作成し、これらの特定のタイプの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オブジェクトに含まれていたはずの追加情報も含まれています。クライアント側で簡単なjQuery操作を使用して、返されたHTMLから関連するコンポーネントを取り出すことができます。

0
paracycle