The ASP.NET Master page concept is a great idea until you start thinking about search engine optimization. Search engines prefer metadata that is relevant to the page's content. The meta description should be a summary of what's on the content page and the keywords should also be relevant to page content. Setting a title from your content page is easy enough since it's built in. What about the metadata?
There are many ways to dynamically change the master pages metadata that range from using the content page's CodeBehind to fully database driven. Here I will describe a way to do it from the web.sitemap, the Master page CodeBehind and provide code samples in VB.NET and C#. Please note that this is best used on a site that is maintained by a webmaster or developer.
To use this example you will have to add some keys to the web.config file and modify your web.sitemap.
In the web.config add the following keys under <appSettings> which contain the default Page title, meta description and meta keywords name/value pairs.
<appSettings>
<!-- Default page title and meta tags -->
<add key="Meta.PageTitle" value="Your Page Title"></add>
<add key="Meta.Description" value="Your meta description."></add>
<add key="Meta.Keywords" value="Your, meta, keywords"></add>
</appSettings>
In the web.sitmap modify your dafault <siteMapnode> by adding the mDesc="" and mKey="" items.
<siteMapNode url="~/YourPage.aspx" title="YourLinkTitle" description="Your Page Title " mDesc="Your meta description" mKey="Your, meta, keywords">
This example uses a class called PageObjects and is called in the Page_Load method from the Master page's CodeBehind.
VB.NET Master Page CodeBehind
Public Partial Class Site
Inherits System.Web.UI.MasterPage
Protected MyPageLevel As Paradoxal.PageObjects = New Paradoxal.PageObjects()
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Me.MyPageLevel.GetMetaTags(Me.Page)
End If
End Sub
End Class
Vb.Net PageObjects class
#Region "=================== Imports ====================="
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Drawing
Imports System.Web
Imports System.Web.SessionState
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Web.Security
Imports System.Security.Cryptography
Imports System.Security.Principal
#End Region
''' <summary>
''' Provides methods and properties which encapsulate character,
''' data and page formatting
''' </summary>
''' <remarks></remarks>
Public Class PageObjects
#Region "================ Global Variables ================"
Protected mTitle As String = ConfigurationManager.AppSettings("Meta.PageTitle")
Protected mDesc As String = ConfigurationManager.AppSettings("Meta.Description")
Protected mKey As String = ConfigurationManager.AppSettings("Meta.Keywords")
#End Region
''' <summary>
''' Gets meta keywords, meta description and the page title values from either
''' the web.sitemap or web.config file and adds them to a Master Page at
''' runtime
''' </summary>
''' <param name="MyPage">The page url (application name)</param>
''' <remarks>
''' Requires configuring the web.config and web.sitemap
''' <list type="bullet">
''' <item>
''' In the web.config: Add the Meta.PageTitle, Meta.Description, Meta.Keywords
''' keys under appSettings with the values being the default data for page
''' title, meta description and meta kewords
''' </item>
''' <item>
''' In the web.sitemap: Add the metaKeys and metaDesc names to the siteMapNode
''' with the values being the default data for meta description and meta
''' keywords
''' </item>
''' </list>
''' </remarks>
''' <example>This sample shows how in a Master pages codebehind to call
''' the <c>GetMetaTags()</c> method:
''' <code>
''' Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
''' If Not Page.IsPostBack Then
''' Dim MyPageLevel As Paradoxal.PageObjects = New Paradoxal.PageObjects()
''' Me.MyPageLevel.GetMetaTags(Me.Page)
''' End If
''' End Sub
''' </code>
''' </example>
''' <history>
''' [Duane Urban] 08/20/2009 Created
''' </history>
Public Sub GetMetaTags(ByVal MyPage As Page)
' Declare our variables
Dim head As HtmlHead = MyPage.Master.Page.Header
Dim metaKey As New HtmlMeta()
Dim metaDesc As New HtmlMeta()
' Check for a current node in the web.sitemap
If SiteMap.CurrentNode IsNot Nothing Then
metaKey.Name = "keywords"
' Verify that the mKey value contains data
If Not SiteMap.CurrentNode("mKey").ToString() = Nothing Then
' Get the mKey value from the sitemap
metaKey.Content = SiteMap.CurrentNode("mKey")
Else
' Get the mKey value from the web.config
metaKey.Content = Me.mKey
End If
metaDesc.Name = "description"
' Verify that the mDesc value contains data
If Not SiteMap.CurrentNode("mDesc").ToString() = Nothing Then
' Get the mDesc value from the sitemap
metaDesc.Content = SiteMap.CurrentNode("mDesc")
Else
' Get the mDesc value from the web.config
metaDesc.Content = Me.mDesc
End If
' Verify that the Description value contains data
If Not SiteMap.CurrentNode.Description = Nothing Then
' Get the Description value from the sitemap
head.Title = SiteMap.CurrentNode.Description
Else
' Get the Description value from the web.config
head.Title = Me.mTitle
End If
Else
' Get default data from the web.config
metaKey.Name = "keywords"
metaKey.Content = Me.mKey
metaDesc.Name = "description"
metaDesc.Content = Me.mDesc
head.Title = Me.mTitle
End If
' Add the controls to the page's head
head.Controls.AddAt(1, New LiteralControl(vbCrLf))
head.Controls.AddAt(2, metaKey)
head.Controls.AddAt(3, New LiteralControl(vbCrLf))
head.Controls.AddAt(4, metaDesc)
head.Controls.AddAt(5, New LiteralControl(vbCrLf))
End Sub
End Class
C# Master Page CodeBehind
public partial class Site : System.Web.UI.MasterPage
{
protected Paradoxal.PageObjects MyPageLevel = new Paradoxal.PageObjects();
protected void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack) {
this.MyPageLevel.GetMetaTags(this.Page);
}
}
}
C# PageObjects class
#region "=================== Imports ====================="
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.Security;
using System.Security.Cryptography;
using System.Security.Principal;
#endregion
/// <summary>
/// Provides methods and properties which encapsulate character,
/// data and page formatting
/// </summary>
/// <remarks></remarks>
public class PageObjects
{
#region "================ Global Variables ================"
protected string mTitle = ConfigurationManager.AppSettings("Meta.PageTitle");
protected string mDesc = ConfigurationManager.AppSettings("Meta.Description");
protected string mKey = ConfigurationManager.AppSettings("Meta.Keywords");
#endregion
/// <summary>
/// Gets meta keywords, meta description and the page title values from either
/// the web.sitemap or web.config file and adds them to a Master Page at
/// runtime
/// </summary>
/// <param name="MyPage">The page url (application name)</param>
/// <remarks>
/// Requires configuring the web.config and web.sitemap
/// <list type="bullet">
/// <item>
/// In the web.config: Add the Meta.PageTitle, Meta.Description, Meta.Keywords
/// keys under appSettings with the values being the default data for page
/// title, meta description and meta kewords
/// </item>
/// <item>
/// In the web.sitemap: Add the metaKeys and metaDesc names to the siteMapNode
/// with the values being the default data for meta description and meta
/// keywords
/// </item>
/// </list>
/// </remarks>
/// <example>This sample shows how in a Master pages codebehind to call
/// the <c>GetMetaTags()</c> method:
/// <code>
/// Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
/// If Not Page.IsPostBack Then
/// Dim MyPageLevel As Paradoxal.PageObjects = New Paradoxal.PageObjects()
/// Me.MyPageLevel.GetMetaTags(Me.Page)
/// End If
/// End Sub
/// </code>
/// </example>
/// <history>
/// [Duane Urban] 08/20/2009 Created
/// </history>
public void GetMetaTags(Page MyPage)
{
// Declare our variables
HtmlHead head = MyPage.Master.Page.Header;
HtmlMeta metaKey = new HtmlMeta();
HtmlMeta metaDesc = new HtmlMeta();
// Check for a current node in the web.sitemap
if (SiteMap.CurrentNode != null) {
metaKey.Name = "keywords";
// Verify that the mKey value contains data
if (!(SiteMap.CurrentNode("mKey").ToString() == null)) {
// Get the mKey value from the sitemap
metaKey.Content = SiteMap.CurrentNode("mKey");
}
else {
// Get the mKey value from the web.config
metaKey.Content = this.mKey;
}
metaDesc.Name = "description";
// Verify that the mDesc value contains data
if (!(SiteMap.CurrentNode("mDesc").ToString() == null)) {
// Get the mDesc value from the sitemap
metaDesc.Content = SiteMap.CurrentNode("mDesc");
}
else {
// Get the mDesc value from the web.config
metaDesc.Content = this.mDesc;
}
// Verify that the Description value contains data
if (!(SiteMap.CurrentNode.Description == null)) {
// Get the Description value from the sitemap
head.Title = SiteMap.CurrentNode.Description;
}
else {
// Get the Description value from the web.config
head.Title = this.mTitle;
}
}
else {
// Get default data from the web.config
metaKey.Name = "keywords";
metaKey.Content = this.mKey;
metaDesc.Name = "description";
metaDesc.Content = this.mDesc;
head.Title = this.mTitle;
}
// Add the controls to the page's head
head.Controls.AddAt(1, new LiteralControl(Constants.vbCrLf));
head.Controls.AddAt(2, metaKey);
head.Controls.AddAt(3, new LiteralControl(Constants.vbCrLf));
head.Controls.AddAt(4, metaDesc);
head.Controls.AddAt(5, new LiteralControl(Constants.vbCrLf));
}
}