レンダリングされたビューも含むJsonの結果を返すことはできますか?
送信されたフォームの新しいIDとそのHTMLおよびその他のプロパティを返すために必要です。
また、Jsonオブジェクト内の1つのアクションから2つ(またはそれ以上)のビュー結果を返す必要がある場合にも役立ちます。
ありがとう!
また、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データ属性とマージするまで、このアプローチは気に入らなかった。これにより、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);
});
これは、「単一責任の原則」に反するように見える場合があります(ビューに適用する場合)。ただし、アプリケーションで両方のデータを応答で送信する必要がある場合は、何も問題はありません。また、モデルが適切に構築されている限り、設計原則に反することはありません。
最初のケースでは、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 );
}
これは少しハッキーかもしれませんが(そして私は頭のてっぺんを書いています)、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から関連するコンポーネントを取り出すことができます。