I was attempting to add the functionality of a pdfresult into my site to generate pdfs in MVC, and I stumbled over this great post by Jim Zimmerman but it didnt work for me as I believe some changes that have come in MVC 2 have broken it. I have made some changes below that will get to work if anybody else needs it go for it.

public static string CaptureActionHtml(
this Controller controller,
TController targetController,
string masterPageName,
Func 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

StringWriter sw = new StringWriter();
var viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(controllerContext.Controller.ViewData.Model), new TempDataDictionary(), sw);

viewResult.View.Render(viewContext, HttpContext.Current.Response.Output);

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

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

return sw.ToString();