On ASP.NET MVC 5 I used a base ViewPage with a few properties:
public String PageTitle { get; set; }
public String PageDescription { get; set; }
public String[] BodyCssClasses { get; set; }
Then on each view I would have:
@{
PageTitle = "Title ..."
PageDescription" = "Description ..."
BodyCssClasses = new String[] { "main", "home" }
}
On the master page I would simply use something like:
<title>@Title</title>
With this approach I was able to use Strong Typed for page properties ...
Is it possible to use a Base View Page in ASP.NET MVC 6?
Since there is no Web.Config how could this be done?
Any suggestions for better options to define page head info is welcome.
UPDATE
I followed the suggested and I am using:
public abstract class ViewPageBase<TModel> : RazorPage<TModel> {
public String Title { get; set; }
} // ViewPageBase
Then on _ViewImports I have:
@inherits ViewPageBase<TModel>
On _Layout.cshtml I have:
<title>@Title</title>
And finally on a view which uses that layout I have:
@{
Title = "Page Title";
Layout = "_Layout";
}
Everything compiles and runs but the page title is always empty.
Does anyone has any idea why?
In the Model-View-Controller (MVC) pattern, the view handles the app's data presentation and user interaction. A view is an HTML template with embedded Razor markup. Razor markup is code that interacts with HTML markup to produce a webpage that's sent to the client.
Go to solution explorer => Views Folder => Right-click on “Home” Folder >> go to “Add” >> Click on [New Item] as follow. Select MVC 5 View Page with Layout(Razor) from "Add New Item" window and provide the required name like "ViewPageWithLayout. cshtml" click on "Add" button as follow.
The file "_Layout. cshtml" represents the layout of each page in the application. Right-click on the Shared folder in Solution Explorer then go to "Add" item and click on "View". Now the View has been created.
cshtml (or _ViewStart. vbhtml for VB) underneath the \Views folder of your project: The _ViewStart file can be used to define common view code that you want to execute at the start of each View's rendering. For example, we could write code within our _ViewStart.
The technique you have described in your update will technically work.
Unfortunately, as @Peter notes, you get one instance of your custom ViewPage for the view, and a different instance for the layout. Because you are using two different instances, you cannot set a property on the view and expect to access that property on the layout. That's the answer to your updated question:
Everything compiles and runs but the page title is always empty. Does anyone has any idea why?
@Peter has offered a work around using the ViewBag
. I'd like to offer an additional workaround using dependency injection.
For instance, consider placing your custom properties in their own class, with its own interface:
public interface IPageMetaData {
string PageTitle { get; set; }
string PageDescription { get; set; }
string[] BodyCssClasses { get; set; }
}
public class PageMetaData : IPageMetaData {
public string PageTitle { get; set; }
public string PageDescription { get; set; }
public string[] BodyCssClasses { get; set; }
}
Now, register this with the .Net Core dependency injection framework. Use the Scoped
lifecycle, so only one instance will be created per-web request. In a vanilla project, this takes place in Startup.cs
, in the ConfigureServices
method:
public void ConfigureServices(IServiceCollection services) {
// Add framework services.
services.AddMvc();
services.AddScoped<IPageMetaData, PageMetaData>();
}
Finally, update your _ViewImports.cshtml
file to inject this object into your views:
@inject Your.Namespace.Goes.Here.IPageMetaData MetaData;
Now your views will have a ambient MetaData
property that will correspond to a per-web request instance of the PageMetaData
class. You can access it from both views and from the layout:
@{
// In a view
MetaData.PageTitle = "Set a page title";
}
@* In a layout *@
<title>@MetaData.PageTitle</title>
You'll probably want to make your base view page inherit from RazorPage
.
public abstract class ViewPageBase<TModel> : RazorPage<TModel>
{
}
Then you should be able to configure all your pages to inherit from this in the _ViewImports.cshtml
file.
@inherits ViewPageBase<TModel>
UPDATE
Not sure if this is the best approach, but I wonder if you could use the common ViewBag to share data between your View and the Layout.
Back the properties in your base page class with the ViewBag:
public abstract class ViewPageBase<TModel> : RazorPage<TModel>
{
public string Title
{
get { return ViewBag.Title; }
set { ViewBag.Title = value; }
}
}
Set the property in your view:
@{
Title = "Home Page";
}
Use the property in _Layout.cshtml:
<title>@Title</title>
Sounds like you're looking for the @inherits
Razor directive.
For instance:
@inherits MyBaseViewPage
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