It took some time, but I found a great solution. Keith's solution works for many people, but in certain situations itβs not the best, because sometimes you want your application to go through the controller process to render the view, and the Keith solution just displays the view with the given model. Iβm introducing a new solution here, which will start the normal process.
The main steps:
- Create Utility Class
- Create a dummy controller with a dummy view
- On your
aspx or master page call the utility method for partial rendering, passing the Controller, view and, if you need, the model to render (as an object),
Let's check this carefully in this example.
1) Create a class called MVCUtility and create the following methods:
//Render a partial view, like Keith solution private static void RenderPartial(string partialViewName, object model) { HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current); RouteData routeData = new RouteData(); routeData.Values.Add("controller", "Dummy"); ControllerContext controllerContext = new ControllerContext(new RequestContext(httpContextBase, routeData), new DummyController()); IView view = FindPartialView(controllerContext, partialViewName); ViewContext viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextBase.Response.Output); view.Render(viewContext, httpContextBase.Response.Output); } //Find the view, if not throw an exception private static IView FindPartialView(ControllerContext controllerContext, string partialViewName) { ViewEngineResult result = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName); if (result.View != null) { return result.View; } StringBuilder locationsText = new StringBuilder(); foreach (string location in result.SearchedLocations) { locationsText.AppendLine(); locationsText.Append(location); } throw new InvalidOperationException(String.Format("Partial view {0} not found. Locations Searched: {1}", partialViewName, locationsText)); } //Here the method that will be called from MasterPage or Aspx public static void RenderAction(string controllerName, string actionName, object routeValues) { RenderPartial("PartialRender", new RenderActionViewModel() { ControllerName = controllerName, ActionName = actionName, RouteValues = routeValues }); }
Create a class to pass parameters, I will call here RendeActionViewModel (you can create the MvcUtility class in the same file)
public class RenderActionViewModel { public string ControllerName { get; set; } public string ActionName { get; set; } public object RouteValues { get; set; } }
2) Now create a controller named DummyController
//Here the Dummy controller with Dummy view public class DummyController : Controller { public ActionResult PartialRender() { return PartialView(); } }
Create a Dummy view named PartialRender.cshtml ( PartialRender.cshtml view) for the DummyController with the following contents, note that it will perform another rendering action using the Html helper.
@model Portal.MVC.MvcUtility.RenderActionViewModel @{Html.RenderAction(Model.ActionName, Model.ControllerName, Model.RouteValues);}
3) Now just put this in a MasterPage or aspx file to partially display the desired view. Note that this is a great answer when you have several types of razors that you want to mix with your MasterPage or aspx pages. (Suppose we have a PartialView called Login for Controller Home).
<% MyApplication.MvcUtility.RenderAction("Home", "Login", new { }); %>
or if you have a model to go into action
<% MyApplication.MvcUtility.RenderAction("Home", "Login", new { Name="Daniel", Age = 30 }); %>
This is a great solution, it does not use an ajax call , which does not cause deferred rendering for nested views, does not create a new WebRequest, so it will not bring you a new session and will process the method to retrieve. ActionResult for the view you need, it works without going through any model
Using MVC RenderAction in a Web Form