KnockoutJSを既存のアプリに導入しています。私の計画は、すでに作成した既存の部分ビューを変更/利用し、それらをKnockoutの宣言型属性を使用してJSビューモデルにバインドすることです。 AJAXアクションを呼び出すとき、理想的には、アクションが部分ビューのHTMLとJSONオブジェクトの両方を返すようにします。次に、divにHTMLを入力し、変換します。 JSONをKnockoutオブジェクトにバインドし、HTMLにバインドします。しかし、アクションから両方を返す方法がわかりません。
フルビューモデルが必要なのは、それを更新して最終的にサーバーに送り返すためです。
アクションで部分ビュー(すでにモデルにバインドされている)を返し、部分ビュー内にjavascriptを含めて.NetモデルをKnockoutオブジェクトに変換することを考えました。しかし、そのようにJSを分散させるのは面倒で、保守が難しいと感じています。むしろ、すべてを元のajax呼び出しに近づけたいと思います。
もう1つの方法は、2つのアクション呼び出しを行うことだと思います。 1つはJSON用で、もう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 );
匿名型を返すことに注意してください。レンダリングされたビューの文字列プロパティがあれば、任意の(シリアル化可能な)型を返すことができます。
手動レンダリングを使用するアクションをテストするには、わずかな変更が必要です。これは、MVCパイプラインでレンダリングされるよりも少し早くビューをレンダリングするためです。
手動レンダリング
自動レンダリング
言い換えると、手動レンダリングプロセスは、テストを困難にする他のさまざまな操作(ビルドマネージャーとの対話によるビューのコンパイルなど)を開始します。
ビューの実際のコンテンツではなく、アクションメソッドをテストする場合は、コードがホスト環境で実行されているかどうかを確認できます。
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
は安価です(内部的には、単にnullチェックです)。
ViewModelのJSON文字列に値を設定して、パーシャルに非表示の_<input>
_を作成できます。次に、部分ビューをレンダリングする前に、そのフィールドからJSON値を取得し、それを解析します。次に、それを部分ビューから削除し、ページに挿入して、ko.applyBindingsToDescendants(viewModel, $("#parentElement")[0])
を実行します。
このアプローチについて私がどのように感じているかは完全にはわかりません。それは単なる理論です。私はこれをテストしていませんが、うまくいくと思います。 1つ 戦利品の罠 注意しなければならないのは、ブラウザがGETリクエストをキャッシュしようとしていることです。あなたのajaxリクエストであなたがしたいこと:
_$.ajax({
url: "/",
type: 'GET',
cache: 'false'
});
_
または、_$.post
_リクエストを実行します。 ( 参照 )
これが1つの選択肢です。