2010-12-03 25 views
95

如何在ASP.NET視圖引擎is known上生成給定部分視圖的HTML。ASP.NET MVC Razor:如何在控制器動作中呈現Razor部分視圖的HTML

但是,如果在剃刀局部視圖上使用此功能,則它不起作用,例外情況是部分視圖不會從「UserControl」派生。

如何解決渲染以支持剃刀局部視圖?

我需要這個,因爲我生成電子郵件成爲本部分景色...

更新:失敗(@mcl)

代碼:

public string RenderPartialToString(string controlName, object viewData) 
    { 
     ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() }; 
     viewPage.Url = this.GetUrlHelper(); 

     string fullControlName = "~/Views/Email/" + controlName + ".ascx"; 

     viewPage.ViewData = new ViewDataDictionary(viewData); 
     viewPage.Controls.Add(viewPage.LoadControl(fullControlName)); 

     StringBuilder sb = new StringBuilder(); 
     using (StringWriter sw = new StringWriter(sb)) 
     { 
      using (HtmlTextWriter tw = new HtmlTextWriter(sw)) 
      { 
       viewPage.RenderControl(tw); 
      } 
     } 
     return sb.ToString(); 
    } 
+1

你能告訴你有這麼遠,產生異常的代碼? – mlibby 2010-12-03 12:48:00

回答

152
@Html.Partial("nameOfPartial", Model) 

更新

protected string RenderPartialViewToString(string viewName, object model) 
{ 
    if (string.IsNullOrEmpty(viewName)) 
     viewName = ControllerContext.RouteData.GetRequiredString("action"); 

    ViewData.Model = model; 

    using (StringWriter sw = new StringWriter()) { 
     ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); 
     ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); 
     viewResult.View.Render(viewContext, sw); 

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

是的,這是您在視圖內渲染局部視圖的方式。但是如何在控制器動作中呈現它? – 2010-12-03 12:42:35

+0

更新了答案。 – jgauffin 2010-12-03 12:53:42

+0

現在好了!與Razon和ASP符號一起工作。 – 2010-12-03 18:57:33

6

您也可以使用RenderView Controller extensionheresource

,並使用它像這樣:

public ActionResult Do() { 
var html = this.RenderView("index", theModel); 
... 
} 

它爲剃刀web的表單 viewengines

1

我看到有人想知道如何爲另一個控制器做這件事。

在我的情況下,我在Views/Email文件夾中放置了所有的電子郵件模板,但是您可以修改它以傳入與您關聯的視圖的控制器。

public static string RenderViewToString(Controller controller, string viewName, object model) 
    { 
     var oldController = controller.RouteData.Values["controller"].ToString(); 

     if (controller.GetType() != typeof(EmailController)) 
      controller.RouteData.Values["controller"] = "Email"; 

     var oldModel = controller.ViewData.Model; 
     controller.ViewData.Model = model; 
     try 
     { 
      using (var sw = new StringWriter()) 
      { 
       var viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, 
                      null); 

       var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw); 
       viewResult.View.Render(viewContext, sw); 

       //Cleanup 
       controller.ViewData.Model = oldModel; 
       controller.RouteData.Values["controller"] = oldController; 

       return sw.GetStringBuilder().ToString(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 

      throw ex; 
     } 
    } 

本質上講這確實是需要一個控制器,如的AccountController並修改它認爲這是一個EmailController使代碼看起來在Views/Email文件夾中。有必要這樣做,因爲FindView方法不會將直線路徑作爲參數,它需要ControllerContext

完成渲染字符串後,它會將AccountController返回到由Response對象使用的初始狀態。

7

雖然已經給出了足夠的答案,但我想提出一個不太詳細的解決方案,可以在沒有MVC控制器類中可用的幫助器方法的情況下使用。使用所謂的「RazorEngine」第三方庫,你可以使用.net文件IO得到剃刀文件的內容,並調用

string html = Razor.Parse(razorViewContentString, modelObject); 

獲取第三方庫here

1

偉大的代碼;小提示:如果你有時必須繞過更多的數據,而不僅僅是viewmodel ..

if (model is ViewDataDictionary) 
{ 
    controller.ViewData = model as ViewDataDictionary; 
} else { 
    controller.ViewData.Model = model; 
} 
0

借款@jgauffin答案作爲擴展的HtmlHelper:

public static class HtmlHelperExtensions 
{ 
    public static MvcHtmlString RenderPartialViewToString(
     this HtmlHelper html, 
     ControllerContext controllerContext, 
     ViewDataDictionary viewData, 
     TempDataDictionary tempData, 
     string viewName, 
     object model) 
    { 
     viewData.Model = model; 
     string result = String.Empty; 

     using (StringWriter sw = new StringWriter()) 
     { 
      ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName); 
      ViewContext viewContext = new ViewContext(controllerContext, viewResult.View, viewData, tempData, sw); 
      viewResult.View.Render(viewContext, sw); 

      result = sw.GetStringBuilder().ToString(); 
     } 

     return MvcHtmlString.Create(result); 
    } 
} 

用法在Razor視圖:

Html.RenderPartialViewToString(ViewContext, ViewData, TempData, "Search", Model) 
相關問題