2010-03-29 86 views
38

我有以下代碼:如何呈現局部視圖爲String

public ActionResult SomeAction() 
{ 
    return new JsonpResult 
    { 
     Data = new { Widget = "some partial html for the widget" } 
    }; 
} 

我想修改它,這樣我可以有

public ActionResult SomeAction() 
{ 
    // will render HTML that I can pass to the JSONP result to return. 
    var partial = RenderPartial(viewModel); 
    return new JsonpResult 
    { 
     Data = new { Widget = partial } 
    }; 
} 

這可能嗎?有人可以解釋一下嗎?

note,我在發佈解決方案之前編輯了問題。

+0

所有的答案 - 作爲一個疑難雜症,如果你想呈現來自另一個控制器的觀點,你必須完全指定視圖名稱'「〜/查看/ / .cshtml「' – drzaus 2013-09-27 21:13:06

回答

20

這是問題的解答略加修改的版本:

public static string RenderPartialToString(string controlName, object viewData) 
{ 
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() }; 

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

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

    return sb.ToString(); 
} 

用法:

string ret = RenderPartialToString("~/Views/MyController/MyPartial.ascx", model); 
+5

這對我來說很好。然而,如果我將RenderPartial添加到我傳遞給此方法的局部視圖中,我開始在RenderControl調用中獲取一個異常:「值不能爲空。參數名稱:視圖」 – 2010-05-20 18:33:35

+3

對我來說沒有效用,我正在使用剃刀視圖引擎,似乎這與ascx用戶控件,而不是部分cshtml視圖。我張貼在這裏我自己的版本,與剃刀工作:http://stackoverflow.com/questions/5532345/mvc-render-to-s-and-string-in-the-controller-or-else-were/8677839#comment10788063_8677839 – Nestor 2011-12-30 09:14:06

1

戴夫,

同一主題的變化(MVC 1.0) :

 protected static string RenderPartialToString(Controller controller, string partialName, object model) 
    { 
     var vd = new ViewDataDictionary(controller.ViewData); 
     var vp = new ViewPage 
     { 
      ViewData = vd, 
      ViewContext = new ViewContext(), 
      Url = new UrlHelper(controller.ControllerContext.RequestContext) 
     }; 

     ViewEngineResult result = ViewEngines 
            .Engines 
            .FindPartialView(controller.ControllerContext, partialName); 

     if (result.View == null) 
     { 
      throw new InvalidOperationException(
      string.Format("The partial view '{0}' could not be found", partialName)); 
     } 
     var partialPath = ((WebFormView)result.View).ViewPath; 

     vp.ViewData.Model = model; 

     Control control = vp.LoadControl(partialPath); 
     vp.Controls.Add(control); 

     var sb = new StringBuilder(); 

     using (var sw = new StringWriter(sb)) 
     { 
      using (var tw = new HtmlTextWriter(sw)) 
      { 
       vp.RenderControl(tw); 
      } 
     } 
     return sb.ToString(); 
    } 

us控制器內年齡:

 public string GetLocationHighlites() 
    { 
     IBlockData model = WebPagesMapper.GetLocationHighlites(); 
     // **this** being the controoler instance 
     // LocationPartial.ascx can be defined in shared or in view folder 
     return RenderPartialToString(**this**,"LocationPartial", model); 
    } 
8

DaveDev的回答工作很適合我,但是當局部視圖調用另一部分,我得到「值不能爲空。參數名:鑑於」

搜索周圍我已經做了following的變種,似乎運作良好

public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext) 
    { 
     if (string.IsNullOrEmpty(viewName)) 
      viewName = ControllerContext.RouteData.GetRequiredString("action"); 
     ViewDataDictionary ViewData = new ViewDataDictionary(); 
     TempDataDictionary TempData = new TempDataDictionary(); 
     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(); 
     } 

    } 

用法:

String result = MVCHelpers.RenderPartialToString("PartialViewHere", Model, ControllerContext) 
5

您可以創建擴展的呈現視圖轉換爲字符串

public static class RenderPartialToStringExtensions 
{ 
    /// <summary> 
    /// render PartialView and return string 
    /// </summary> 
    /// <param name="context"></param> 
    /// <param name="partialViewName"></param> 
    /// <param name="model"></param> 
    /// <returns></returns> 
    public static string RenderPartialToString(this ControllerContext context, string partialViewName, object model) 
    { 
     return RenderPartialToStringMethod(context, partialViewName, model); 
    } 

