ASP.NET Open Graph Meta Tags: Add OG to Your .NET Web App

How to add og:title, og:image, og:description, and Twitter card meta tags in an ASP.NET Core app using Razor Pages, MVC views, or Blazor.

Razor Pages

Override the _Layout.cshtml head section to inject OG meta tags from your page model:

@* Pages/Shared/_Layout.cshtml — add to <head> *@
<title>@ViewData["Title"] | MySite</title>
<meta name="description" content="@ViewData["Description"]" />

@if (ViewData["OgTitle"] != null)
{
  <meta property="og:title"        content="@ViewData["OgTitle"]" />
  <meta property="og:description"  content="@ViewData["OgDescription"]" />
  <meta property="og:image"        content="@ViewData["OgImage"]" />
  <meta property="og:url"          content="@ViewData["CanonicalUrl"]" />
  <meta property="og:type"         content="article" />
  <meta name="twitter:card"        content="summary_large_image" />
  <meta name="twitter:title"       content="@ViewData["OgTitle"]" />
  <meta name="twitter:description" content="@ViewData["OgDescription"]" />
  <meta name="twitter:image"       content="@ViewData["OgImage"]" />
  <link rel="canonical" href="@ViewData["CanonicalUrl"]" />
}
// Pages/Blog/Post.cshtml.cs
public class PostModel : PageModel
{
    private readonly IPostService _posts;
    public PostModel(IPostService posts) => _posts = posts;

    [BindProperty(SupportsGet = true)]
    public string Slug { get; set; } = "";

    public Post? Post { get; set; }

    public async Task<IActionResult> OnGetAsync()
    {
        Post = await _posts.GetBySlugAsync(Slug);
        if (Post is null) return NotFound();

        ViewData["Title"]           = Post.Title;
        ViewData["Description"]     = Post.Excerpt;
        ViewData["OgTitle"]         = Post.Title;
        ViewData["OgDescription"]   = Post.Excerpt;
        ViewData["OgImage"]         = $"https://yourdomain.com/og/{Slug}.png";
        ViewData["CanonicalUrl"]    = $"https://yourdomain.com/blog/{Slug}";
        return Page();
    }
}

ASP.NET MVC (Controller + View)

// Controllers/BlogController.cs
public async Task<IActionResult> Post(string slug)
{
    var post = await _posts.GetBySlugAsync(slug);
    if (post is null) return NotFound();

    ViewBag.OgTitle       = post.Title;
    ViewBag.OgDescription = post.Excerpt;
    ViewBag.OgImage       = $"https://yourdomain.com/og/{slug}.png";
    ViewBag.CanonicalUrl  = $"https://yourdomain.com/blog/{slug}";
    return View(post);
}
@* Views/Shared/_Layout.cshtml — inside <head> *@
@if (ViewBag.OgTitle != null)
{
  <meta property="og:title"       content="@ViewBag.OgTitle" />
  <meta property="og:description" content="@ViewBag.OgDescription" />
  <meta property="og:image"       content="@ViewBag.OgImage" />
  <meta property="og:url"         content="@ViewBag.CanonicalUrl" />
  <meta property="og:type"        content="article" />
  <meta name="twitter:card"       content="summary_large_image" />
  <meta name="twitter:title"      content="@ViewBag.OgTitle" />
  <meta name="twitter:image"      content="@ViewBag.OgImage" />
  <link rel="canonical" href="@ViewBag.CanonicalUrl" />
}

Blazor Server-Side Rendering (SSR)

Blazor SSR (introduced in .NET 8) renders HTML on the server. Use the HeadContent component to inject OG meta tags:

@* Pages/BlogPost.razor *@
@page "/blog/{Slug}"
@inject IPostService Posts

<HeadContent>
  <title>@post?.Title | MySite</title>
  <meta name="description" content="@post?.Excerpt" />
  <meta property="og:title"       content="@post?.Title" />
  <meta property="og:description" content="@post?.Excerpt" />
  <meta property="og:image"       content="@($"https://yourdomain.com/og/{Slug}.png")" />
  <meta property="og:url"         content="@($"https://yourdomain.com/blog/{Slug}")" />
  <meta property="og:type"        content="article" />
  <meta name="twitter:card"       content="summary_large_image" />
  <meta name="twitter:title"      content="@post?.Title" />
  <meta name="twitter:image"      content="@($"https://yourdomain.com/og/{Slug}.png")" />
  <link rel="canonical" href="@($"https://yourdomain.com/blog/{Slug}")" />
</HeadContent>

@if (post is not null)
{
  <h1>@post.Title</h1>
  <p>@post.Excerpt</p>
}

@code {
  [Parameter] public string Slug { get; set; } = "";
  private Post? post;

  protected override async Task OnInitializedAsync()
  {
    post = await Posts.GetBySlugAsync(Slug);
  }
}

Note: Blazor WebAssembly (WASM) renders client-side — OG meta tags injected in WASM components won't be read by social scrapers. Use Blazor SSR, Razor Pages, or MVC for shareable pages.

Verify your ASP.NET OG tags

After deploying, paste your URL into OGFixer to preview how your .NET app's links appear on Twitter, LinkedIn, Slack, and Discord — and catch any OG tag issues before they go live.