可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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>
回答2:
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 IPageMetaData { string PageTitle { get; set; } string PageDescription { get; set; } string[] BodyCssClasses { get; set; } } public 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>
回答3:
Sounds like you're looking for the @inherits
Razor directive.
For instance:
@inherits MyBaseViewPage