<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Jason Conway : ContentPlaceHolders</title><link>http://weblogs.asp.net/jasonconway/archive/tags/ContentPlaceHolders/default.aspx</link><description>Tags: ContentPlaceHolders</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Meta Tags in ASP.NET using MasterPage and ContentPlaceHolders</title><link>http://weblogs.asp.net/jasonconway/archive/2008/03/24/meta-tags-in-asp-net-using-masterpage-and-contentplaceholders.aspx</link><pubDate>Mon, 24 Mar 2008 15:19:50 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6019413</guid><dc:creator>Jason Conway</dc:creator><author>Jason Conway</author><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/jasonconway/rsscomments.aspx?PostID=6019413</wfw:commentRss><comments>http://weblogs.asp.net/jasonconway/archive/2008/03/24/meta-tags-in-asp-net-using-masterpage-and-contentplaceholders.aspx#comments</comments><description>&lt;p&gt;Having META tags like Description and Keywords on the .aspx pages of our sites is very important.&amp;#160; It is also important that the content of the tags be easily added and/or updated.&amp;#160; Most online help will have you instantiate an &lt;a title="HtmlMeta Class on MSDN" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.htmlcontrols.htmlmeta.aspx" target="_blank"&gt;HtmlMeta&lt;/a&gt; class or write tags by implementing some variance of either:&lt;/p&gt;  &lt;ul style="list-style-type: none"&gt;   &lt;li&gt;&lt;u&gt;Option 1&lt;/u&gt; - create a base Page class with methods or properties and create an external persistence store for META content &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Option 2&lt;/u&gt; - create a base Page class with virtual methods or properties and override those on the deriving page &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Option 3&lt;/u&gt; - create an Interface or abstract class with methods or properties that the deriving page will employ &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Option 4&lt;/u&gt; - use a third-party component or write a control &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Option 5&lt;/u&gt; - on &lt;strong&gt;every&lt;/strong&gt; page, write or use existing implementation to create META tags &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;While my solution also uses the &lt;a title="HtmlMeta Class on MSDN" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.htmlcontrols.htmlmeta.aspx" target="_blank"&gt;HtmlMeta&lt;/a&gt; class, it differs in architecture and uses the following guidelines:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;create&lt;/strong&gt; META tags on pages in a new or existing Site &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; base Page class, abstract class, or Interface that all existing or new pages inherit &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;no &lt;/strong&gt;database or external store for persisting Tag content &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; controls or third-party components &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;just&lt;/strong&gt; want META content and not the actual tag creation on every page &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;must&lt;/strong&gt; provide unique content per page &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;must&lt;/strong&gt; provide simple, maintainable content changes without recompile &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;must&lt;/strong&gt; provide the ability to change content with basic skills and without a special interface &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In other words, I did not want to create a base Page, Interface, control, or third-party component that every single one of the pages in my site derives from or uses.&amp;#160; In addition having to ensure that any newly created pages inherited the base Page or implement some Interface is not as easily maintainable.&amp;#160; I can also use this solution on existing sites without having to worry about any Page inheritance issues.&lt;/p&gt;  &lt;p&gt;What better place to keep information about an .aspx file than right in the .aspx file?&amp;#160; Most markup resides in each .aspx file using ContentPlaceHolders anyway and when you create a new page, these ContentPlaceHolders will be included automatically!&amp;#160; For this post, I am only going to demonstrate adding META Description and Keywords tags, but this process can be applied to as many tags as you need.&amp;#160; One thing that is great about this approach, is that you will &lt;strong&gt;not&lt;/strong&gt; need a database or external file (like xml) to store META content...making the content very easily updated with a simple text editor (like Notepad) and no additional programming or database skills!&lt;/p&gt;  &lt;p class="downloadsection"&gt;&lt;a href="http://weblogs.asp.net/blogs/jasonconway/Meta%20Spike.zip"&gt;&lt;img src="http://weblogs.asp.net/blogs/jasonconway/download.gif" align="middle" border="0" /&gt;&lt;span&gt;DOWNLOAD - Meta Spike Files&lt;span&gt;&lt;/a&gt;&lt;/p&gt;      &lt;p&gt;This is how you do it (the source files are available for download above):&lt;/p&gt;      &lt;ol&gt;       &lt;li&gt;drop 2 ContentPlaceHolders in a MasterPage's head tag, 1 for Description and 1 for Keywords making sure to set&amp;#160; &lt;font face="Courier New"&gt;Visible=&amp;quot;false&amp;quot;&lt;/font&gt;&amp;#160; &lt;/li&gt;        &lt;li&gt;wire up &lt;a title="ContentPlaceHolder Load event" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.control.load.aspx"&gt;Load&lt;/a&gt; events on the ContentPlaceHolders and &lt;a title="Page LoadComplete event" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.page.loadcomplete.aspx" target="_blank"&gt;LoadComplete&lt;/a&gt; on the MasterPage's Page property &lt;/li&gt;        &lt;li&gt;implement handled events &lt;/li&gt;        &lt;li&gt;create or update existing page with new Description and Keywords ContentPlaceHolders add content to place holders &lt;/li&gt;        &lt;li&gt;view page in browser and inspect rendered source &lt;/li&gt;     &lt;/ol&gt;      &lt;h4 class="contentgroup"&gt;Step 1 - &lt;span&gt;default.master&lt;/span&gt;&lt;/h4&gt;      &lt;div class="csharpcode-wrapper"&gt;       &lt;pre class="csharpcode"&gt;&lt;span class="asp"&gt;&amp;lt;%@ Master Language=&amp;quot;C#&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot; CodeBehind=&amp;quot;Default.master.cs&amp;quot; Inherits=&amp;quot;MetaSpike.Default&amp;quot; %&amp;gt;&lt;/span&gt;

