Reputation: 1202
I have defined a custom WebViewPage type with custom properties used by our site:
public abstract class BasePage : WebViewPage
{
public string OmniPageName { get; set; }
}
public abstract class BasePage<TModel> : WebViewPage<TModel> where TModel: class
{
public string OmniPageName { get; set; }
}
And in my view I set this property like:
Index.cshtml:
@{
OmniPageName = "Home";
}
This is set fine and usable within the view, but I also need to access this value in the layout. I am hoping I can access the view instance from within the layout's InitializePage() override but I cannot figure out how. Something like:
protected override void InitializePage()
{
// this.OmniPageName = (expr:child view).OmniPageName
base.InitializePage();
}
And then use:
Layout.cshtml:
<!-- render value from Index.cshtml -->
<div class="pagelet" data-omnipage="@OmniPageName"></div>
Currently, the Layout's value for this property is null. I could use the ViewBag but there are other properties that are not simple, scalar values and I want to leverage the IDE's enforcement of strong typing to prevent mistakes.
Any help would be greatly appreciated!
Upvotes: 1
Views: 2113
Reputation: 12683
There is no reason why you cant do it exactly as you have written.
However you need to make sure that the web.Config is set to all views to inherit from your custom view page. (Not sure if this is already done).
In the web.config
found ~/Views/web.config
folderSet the pageBaseType
to the type of your view. Such as
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="YourNameSpace.BasePage"> <!-- Edit This line -->
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<!-- ommited -->
</namespaces>
</pages>
</system.web.webPages.razor>
Now from what we can see you only have a custom WebViewPage
for a Typed model by inheriting from WebViewPage<TModel>
. However layout pages typically not typed. Therefore you should create another class that inherits from your BaseViewPage
such as
public class BaseViewPage : BaseViewPage<dynamic>
{
//functionality is inherited from BaseViewPage<T>
}
This will inherit all the functionality of your Typed BaseViewPage
and allow for non-typed views.
Edit:
Now if you test this you still wont get data passed to the Layout page as you will find (set a constructor break point) and a new instance of the BaseViewPage
is created for each View rendered. Therefore you need to find a way to pass data in a shared object between the instances. Luckily there are many different shared objects available.
public string OmniPageName
{
get
{
return (ViewBag._OmniPageName ?? "").ToString();
}
set
{
ViewBag._OmniPageName = value;
}
}
This is a simple example that uses the ViewBag
(<dynamic>
) to shared the name. We could use:
ViewData
: Essentially the same as ViewBag
but is a Dictionary
TempData
: This is similar to the ViewData
but can persist between requests.Upvotes: 3