tags:

views:

466

answers:

3

Is there an equivalent to Server.Execute() in ASP.NET MVC?

Apparently that only works with traditional webforms .aspx pages.

Update: I need to grab the rendered HTML from a different action in the same controller to generate a PDF. Maybe there's a way to execute a View without outputting the html to the response stream?

A: 

The equivalent to Server.Execute in MVC is to simply instantiate the desired controller and execute the action method.

public ActionResult EntryAction()
{
    ProductController pc = new ProductController();

    return pc.Index();
}

Of course, you can skip the first step if the desired action is on the same controller.

Richard Szalay
Andrew actually needs to capture the Html from the view to write to a PDF document.
Will
Ah, the devil is in the (updated) details ;)
Richard Szalay
+1  A: 

Look at this solution:

http://stackoverflow.com/questions/483091/render-a-view-as-a-string/1241257#1241257

I used it to generate partial view and it worked. You'll have to switch to partial, but it shouldn't be the problem.

Edit:

I've done some corrects, worked with reflector and used solutions from previous questions. This code looks nicer. View rendering engine is strongly connected to HttpContext.Current, so we have to do some hacking:

    /// <summary>Renders a view to string.</summary>
    public static string RenderViewToString(this Controller controller,
                                            string viewName, object viewData)
    {
        //Getting current response
        var response = HttpContext.Current.Response;
        //Flushing
        response.Flush();

        //Finding rendered view
        var view = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName).View;
        //Creating view context
        var viewContext = new ViewContext(controller.ControllerContext, view,
                                          controller.ViewData, controller.TempData);

        //Since RenderView goes straight to HttpContext.Current, we have to filter and cut out our view
        var oldFilter = response.Filter;
        Stream filter = new MemoryStream(); ;
        try
        {
            response.Filter = filter;
            viewContext.View.Render(viewContext, null);
            response.Flush();
            filter.Position = 0;
            var reader = new StreamReader(filter, response.ContentEncoding);
            return reader.ReadToEnd();
        }
        finally
        {
            filter.Dispose();
            response.Filter = oldFilter;
        } 
    }

It should be easily convertible to allow to render View (change ViewEngines.Engines.FindPartialView to ViewEngines.Engines.FindView). I don't see better solution.

LukLed
Thanks. This works, BUT, I just can't believe that we have to jump through so many hoops just to get something like this going. It seems like a big hack to me.
Andrew Young
I corrected my answer. Does it look better?
LukLed
A: 

Many thanks for your RenderViewToString code snippet. I had to make some changes and I integrated it into to our base controller, but it works really well.

    /// <summary>Renders a view to string.</summary>
    public string RenderViewToString(ViewResult viewResult)
    {
        //Getting current response
        //var response = HttpContext.Current.Response;
        var response = Response;
        //Flushing
        response.Flush();

        //Finding rendered view
        var view = ViewEngines.Engines.FindView(ControllerContext, viewResult.ViewName, viewResult.MasterName).View;

        //Creating view context
        var viewContext = new ViewContext(ControllerContext, view,
                                          ViewData, TempData);

        //Since RenderView goes straight to HttpContext.Current, we have to filter and cut out our view
        var oldFilter = response.Filter;
        Stream filter = new MemoryStream();
        try
        {
            response.Filter = filter;
            viewContext.View.Render(viewContext, null);
            response.Flush();
            filter.Position = 0;
            var reader = new StreamReader(filter, response.ContentEncoding);
            return reader.ReadToEnd();
        }
        finally
        {
            filter.Dispose();
            response.Filter = oldFilter;
        }
    }
Bart McLeod