&lt;span class="kwrd"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;DOCTYPE&lt;/span&gt; &lt;span class="attr"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;PUBLIC&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;quot;-//W3C//DTD XHTML 1.0 Strict//EN&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MetaDescriptionHolder&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Visible&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MetaKeywordsHolder&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Visible&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;DefaultMasterForm&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MainContentHolder&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
    &lt;/div&gt;

    &lt;h4 class="contentgroup"&gt;Step 2 - &lt;span&gt;default.master.cs&lt;/span&gt;&lt;/h4&gt;

    &lt;div class="csharpcode-wrapper"&gt;
      &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MetaSpike {
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Default : MasterPage {

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnInit(EventArgs e) {
            &lt;span class="kwrd"&gt;base&lt;/span&gt;.OnInit(e);

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.MetaDescriptionHolder.Load += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(MetaDescriptionHolder_Load);
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.MetaKeywordsHolder.Load += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(MetaKeywordsHolder_Load);

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Page.LoadComplete += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(Page_LoadComplete);
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MetaDescriptionHolder_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MetaKeywordsHolder_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_LoadComplete(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }
    }
}&lt;/pre&gt;
    &lt;/div&gt;

    &lt;h4 class="contentgroup"&gt;Step 3 - &lt;span&gt;default.master.cs (continued)&lt;/span&gt;&lt;/h4&gt;

    &lt;div class="csharpcode-wrapper"&gt;
      &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.HtmlControls;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.WebControls;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MetaSpike {
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Default : MasterPage {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; HtmlMeta descriptionMeta;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; HtmlMeta keywordsMeta;

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnInit(EventArgs e) {
            &lt;span class="kwrd"&gt;base&lt;/span&gt;.OnInit(e);

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.MetaDescriptionHolder.Load += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(MetaDescriptionHolder_Load);
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.MetaKeywordsHolder.Load += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(MetaKeywordsHolder_Load);

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Page.LoadComplete += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(Page_LoadComplete);
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MetaDescriptionHolder_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; content = &lt;span class="kwrd"&gt;this&lt;/span&gt;.ParseHolderContent(&lt;span class="kwrd"&gt;this&lt;/span&gt;.MetaDescriptionHolder);

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(content)) &lt;span class="kwrd"&gt;return&lt;/span&gt;;

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.descriptionMeta = &lt;span class="kwrd"&gt;new&lt;/span&gt; HtmlMeta();
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.descriptionMeta.Name = &lt;span class="str"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;;
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.descriptionMeta.Content = content;
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MetaKeywordsHolder_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; content = &lt;span class="kwrd"&gt;this&lt;/span&gt;.ParseHolderContent(&lt;span class="kwrd"&gt;this&lt;/span&gt;.MetaKeywordsHolder);

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(content)) &lt;span class="kwrd"&gt;return&lt;/span&gt;;

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.keywordsMeta = &lt;span class="kwrd"&gt;new&lt;/span&gt; HtmlMeta();
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.keywordsMeta.Name = &lt;span class="str"&gt;&amp;quot;keywords&amp;quot;&lt;/span&gt;;
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.keywordsMeta.Content = content;
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_LoadComplete(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
            Page page = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; Page;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (page == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;return&lt;/span&gt;;

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.descriptionMeta != &lt;span class="kwrd"&gt;null&lt;/span&gt;) page.Header.Controls.Add(&lt;span class="kwrd"&gt;this&lt;/span&gt;.descriptionMeta);
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.keywordsMeta != &lt;span class="kwrd"&gt;null&lt;/span&gt;) page.Header.Controls.Add(&lt;span class="kwrd"&gt;this&lt;/span&gt;.keywordsMeta);
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ParseHolderContent(ContentPlaceHolder holder) {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (holder == &lt;span class="kwrd"&gt;null&lt;/span&gt; || holder.Controls.Count == 0) &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;

            LiteralControl control = holder.Controls[0] &lt;span class="kwrd"&gt;as&lt;/span&gt; LiteralControl;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (control == &lt;span class="kwrd"&gt;null&lt;/span&gt; || &lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(control.Text)) &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;

            &lt;span class="kwrd"&gt;return&lt;/span&gt; control.Text.Trim();
        }
    }
}&lt;/pre&gt;
    &lt;/div&gt;

    &lt;h4 class="contentgroup"&gt;Step 4 - &lt;span&gt;home.aspx&lt;/span&gt;&lt;/h4&gt;

    &lt;div class="csharpcode-wrapper"&gt;
      &lt;pre class="csharpcode"&gt;&lt;span class="asp"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; MasterPageFile=&amp;quot;~/Default.Master&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot; 
    CodeBehind=&amp;quot;Home.aspx.cs&amp;quot; Inherits=&amp;quot;MetaSpike.Home&amp;quot; Title=&amp;quot;Meta Spike Home&amp;quot; %&amp;gt;&lt;/span&gt;
    
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MetaDescription&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentPlaceHolderID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MetaDescriptionHolder&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;description goes here&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MetaKeywords&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentPlaceHolderID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MetaKeywordsHolder&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;keywords, .net, asp.net, meta&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MainContent&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentPlaceHolderID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MainContentHolder&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    this page now has a very simple mechanism for adding and updating meta tags! enjoy!
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
    &lt;/div&gt;

    &lt;h4 class="contentgroup"&gt;Step 5 - &lt;span&gt;view source rendered home.aspx&lt;/span&gt;&lt;/h4&gt;

    &lt;div class="csharpcode-wrapper"&gt;
      &lt;pre class="csharpcode"&gt;&lt;span&gt;&amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt; &lt;span&gt;html&lt;/span&gt; &lt;span&gt;PUBLIC&lt;/span&gt; &lt;span&gt;&amp;quot;-//W3C//DTD XHTML 1.0 Strict//EN&amp;quot;&lt;/span&gt; &lt;span&gt;&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;

