ASP.NET

Set an ASPX page's title, meta description and keywords dynamically

ASP.NET · · Published 2026-10-06

Pages that display database content, such as a product or an article, need a title and description built from that content. Since .NET 4, Web Forms makes this a one-liner per tag, as long as the page has a <head runat="server">.

Requirement: a server-side head

<head runat="server">
    <title></title>
</head>

Without runat="server", Page.Header is null and the properties below have nothing to write into. With master pages, the <head runat="server"> lives in the master page, and content pages can still set the values.

Title, description and keywords

protected void Page_Load(object sender, EventArgs e)
{
    if (!int.TryParse(Request.QueryString["id"], out int id)) { ShowNotFound(); return; }

    Product p = ProductRepository.Find(id);
    if (p == null) { ShowNotFound(); return; }

    Page.Title = p.Name + " | Example Shop";
    Page.MetaDescription = Shorten(p.Summary, 155);
    Page.MetaKeywords = string.Join(", ", p.Tags); // optional, see below
}

private static string Shorten(string text, int max)
{
    if (string.IsNullOrEmpty(text) || text.Length <= max) return text ?? "";
    int cut = text.LastIndexOf(' ', max);
    return text.Substring(0, cut > 0 ? cut : max) + "…";
}

private void ShowNotFound()
{
    Response.StatusCode = 404;
    Page.Title = "Product not found";
}

ASP.NET HTML-encodes these values when it renders them, so quotes or angle brackets in a product name cannot break the markup. MetaDescription and MetaKeywords render <meta name="description"> and <meta name="keywords">; if the markup already contains such tags, the property replaces their content.

You can also set them declaratively in the @Page directive: <%@ Page Title="Contact" MetaDescription="How to reach us" %>.

Other tags: canonical, Open Graph, robots

HtmlMeta and HtmlLink controls add anything else:

using System.Web.UI.HtmlControls;

var canonical = new HtmlLink { Href = "https://www.example.com/products/" + p.Slug };
canonical.Attributes["rel"] = "canonical";
Page.Header.Controls.Add(canonical);

var ogTitle = new HtmlMeta();
ogTitle.Attributes["property"] = "og:title";  // Open Graph uses "property", not "name"
ogTitle.Content = p.Name;
Page.Header.Controls.Add(ogTitle);

if (p.IsHidden)
{
    Page.Header.Controls.Add(new HtmlMeta { Name = "robots", Content = "noindex" });
}

Adding controls to the header fails with "The Controls collection cannot be modified because the control contains code blocks" if the <head> contains <%= … %> expressions. Replace them with data-binding expressions (<%# … %>) and call Page.Header.DataBind(), or move scripts out of the head.

What search engines use

Official documentation