Reputation: 93551
I have an extension methods for MVCs Controller
class that needs to know what the current default layout file is (i.e. the value from _ViewStart.cshtml
).
The code is in a library, so I only have the controller to start from. The code below basically allows any controller action to always return a PartialPage, but conditionally assigns the default layout layout (making it a full View) if it was not in response to an Ajax request (e.g. to see the entire page for debugging).
e.g.
public static void RenderMode(this Controller controller)
{
if (!controller.Request.IsAjaxReuest())
{
controller.ViewBag.Layout = ????????;
}
}
So the question is, how do you get at the default layout page value from code?
Upvotes: 1
Views: 1800
Reputation: 93551
According to the comment from Andreas (thanks), the required setting is buried away in the RazorViewEngine class and is not accessible.
We recently found a better way to do this, without the invasive changes to any action code.
BaseController
class.OnActionExecuting
override method to the BaseController
.RenderMode()
from inside that method - so this will happen for all requests, before the action gets called.RenderMode()
to set ViewBag.Layout = null
for Ajax page requests.BaseController.cs - RenderMode()
public void RenderMode(string layout)
{
if (IsPartialPage)
{
// Wipe any existing layout page
ViewBag.Layout = null;
return;
}
ViewBag.Layout = layout;
}
ViewStart.cshtml
@{
Layout = (string)ViewContext.Controller.ViewBag.Layout;
}
The end result is that you can return a View()
or a PartialView()
as normal and the view will be rendered as a full or partial view based instead on the "ajax" check done before the action executes. This has simplified our websites significantly as we can use more of the standard scaffolded code as-is.
My workaround is therefore to pass a default layout to the RenderMode
extension method:
public static void RenderMode(this Controller controller, layout)
{
if (!controller.Request.IsAjaxReuest())
{
controller.ViewBag.Layout = layout;
}
}
and call from any controller like this (or using a constant known to the app):
public ActionResult SomeAction()
{
var vm = new SomeViewModel();
RenderMode("~/views/shared/_MainLayout.cshtml");
return PartialView(vm);
}
The end result is a partial view when called from Ajax or a full view, using _mainLayout.cshtml
, if called directly.
Upvotes: 1