2013-09-06 14 views
13

私はKnockoutJSを既存のアプリケーションに導入しています。私の計画は、既に作成した既存のパーシャルビューを変更/利用し、Knockoutの宣言属性を使用してJSビューモデルにバインドすることです。アクションにAJAX呼び出しを行うと、パーシャルビューのHTMLとJSONオブジェクトの両方を返すことが理想的です。その後、HTMLでdivを入力し、JSONをKnockoutオブジェクトに変換してHTMLにバインドすることができます。しかし、私は両方のアクションから戻る方法を把握することはできません。ASP.NET MVCの部分ビューとJSONを返すアクション

私はそれを更新し、最終的にそれをサーバーに送り返すので、フルビューモデルが必要です。

部分的なビュー(モデルに既にバインドされています)を返し、部分ビュー内で.NetモデルをKnockoutオブジェクトに変換するためのjavascriptが含まれていると考えました。しかし、私はそれのように周りのJSを散らすことは面倒でメンテナンスが難しいと感じています。私はむしろオリジナルのAjaxコールの近くにすべてを持っていたいと思います。

もう1つの方法は、2つのアクション呼び出しを行うことです。 1つはJSON用、もう1つは部分表示用です。しかし、より滑らかなやり方が必要です。

これを行うにはどうすればよいですか?

答えて

21

私はこれを行うにはさまざまな方法があると確信しています。コントローラからビューを手動でレンダリングし、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パイプラインでレンダリングするよりも少し早くレンダリングするためです。

マニュアルレンダリング

  1. はアクションメソッド
  2. を入力し、明示的に<ビューをレンダリング - これは、それが困難な呼び出し元のアクション
  3. 終了アクションメソッド

自動をテストすることになりますレンダリング

  1. は、言い換えれば

(したがって、ビューをレンダリング)

  • 出口アクションメソッド
  • プロセスビュー結果を表示結果を作成し、アクションメソッド
  • を入力し、私たちの手動レンダリング処理がキックオフ(ビューをコンパイルするためにビルドマネージャとやりとりするなど)テストすることを困難にするさまざまな他の操作

    ビューの実際の内容ではなくアクションメソッドをテストすると仮定して、コードがホストされた環境で実行されているかどうかを確認できます。 HostingEnvironment.IsHosted確認

    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 
        } 
    

    (ボンネットの下に、それは単にヌルチェックある)安価です。

  • +0

    +1ヘルパークラスについては決して考えませんでした。これは最も洗練されたソリューションかもしれません。私はそれを試してみましょう。ありがとう。 – nthpixel

    +0

    あなたはしたくないでしょう: 'var obj = new {view = RenderHelper.PartialView(this、" _PartialName "、viewModel)、model = koViewModel};'?それとも「フー」って何?または私は何かを逃していますか? – nwayve

    +0

    @Dennis - はい、 "foo"は返す必要がある他のデータを表します。ノックアウトがクライアントに必要なものは正確にはわかりませんが、ビューにはモデルが必要です(ヌルであっても)。 –

    1

    部分モデルに<input>を隠して、値をViewModelのJSON文字列に設定することができます。次に部分ビューをレンダリングする前に、そのフィールドからJSON値を取得し、解析します。部分図から削除し、ページに挿入して実行します。ko.applyBindingsToDescendants(viewModel, $("#parentElement")[0])

    私はこのアプローチについてどのように感じているのか、それは単なる理論です。私はこれをテストしていないが、うまくいくと思う。 1つのbooty trapはあなたのGET要求をキャッシュしようとしているブラウザです。あなたのAjaxリクエストでは、次のようにしてください:

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

    または$.postリクエストをしてください。 (reference

    これは1つのオプションです。

    +0

    +1 ...しかし、私はそれについてどう感じるかわかりません。 – nthpixel

    関連する問題