2012-07-25 2 views
33

PartialViewをHTML文字列にレンダリングして、SignalR ajaxリクエストに戻すことができます。MVC PartialViewをSignalRレスポンスにレンダリングする

のような何か:

SignalRハブ(mySignalHub.cs)

public class mySignalRHub: Hub 
{ 
    public string getTableHTML() 
    { 
     return PartialView("_MyTablePartialView", GetDataItems()) // *How is it possible to do this* 
    } 
} 

レイザーPartialView(_MyTablePartialView.cshtml)

@model IEnumerable<DataItem> 

<table> 
    <tbody> 
     @foreach (var dataItem in Model) 
     { 
     <tr> 
      <td>@dataItem.Value1</td> 
      <td>@dataItem.Value2</td> 
     </tr> 
     } 
    </tbody> 
</table> 

HTML(MySignalRWebPage.html)

<Script> 
    ...  
    //Get HTML from SignalR function call 
    var tableHtml = $.connection.mySignalRHub.getTableHTML(); 

    //Inject into div 
    $('#tableContainer).html(tableHtml); 
</Script> 

<div id="tableContainer"></div> 

私の問題は、PartialViewをコントローラの外でレンダリングできないようです。コントローラの外でPartialViewをレンダリングすることも可能ですか? Razorに付属している素晴らしいHTML生成能力を引き続き活用することは、非常にうれしいことです。

私はこれについてすべて間違っていますか?別の方法がありますか?

+1

も興味を持って...アイデア:

public static string RenderPartialView(string controllerName, string partialView, object model) { var context = new HttpContextWrapper(System.Web.HttpContext.Current) as HttpContextBase; var routes = new System.Web.Routing.RouteData(); routes.Values.Add("controller", controllerName); var requestContext = new RequestContext(context, routes); string requiredString = requestContext.RouteData.GetRequiredString("controller"); var controllerFactory = ControllerBuilder.Current.GetControllerFactory(); var controller = controllerFactory.CreateController(requestContext, requiredString) as ControllerBase; controller.ControllerContext = new ControllerContext(context, routes, controller); var ViewData = new ViewDataDictionary(); var TempData = new TempDataDictionary(); ViewData.Model = model; using (var sw = new StringWriter()) { var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialView); var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, ViewData, TempData, sw); viewResult.View.Render(viewContext, sw); return sw.GetStringBuilder().ToString(); } } 

あなたはのようなもので、それを呼ぶのでしょうか?コントローラの外にパーシャルをレンダリングできますか? –

+0

これは簡単な方法ではありません。 ksonのデータを返してから、すでにページに入っているクライアント側のtempateを調整する方が良いでしょう。次に、tempateはパーシャルビューでレンダリングできます –

答えて

12

これは私がコントローラ用のajaxで使っているものです。コントローラーの代わりにメソッドから呼び出すことができるように少し修正しましたreturnViewビューをレンダリングし、JS/jQueryあなたは、クライアント側でそれをrecive時に、あなたのページに:

