Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Base View Page in ASP.NET MVC 6

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?

like image 581
Miguel Moura Avatar asked Sep 14 '15 11:09

Miguel Moura


People also ask

What is view page in ASP.NET MVC?

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.

How do I create a Cshtml page in Visual Studio?

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.

What is _layout Cshtml in MVC?

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.

Where is _ViewStart Cshtml called?

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.


3 Answers

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>
like image 77
Chris Nielsen Avatar answered Oct 18 '22 18:10

Chris Nielsen


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>
like image 3
Peter Avatar answered Oct 18 '22 18:10

Peter


Sounds like you're looking for the @inherits Razor directive.

For instance:

@inherits MyBaseViewPage

like image 1
N. Taylor Mullen Avatar answered Oct 18 '22 19:10

N. Taylor Mullen