    /// <summary> 
    /// render PartialView and return string 
    /// </summary> 
    /// <param name="context"></param> 
    /// <param name="partialViewName"></param> 
    /// <param name="viewData"></param> 
    /// <param name="tempData"></param> 
    /// <returns></returns> 
    public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData) 
    { 
     return RenderPartialToStringMethod(context, partialViewName, viewData, tempData); 
    } 

    public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData) 
    { 
     ViewEngineResult result = ViewEngines.Engines.FindPartialView(context, partialViewName); 

     if (result.View != null) 
     { 
      StringBuilder sb = new StringBuilder(); 
      using (StringWriter sw = new StringWriter(sb)) 
      { 
       using (HtmlTextWriter output = new HtmlTextWriter(sw)) 
       { 
        ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, output); 
        result.View.Render(viewContext, output); 
       } 
      } 

      return sb.ToString(); 
     } 
     return String.Empty; 
    } 

    public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, object model) 
    { 
     ViewDataDictionary viewData = new ViewDataDictionary(model); 
     TempDataDictionary tempData = new TempDataDictionary(); 
     return RenderPartialToStringMethod(context, partialViewName, viewData, tempData); 
    } 
} 

然後在行動中使用它

[HttpPost] 
public ActionResult GetTreeUnit(string id) 
{ 
    int _id = id.ExtractID(); 
    string render = ControllerContext.RenderPartialToString("SomeView"); 
    return Json(new { data = render }); 
} 
34

我選擇了像ASP.NET MVC 4應用程序一樣的擴展方法。我認爲它比一些我見過的建議簡單:

public static class ViewExtensions 
{ 
    public static string RenderToString(this PartialViewResult partialView) 
    { 
     var httpContext = HttpContext.Current; 

     if (httpContext == null) 
     { 
      throw new NotSupportedException("An HTTP context is required to render the partial view to a string"); 
     } 

     var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString(); 

     var controller = (ControllerBase)ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, controllerName); 

     var controllerContext = new ControllerContext(httpContext.Request.RequestContext, controller); 

     var view = ViewEngines.Engines.FindPartialView(controllerContext, partialView.ViewName).View; 

     var sb = new StringBuilder(); 

     using (var sw = new StringWriter(sb)) 
     { 
      using (var tw = new HtmlTextWriter(sw)) 
      { 
       view.Render(new ViewContext(controllerContext, view, partialView.ViewData, partialView.TempData, tw), tw); 
      } 
     } 

     return sb.ToString(); 
    } 
} 

它能讓我做到以下幾點:

var html = PartialView("SomeView").RenderToString(); 

而且,這種方法仍然存在任何型號ViewBag和視圖的其他視圖數據。

2

運行完美(僅需要查看名稱)
*爲參數,你可以使用一個模型
*可以從視圖也稱之爲

查看側或主叫方

BuyOnlineCartMaster ToInvoice1 = new BuyOnlineCartMaster(); // for passing parameters 
ToInvoice1.CartID = 1; 

string HtmlString = RenderPartialViewToString("PartialInvoiceCustomer", ToInvoice1); 

功能生成HTML

public static string RenderPartialViewToString(string viewName, object model) 
    {  
    using (var sw = new StringWriter()) 
      { 
       BuyOnlineController controller = new BuyOnlineController(); // instance of the required controller (you can pass this as a argument if needed) 

       // Create an MVC Controller Context 
       var wrapper = new HttpContextWrapper(System.Web.HttpContext.Current); 

       RouteData routeData = new RouteData(); 

       routeData.Values.Add("controller", controller.GetType().Name 
                  .ToLower() 
                  .Replace("controller", "")); 

       controller.ControllerContext = new ControllerContext(wrapper, routeData, controller); 

       controller.ViewData.Model = model; 

       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); 

       return sw.ToString(); 
      } 
    } 
1

您可以通過以下方式執行此操作:

var partial = new HtmlString(Html.Partial("_myPartial", Model).ToString()); 
+0

我可以'得到Html.Partial。 – Machado 2017-10-06 20:45:29

+0

@ Dan-p據我所知Html.Partial不能直接用在控制器中。你如何使這一行代碼工作? – Mike 2017-10-11 13:23:06

+0

對不起,您是對的,我們在視圖的剃刀的@ {}塊中使用該行,而不是直接在控制器中使用該行。也許你的控制器可能會返回一個使用該代碼的局部視圖。 – 2017-10-12 15:57:22

0
public virtual string RenderPartialViewToString(string viewName, object viewmodel) 
     { 
      if (string.IsNullOrEmpty(viewName)) 
      { 
       viewName = this.ControllerContext.RouteData.GetRequiredString("action"); 
      } 

      ViewData.Model = viewmodel; 

      using (var sw = new StringWriter()) 
      { 
       ViewEngineResult viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName); 
       var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw); 
       viewResult.View.Render(viewContext, sw); 
       viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View); 

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