2012-07-25 57 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(); } } 

你會用類似的東西打電話了嗎?你可以渲染控制器外部的部分嗎? – 2012-07-25 20:14:01

+0

這不是一個方便的方法。最好只返回kson數據,然後提取已經在頁面中的客戶端臨時值。臨時文件可以用局部視圖呈現 – 2012-08-02 14:17:44

回答

12

這裏,這是我在控制器中用於ajax,我修改了一下,所以它可以從方法調用,而不是控制器,方法returnView呈現您的視圖並返回HTML字符串,因此您可以插入它與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,從控制器外部調用它可能會非常棘手。 – 2012-07-31 20:01:50

+0

@四十二我認爲它應該是好的,因爲我調用這個方法之前,我初始化控制器的instace。你可以看到從頭創建的ControllerContext的實例。如果有人測試它,只是爲了讓我知道,因爲我正在休假,並且沒有任何地方可以測試它,所以它會很好。 – formatc 2012-08-01 11:13:25

+0

嗯。這最初看起來像它會做的伎倆,但是當我完全測試時,我一直遇到問題:沒有可用的路由數據(因爲請求不通過MVC路由)。添加了虛假路由來解決這個問題。當試圖找到partialview時,現在得到nullreference異常...它仍然覺得這種方法正在上游游泳。我將研究其他一些選項(例如Razor模板引擎)並查看讓我感興趣的地方。我會更新這篇文章,因爲我瞭解更多。 – James 2012-08-06 18:18:34

-1

根據提供給下面asimilar問題的答案,我會建議使用

Html.Partial(partialViewName

它返回一個MvcHtmlString,你應該能夠爲內容使用你的SignalR響應。但是,我沒有測試過這個。

堆棧溢出問題:Is it possible to render a view outside a controller?

+0

「HTML」對象的類型是「HTMLHelper」。爲了實例化這個,你需要一個ViewContext。要實例化一個ViewContext,你需要一個ControllerContext ...回到同樣的問題。沒有控制器。感謝您的期待! – James 2012-07-26 15:25:47

1

你有沒有想過用剃刀將模板引擎就像http://razorengine.codeplex.com/? 您不能使用它來分析部分視圖,但可以使用它來分析剃刀模板,這幾乎與部分視圖相似。

+0

有趣,謝謝。見下面Paolo的帖子評論。我可能會進一步測試,但該項目似乎存在一些潛在的問題。 – James 2012-08-06 18:24:16

4

也許是最好的選擇是使用RazorEngine,作爲Wim是在暗示。

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

看起來很有趣。但是,這個庫存在併發使用問題,這在網絡環境下將無法正常工作。有關詳細信息,請參閱此主題:http://stackoverflow.com/questions/6444277/using-razorengine-to-parse-razor-templates-concurrently。該引擎的作者正在進行重寫以解決這些問題,但目前似乎沒有任何關於此項目的動作 - 現在可能是一個死了的項目:https://github.com/Antaris/RazorEngine – James 2012-08-06 18:22:37

+1

@James RazorEngine v3(當前的[NuGet包](http://nuget.org/packages/RazorEngine))應該在多線程場景中正常工作。你只需要實例化一個'TemplateService',而不是調用靜態方法'Razor.Parse'。看看[這篇文章](http://www.fidelitydesign.net/?p=473)瞭解更多詳情。 – 2012-08-06 20:12:36

0

如何使用RazorEngineHostRazorTemplateEngine。我發現這nice article這可能是你在找什麼。這是關於在ASP.NET之外託管Razor(MVC)的。

3

除了上面@ user1010609提供的答案之外,我還努力完成了這個任務,並且最終得到了一個函數,該函數返回呈現的PartialView,並給出控制器名稱,視圖和模型的路徑。

考慮到您沒有控制器,因此沒有來自SignalR事件的常見狀態。

RenderPartialView("MyController", "~/Views/MyController/_partialView.cshtml", model);