2010-07-13 79 views
6

我想獲取視圖在字符串中生成的html代碼,在我的控制器中修改它,然後將其添加到我的JsonResult。渲染以編程方式查看字符串

我發現代碼可以做我正在談論的部分內容。我想從aspx視圖做它。

- 額外的解釋:

比方說,我有一個頁面Frame.aspx是/控制器/框將返回

我希望得到我的手對面前的反應出來,所以我可以給用jsonp包裝它。 我不希望每次都在代碼中編輯返回結果,這就是爲什麼我想以編程方式加載視圖的原因。

/控制器/幀返回當前Frame.aspx的內容:<html><body>hello</body></html>

比方說有呈現一個視圖中的字符串生成器

StringBuilder sb = new StringBuilder(); 
RenderView(sb, "Frame"); 

現在採取某人與JSONP包裝它的功能:

public JsonResult Frame(string callback) 
{ 
    StringBuilder sb = new StringBuilder(); 
    RenderView(sb, "Frame"); 

    return new JsonResult 
    { 
     Data = "(function() { " + callback + "(" + clientResponse + "); })();" 
     , 
     JsonRequestBehavior = JsonRequestBehavior.AllowGet 
    }; 
} 
+1

[Render a view as a string]可能的重複(http://stackoverflow.com/questions/483091/render-a-view-as-a-string) – 2010-07-13 03:54:46

+0

請編輯這個問題的更多細節,也許一些示例代碼。這裏沒有足夠的細節來嘗試答案。 – 2010-07-13 03:55:10

+0

請不要在標題中包含「C#」等標籤。這只是多餘的。將它們留在標籤中就足夠了。 – 2010-07-13 04:33:52

回答

19

這就像一個魅力(得到它通過SO)。

我使用這樣的:

public class OfferController : Controller 
{ 
    [HttpPost] 
    public JsonResult EditForm(int Id) 
    { 
     var model = Mapper.Map<Offer, OfferEditModel>(_repo.GetOffer(Id)); 

     return Json(new { status = "ok", partial = this.RenderPartialViewToString("Edit", model) }); 
    } 
} 



public static partial class ControllerExtensions 
{ 
    public static string RenderPartialViewToString(this ControllerBase controller, string partialPath, object model) 
    { 
     if (string.IsNullOrEmpty(partialPath)) 
      partialPath = controller.ControllerContext.RouteData.GetRequiredString("action"); 

     controller.ViewData.Model = model; 

     using (StringWriter sw = new StringWriter()) 
     { 
      ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialPath); 
      ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw); 
      // copy model state items to the html helper 
      foreach (var item in viewContext.Controller.ViewData.ModelState) 
       if (!viewContext.ViewData.ModelState.Keys.Contains(item.Key)) 
       { 
        viewContext.ViewData.ModelState.Add(item); 
       } 


      viewResult.View.Render(viewContext, sw); 

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

太棒了!謝謝:-) – Abdo 2010-11-15 22:56:25

+1

我怎樣才能對.NET CORE做同樣的事情? – 2016-12-01 13:59:11

0

Mike Hadlow在博客中介紹了一個名爲CaptureActionHtml()的函數。我用它來製作更小,更易於管理的報告,然後傳遞給他們。

http://mikehadlow.blogspot.com/2008/06/mvc-framework-capturing-output-of-view_05.html

using System; 
using System.IO; 
using System.Web; 
using System.Web.Mvc; 

namespace Suteki.Common.Extensions 
{ 
    public static class ControllerExtensions 
    { 
     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The controller</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this TController controller, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      return controller.CaptureActionHtml(controller, null, action); 
     } 

     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The controller</param> 
     /// <param name="masterPageName">The master page to use for the view</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this TController controller, 
      string masterPageName, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      return controller.CaptureActionHtml(controller, masterPageName, action); 
     } 

     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The current controller</param> 
     /// <param name="targetController">The controller which has the action to execute</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this Controller controller, 
      TController targetController, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      return controller.CaptureActionHtml(targetController, null, action); 
     } 

     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The current controller</param> 
     /// <param name="targetController">The controller which has the action to execute</param> 
     /// <param name="masterPageName">The name of the master page for the view</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this Controller controller, 
      TController targetController, 
      string masterPageName, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      if (controller == null) 
      { 
       throw new ArgumentNullException("controller"); 
      } 
      if (targetController == null) 
      { 
       throw new ArgumentNullException("targetController"); 
      } 
      if (action == null) 
      { 
       throw new ArgumentNullException("action"); 
      } 

      // pass the current controller context to orderController 
      var controllerContext = controller.ControllerContext; 
      targetController.ControllerContext = controllerContext; 

      // replace the current context with a new context that writes to a string writer 
      var existingContext = System.Web.HttpContext.Current; 
      var writer = new StringWriter(); 
      var response = new HttpResponse(writer); 
      var context = new HttpContext(existingContext.Request, response) {User = existingContext.User}; 
      System.Web.HttpContext.Current = context; 

      // execute the action 
      var viewResult = action(targetController); 

      // change the master page name 
      if (masterPageName != null) 
      { 
       viewResult.MasterName = masterPageName; 
      } 

      // we have to set the controller route value to the name of the controller we want to execute 
      // because the ViewLocator class uses this to find the correct view 
      var oldController = controllerContext.RouteData.Values["controller"]; 
      controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", ""); 

      // execute the result 
      viewResult.ExecuteResult(controllerContext); 

      // restore the old route data 
      controllerContext.RouteData.Values["controller"] = oldController; 

      // restore the old context 
      System.Web.HttpContext.Current = existingContext; 

      return writer.ToString(); 
     } 
    } 
} 
+0

