2011-04-05 65 views
1

我是MVC2.0的新手。我使用下面的代碼來捕獲HTML並將其作爲字符串返回。但是這在MVC1.0和.NET 3.5框架中工作正常。最近我將代碼升級到.NET 4.0和MVC 2.0。現在這不再起作用,上下文返回null。當我探索我看到兩個錯誤 1.「此操作需要IIS集成管道模式。」 2.OutputStream = 'response.OutputStream' 扔類型system.Web.HttpException」的例外在MVC2.0中捕獲HTML爲字符串

這裏,調用函數

var htmlstring = this.CaptureActionHtml(new PdfController(_paService, _configService), c => (ViewResult)paController.GetHTML(p)); 

//和捕獲方法。

/// <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(); 
     } 

我發現周圍的工作..但在另外一個問題。該模型未經過view..Here襲擊是更新的代碼

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 viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(controllerContext.Controller.ViewData.Model), new TempDataDictionary(), sw); 
    var viewContext = new ViewContext(controllerContext, viewResult.View, targetController.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(); 
    } 

任何建議將是很有益的。 。

回答

1

感謝您的審查..我發現它自己..傻我!它只是簡單的事情。這裏是完整的代碼..

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

我剛剛更換這行代碼

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

它工作正常..乾杯!