RenderAction from Controller


I've created a fancy pagination tool, and it works well, but I want to refactor/simplify it's implementation more.  

(Look at the code sample to see what's exactly going on)

1. I have a base controller with the PaginationPackage property (it's a custom class I whipped up).  
2. User drops an IQueryable object into the PaginationPackage.FilterData() method.
3. User returns List<DTO_Whatever> to GetTable View.
4. User calls RenderAction() in the GetTable View, which invokes PaginationPackage's supplemental View.  The magic happens in that supplemental view.

I want to remove the RenderAction() from the GetTable View and move it to the BaseController if the PaginationPackage has been filled in.

In other words, I have a Partial View with a table and some other data... And at the end of it, I have:
<% Html.RenderAction("Initialize", "Pagination", new { package = (DomainModel.Entities.PaginationPackage)ViewData["PaginationPackage"] }); %>

I don't want to have to call this on the User Control; it should be automatically invoked during the controller life cylce if that PaginationPackage object is set.

Any ideas?
// --------------------------------------------------------
// MyDataController.cs
// --------------------------------------------------------
public ActionResult GetTable() {

// IQueryable<DTO_Whatever>
var dtoPackage = myRepository.GetDTO();

// ...

// PaginationPackage property is in the base controller
this.PaginationPackage = new PaginationPackage(){
   PageSize = 25

var filteredData = this.PaginationPackage.FilterData(dtoPackage);

ViewData["PaginationPackage"] = this.PaginationPackage;

return PartialView(filteredData.ToList(););


// --------------------------------------------------------
// MyData > GetTable.ascx
// --------------------------------------------------------

// Table HTML code/Model stuff, etc...
<% Html.RenderAction("Initialize", "Pagination", new { package = (DomainModel.Entities.PaginationPackage)ViewData["PaginationPackage"] }); %>

Open in new window

Who is Participating?
UnionblitzAuthor Commented:
For anyone who cares (or Googled a similar question/answer):

I wanted to call a RenderAction(...) dynamically, based on a flag.  

Example 1:
Solution: One option was to just set a ViewData value, and call the RenderAction based on it: see Example 1 in the code below.  
Problem: I wanted the solution to be more dynamic... I didn't want to keep copying/pasting the ViewData["..."] flag on every partial view I created.

Example 2:
(Attempted) Solution: Another option was to call the RenderAction dynamically from the Controller. See Example 2 for the logic behind that.
Problem: I couldn't find a way to call the HTML Helper RenderAction(....) from the controller end... I guess it doesn't make sense to do it anyway, seeing as it's an HTML/View concern.

Example 3 (the winner)
Solution: Create a base controller, with the PaginationPackage class as a property that can be get/set easily.  Then, in that base controller, have the "Initialize()" ActionResult, and throw the partial page into the Shared directory (so any sub controller can access it).  Then, to call "initialize()" dynamically:
1. Override the OnActionExecuted(...) method
2. In the overridden OnActionExecuted(...) method, see if paginationpackage has been filled with content.
3. If the PaginationPackage is filled with content, Render the Initialize() method dynamically by calling the ViewEngines.Engines.FindPartialView(...), rendering the ViewContext, and converting the viewResult into a string.
4. Append the string from step 3 into the Response.
Problem: None, really... I am doing a Response.Write(...) with the dynamically created View; there is probably a better way to do it.
(in the ascx page)
// if user wishes to show the pagination toolbar:
if ((bool)ViewData["ShowPagination"]){
    Html.RenderAction("Initialize", "Pagination", new { package = (DomainModel.Entities.PaginationPackage)ViewData["PaginationPackage"] });

Example 2:
(MyTableController class)
public ActionResult ShowTableOfData(){
var dtoCollection = repository.GetData();

// Do pagination stuff
// .....

// this method would call RenderAction from the controller level.
// I couldn't find any code that could do this, so ignore it.

return View(dtoCollection);

Example 3:

(some where in a child controller, I am instantiating a PaginationPackage object, and filling it in with pagination-related content. At some point, I call a "FilterData" method to filter the IQueryable content.  Eventually, a PartialView() is returned as an ActionResult to the child controller.  This will trigger the OnActionExecuted(...) method in the parent controller class)

(The base controller class, called PaginationController)

public class PaginationController : Controller

        public PaginationPackage PaginationPackage { get; set; }

        public PaginationController()
            // this can all be overridden!
            PaginationPackage = new PaginationPackage()
                PageSize = 25,
                TargetTableClassName = "tbl-draft-folder",
                IsEnabled = false


        // When the action has been executed, attach the pagination HTML to the result:
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
            if (PaginationPackage.IsEnabled)
                // load the controller/action info into the pagination package:
                // load the pagination HTML/View here:
                string paginationContent = RenderPartialViewToString("Initialize", PaginationPackage);
                // Is there a better way to append the pagination code then 
                // to just dump to the response stream?

        protected string RenderPartialViewToString(string viewName, object model)
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");

            ViewDataDictionary vd = new ViewDataDictionary(model);
            using (StringWriter sw = new StringWriter())
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, vd, TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();

        public ActionResult Initialize(PaginationPackage package)
            return View(package);


Open in new window

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.