這對V3.5和MVc1.0適合我。但是當我將其升級到V4.0和MVC 2.0時,上下文返回null ..任何想法? – Gokul 2011-04-04 20:36:32

0

下面是用於捕獲在MVC 2.0視圖和>淨4.0另一個解決方法。我只是向Andrews原創內容添加了幾行代碼。

public static class ControllerExtensions 
    { 

     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The controller</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this TController controller, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      return controller.CaptureActionHtml(controller, null, action); 
     } 

     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The controller</param> 
     /// <param name="masterPageName">The master page to use for the view</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this TController controller, 
      string masterPageName, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      return controller.CaptureActionHtml(controller, masterPageName, action); 
     } 

     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The current controller</param> 
     /// <param name="targetController">The controller which has the action to execute</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     public static string CaptureActionHtml<TController>(
      this Controller controller, 
      TController targetController, 
      Func<TController, ViewResult> action) 
      where TController : Controller 
     { 
      return controller.CaptureActionHtml(targetController, null, action); 
     } 




     /// <summary> 
     /// Captures the HTML output by a controller action that returns a ViewResult 
     /// </summary> 
     /// <typeparam name="TController">The type of controller to execute the action on</typeparam> 
     /// <param name="controller">The current controller</param> 
     /// <param name="targetController">The controller which has the action to execute</param> 
     /// <param name="masterPageName">The name of the master page for the view</param> 
     /// <param name="action">The action to execute</param> 
     /// <returns>The HTML output from the view</returns> 
     ///  
    public static string CaptureActionHtml<TController>(this Controller controller, TController targetController, string masterPageName, Func<TController, ViewResult> action) where TController : Controller 

     { 
    if (controller == null) 
    { 
    throw new ArgumentNullException("controller"); 
    } 
    if (targetController == null) 
    { 
    throw new ArgumentNullException("targetController"); 
    } 
    if (action == null) 
    { 
    throw new ArgumentNullException("action"); 
    } 
    // pass the current controller context to orderController 
    var controllerContext = controller.ControllerContext; 
    targetController.ControllerContext = controllerContext; 

    // replace the current context with a new context that writes to a string writer 
    var existingContext = HttpContext.Current; 
    var writer = new StringWriter(); 
    var response = new HttpResponse(writer); 
    var context = new HttpContext(existingContext.Request, response) { User = existingContext.User }; 
    HttpContext.Current = context; 

    // execute the action 
    var viewResult = action(targetController); 

    // change the master page name 
    if (masterPageName != null) 
    { 
    viewResult.MasterName = masterPageName; 
    } 

    // we have to set the controller route value to the name of the controller we want to execute 
    // because the ViewLocator class uses this to find the correct view 
    var oldController = controllerContext.RouteData.Values["controller"]; 
    controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", ""); 

    // execute the result 
    viewResult.ExecuteResult(controllerContext); 

    StringWriter sw = new StringWriter(); 
    var xx = targetController.TempData["pdf"]; 
    //var viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(targetController.ViewData.Model), new TempDataDictionary(), sw); 
    var viewContext = new ViewContext(controllerContext, viewResult.View, viewResult.ViewData, new TempDataDictionary(), sw); 
    viewResult.View.Render(viewContext, HttpContext.Current.Response.Output); 
    response.Flush(); 

    // restore the old route data 
    controllerContext.RouteData.Values["controller"] = oldController; 

    // restore the old context 
    HttpContext.Current = existingContext; 

    return sw.ToString(); 
    } 



    } 
} 

乾杯!