In the method CreateView() (check my View Engine below) or in my custom action filter (also below) I have to somehow check if the View we are requesting is a ViewUserControl. Because otherwise I get an error saying
"A master name cannot be specified when the view is a ViewUserControl."
when I have "modal=true" in QueryString and the View request is ViewUsercontrol because you cannot set master page on ViewUserControls (obviously).
This is my custom view engine code right now:
public class PendingViewEngine : VirtualPathProviderViewEngine
{
public PendingViewEngine()
{
// This is where we tell MVC where to look for our files.
/* {0} = view name or master page name
* {1} = controller name */
MasterLocationFormats = new[] {"~/Views/Shared/{0}.master", "~/Views/{0}.master"};
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx", "~/Views/Shared/{0}.ascx",
"~/Views/{1}/{0}.ascx"
};
PartialViewLocationFormats = new[] {"~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.ascx"};
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
return new WebFormView(partialPath, "");
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
return new WebFormView(viewPath, masterPath);
}
}
My action filter:
public class CanReturnModalView : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// setup the request, view and data
HttpRequestBase request = filterContext.RequestContext.HttpContext.Request;
bool modal = false;
if (request.QueryString["modal"] != null)
modal = bool.Parse(request.QueryString["modal"]);
if (filterContext.Result is ViewResult)
{
ViewResult view = (ViewResult) (filterContext.Result);
// replace the view Master page file with Modal Masterpage
if (modal)
view.MasterName = "AdministrationModal";
filterContext.Result = view;
}
else if (filterContext.Result is RedirectToRouteResult)
{
RedirectToRouteResult redirect = (RedirectToRouteResult) filterContext.Result;
// append modal route value to the redirect result if modal was requested
if (modal)
redirect.RouteValues.Add("modal", true);
filterContext.Result = redirect;
}
}
}
The above ViewEngine fails on calls like this:
<% Html.RenderAction("Display", "MyController", new { zoneslug = "some-zone-slug" });%>
The action I am rendering here is this:
public ActionResult Display(string zoneslug)
{
WidgetZone zone;
if (!_repository.IsUniqueSlug(zoneslug))
zone = (WidgetZone) _repository.GetInstance(zoneslug);
else
{
// do something here
}
// WidgetZone used here is WidgetZone.ascx, so a partial
return View("WidgetZone", zone);
}
I cannot use RenderPartial because you cannot send route values to RenderPartial the way you can to RenderAction. To my knowledge there is no way to provide RouteValueDictionary to RenderPartial() like the way you can to RenderAction().