public static string RenderPartialToString(string view, object model, ControllerContext Context) 
     { 
      if (string.IsNullOrEmpty(view)) 
      { 
       view = Context.RouteData.GetRequiredString("action"); 
      } 

      ViewDataDictionary ViewData = new ViewDataDictionary(); 

      TempDataDictionary TempData = new TempDataDictionary(); 

      ViewData.Model = model; 

      using (StringWriter sw = new StringWriter()) 
      { 
       ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(Context, view); 

       ViewContext viewContext = new ViewContext(Context, viewResult.View, ViewData, TempData, sw); 

       viewResult.View.Render(viewContext, sw); 

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

     //"Error" should be name of the partial view, I was just testing with partial error view 
     //You can put whichever controller you want instead of HomeController it will be the same 
     //You can pass model instead of null 
     private string returnView() 
     { 
      var controller = new HomeController(); 
      controller.ControllerContext = new ControllerContext(HttpContext,new System.Web.Routing.RouteData(), controller); 
      return RenderPartialToString("Error", null, new ControllerContext(controller.Request.RequestContext, controller)); 
     } 

私はハブ上でそれをテストしていないが、それは動作するはずです。

+0

私は同様のテクニックを使用して、さまざまなビューを電子メールメッセージとして送信する目的で文字列としてレンダリングします。これまでのところ有効です。唯一のことは、パラメータ内のControllerContextのためコントローラ外から呼び出すのが難しいかもしれないということです。 –

+0

@ 42私は、このメソッドを呼び出す前にコントローラのインスタンスを初期化しておくと良いはずです。 ControllerContextのインスタンスがscratch.Itから作成されているのがわかります。誰かがそれをテストして、私が休暇中で、テストする場所がないので、私に知らせてくれればいいです。 – formatc

+0

Hmmm。これは当初のように見えましたが、私が完全にテストしたところ、私は問題を抱えていました:利用可能なルートデータがありません(リクエストがMVCルーティング経由でルーティングされないため)。これに対処するために偽のルーティングを追加しました。 partialviewを見つけようとしたときにnullreference例外が発生しました。このアプローチが上流で泳いでいるように感じています。私はいくつかの他のオプション(Razorテンプレートエンジンなど)を調べて、それがどこにあるのかを見ていきます。私はこの記事を更新し、もっと詳しく調べていきます。 – James

-1

以下asimilar質問に供給された回答に基づいて、私はそれはあなたがコンテンツとして使用することができすべきMvcHtmlStringを返し

Html.Partial(partialViewNameに)

を使用することをお勧めしあなたのSignalRの応答の。私はこれをテストしていない。

スタックオーバーフロー質問:Is it possible to render a view outside a controller?

+0

"HTML"オブジェクトのタイプは "HTMLHelper"です。これをインスタンス化するには、ViewContextが必要です。 ViewContextをインスタンス化するには、同じ問題に戻るControllerContextが必要です。コントローラなし。見てくれてありがとう!おかげさまで、ありがとうございます。 – James

1

あなたがhttp://razorengine.codeplex.com/のようなかみそりのテンプレートエンジンを使用して考えたことはありますか? パーシャルビューの解析には使用できませんが、部分ビューとほぼ同様のカミソリテンプレートの解析に使用できます。

+0

下のパオロの記事へのコメントを見てください。私はさらにテストするかもしれませんが、そのプロジェクトに潜在的な問題があるようです。 – James

4

Wimが示唆しているように、RazorEngineを使用することをお勧めします。

public class mySignalRHub: Hub 
{ 
    public string getTableHTML() 
    { 
     var viewModel = new[] { new DataItem { Value1 = "v1", Value2 = "v2" } }; 

     var template = File.ReadAllText(Path.Combine(
      AppDomain.CurrentDomain.BaseDirectory, 
      @"Views\PathToTablePartialView\_MyTablePartialView.cshtml")); 

     return Engine.Razor.RunCompile(template, "templateKey", null, viewModel); 
    } 
} 
+1

面白そうだ。ただし、このライブラリには同時使用に関する問題があり、Web環境ではうまく機能しません。詳細については、このスレッドを参照してください:http://stackoverflow.com/questions/6444277/using-razorengine-to-parse-razor-templates-concurrently。このエンジンの作者は、これらの問題に対処するために書き直しを行っていましたが、しばらくの間、このプロジェクトに動きがなかったようです。現在、デッドプロジェクトになっている可能性があります。https://github.com/Antaris/RazorEngine – James

+1

@James RazorEngine v3(現在の[NuGetパッケージ](http://nuget.org/packages/RazorEngine))は、マルチスレッドのシナリオでうまく動作するはずです。静的メソッド 'Razor.Parse'を呼び出すのではなく、' TemplateService'をインスタンス化するだけです。詳細については、[この投稿](http://www.fidelitydesign.net/?p=473)をご覧ください。 –

0

方法RazorEngineHostRazorTemplateEngine使用について。私はあなたが探しているかもしれないこのnice articleを見つけました。これは、ASP.NET(MVC)の外でRazorをホスティングすることに関するものです。

3

上記の@ user1010609の回答に加えて、私はこれも苦労し、レンダリングされたPartialViewがコントローラ名、ビューおよびモデルへのパスが与えられた場合に返される関数で終了しました。

コントローラを持たないため、通常の状態がSignalRイベントから発生していないことを考慮してください。

RenderPartialView("MyController", "~/Views/MyController/_partialView.cshtml", model); 
関連する問題