&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;html&lt;/span&gt; &lt;span&gt;xmlns&lt;/span&gt;&lt;span&gt;=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt;
    &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
        &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;Meta Spike Home&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
        &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;=&amp;quot;description&amp;quot;&lt;/span&gt; &lt;span&gt;content&lt;/span&gt;&lt;span&gt;=&amp;quot;description goes here&amp;quot;&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
        &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;=&amp;quot;keywords&amp;quot;&lt;/span&gt; &lt;span&gt;content&lt;/span&gt;&lt;span&gt;=&amp;quot;keywords, .net, asp.net, meta&amp;quot;&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
    &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
    &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
        &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;form&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;=&amp;quot;aspnetForm&amp;quot;&lt;/span&gt; &lt;span&gt;method&lt;/span&gt;&lt;span&gt;=&amp;quot;post&amp;quot;&lt;/span&gt; &lt;span&gt;action&lt;/span&gt;&lt;span&gt;=&amp;quot;Home.aspx&amp;quot;&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;span&gt;=&amp;quot;aspnetForm&amp;quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
            &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
                &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt; &lt;span&gt;type&lt;/span&gt;&lt;span&gt;=&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;=&amp;quot;__VIEWSTATE&amp;quot;&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;span&gt;=&amp;quot;__VIEWSTATE&amp;quot;&lt;/span&gt;
 		   &lt;span&gt;value&lt;/span&gt;&lt;span&gt;=&amp;quot;/wEPDwUJNDMyNDU0NjAzZGQfTG4D56NhuIUPL9dxPlf1j85RXw==&amp;quot;&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
            &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
            &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;              
                this page now has a very simple mechanism for adding and updating meta tags! enjoy!
            &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
        &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
    &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
    &lt;/div&gt;

    &lt;p&gt;Some things to note:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;ContentPlaceHolders on the MasterPage have Visible set to false &lt;/li&gt;

      &lt;li&gt;the use of the Page's LoadComplete event instead of Load &lt;/li&gt;

      &lt;li&gt;only straight text in the Content tags on Home.aspx, ASP.NET will put that text into LiteralControls &lt;/li&gt;

      &lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; text in the Content tags on Home.aspx will result in &lt;strong&gt;no&lt;/strong&gt; META tags being output (good thing) &lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;This will prevent you from having to write more code than you need and leaves the actual content on the page itself (where it belongs).&amp;#160; In addition, you won't have a database or special component to worry about or pay for. &lt;/p&gt;

    &lt;p&gt;I hope you find this approach very simple, maintainable, and easily employed.&lt;/p&gt;

    &lt;p&gt;Jason Conway&lt;/p&gt;

    &lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fweblogs.asp.net%2fjasonconway%2farchive%2f2008%2f03%2f24%2fmeta-tags-in-asp-net-using-masterpage-and-contentplaceholders.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fweblogs.asp.net%2fjasonconway%2farchive%2f2008%2f03%2f24%2fmeta-tags-in-asp-net-using-masterpage-and-contentplaceholders.aspx" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6019413" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/jasonconway/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/ContentPlaceHolders/default.aspx">ContentPlaceHolders</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/MasterPage/default.aspx">MasterPage</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/Meta/default.aspx">Meta</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/Meta+Keywords/default.aspx">Meta Keywords</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/Meta+Tags/default.aspx">Meta Tags</category><category domain="http://weblogs.asp.net/jasonconway/archive/tags/Meta+Description/default.aspx">Meta Description</category></item></channel></rss>