In a .NET Razor Web Application i'm trying to programmatically set the Layout
. I can not use _ViewStart.cshtml
and don't wont to set the @{ Layout = "..." }
on every page. This is what I have come up with:
A base WebViewPage
class:
public abstract class SitePage<T> : System.Web.Mvc.WebViewPage<T>
{
private object _layout;
public new dynamic Layout { get { return _layout; } }
public override void InitHelpers()
{
base.InitHelpers();
_layout = "~/Themes/" + Settings.Theme + "/Views/_Layout.cshtml";
}
}
And in the application web.config
I specify all view to use this base page. But the Layout
is never used it seems. What could be wrong here?
The WebViewPage
class inherits from WebPageBase
that has a property named Layout
like:
public override string Layout { get; set; }
You can override the Layout
property, or change your _layout logic to achieve your purpose. For example:
public abstract class SitePage<T> : System.Web.Mvc.WebViewPage<T> {
// set this modifier as protected, to make it accessible from view-pages
protected string _layout{
get {
return base.Layout;
}
set {
base.Layout = value;
}
}
public override void InitHelpers() {
base.InitHelpers();
_layout = "~/Themes/" + Settings.Theme + "/Views/_Layout.cshtml";
}
}
and/or in a view-page, you can set it too:
@{
_layout = "_Your_Special_Layout.cshtml";
}
UPDATE: using a flag to avoid stack-over-flow in assigning _layout more that once:
public abstract class SitePage<T> : System.Web.Mvc.WebViewPage<T> {
public bool LayoutAssigned {
get {
return (ViewBag.LayoutAssigned == true);
}
set {
ViewBag.LayoutAssigned = value;
}
}
// set this modifier as protected, to make it accessible from view-pages
protected string _layout{
get {
return base.Layout;
}
set {
base.Layout = value;
}
}
public override void InitHelpers() {
base.InitHelpers();
if(!LayoutAssigned) {
_layout = "~/Themes/" + Settings.Theme + "/Views/_Layout.cshtml";
LayoutAssigned = true;
}
}
}
I tried to achieve the same just now by implementing a custom WebViewPage, however changing WebViewPage.Layout within my custom class didn't have any effect (as you have also discovered).
Eventually I ended up changing my _ViewStart.cshtml to have this code:
@{
this.Layout = this.Request.QueryString["print"] == "1"
? "~/Views/Layout/_Print.cshtml"
: "~/Views/Layout/_Layout.cshtml";
}
It might not be implemented how you wanted it, but it certainly does keep things dry and that is the main point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With