2010-12-03 41 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) 
相关问题