# 为什么你在Google上找到这个?

<!--category-- ASP.NET Core, SEO -->
<datetime class="hidden">2025-11-26T14:00</datetime>

I' @% 运行这个博客已有一段时间了@,{} 正在撰写关于ASP=.NET Core,}实体框架的详细技术文章,

[TOC]

# 与Google一模一样的每页问题

当Google爬行你的网站,时,它会看到几个关键信号 来理解每页关于什么的“.” 我给Googgle发送了每个页面相同的信号 “.”

## 吸烟的枪声 :

在这里,M'什么我的 `_Layout.cshtml` 看起来像:

```html
<meta name="description" content="Scott Galloway is a lead developer and software engineer with a passion for building web applications.">
<meta property="og:description" content="Scott Galloway is a lead developer and software engineer with a passion for building web applications.">
```

同一描述我的文章, [ASP .NET核心背景服务](/blog/background-services-in-aspnetcore-part1)与我的主页相同描述 我的深潜 [RAG 建筑结构](/blog/rag-architecture){\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}同样的描述...

Google用相同的描述阅读“200+”页面, 认为这个网站有重复的内容问题@"或“MS K3”这个网站并不关心提供有用的信息 @.",

## 缺失的罐体 URL

我有一个多语种博客,

- `/blog/my-article` -=YTET -伊甸园字幕组=- 翻译:
- `/blog/my-article/fr` -=YTET -伊甸园字幕组=- 翻译:
- `/blog/my-article/de` {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}"德国"

如果没有 Canonical URLs,Google 可能会认为这些内容是重复的内容\ , 将 SEO 值冲淡到多个URL, 而不是将其合并在主页@.

## 无结构数据

Google' @%s 搜索结果可以显示富有的片段@ -}作者信息 *,发布日期*\,文章预览@.}但只有您告诉谷歌使用此数据时 [JSON-LD结构数据](https://developers.google.com/search/docs/appearance/structured-data/article)我当时是' T.

## 静态社会形象

每页共享的页面相同 `og:image`这直接影响到谷歌排名 , 当社会媒体上分享文章时,

# 定法

## 1. 动态元描述

第一个修正是制作布局支持动态描述, 并配有明智的后退@: @%

```html
@{
    var currentUrl = $"https://{Context.Request.Host}{Context.Request.Path}";
    var defaultDescription = "Scott Galloway is a lead developer and software engineer with a passion for building web applications.";
    var pageDescription = ViewBag.Description as string ?? defaultDescription;
}

<!-- Canonical URL -->
<link rel="canonical" href="@currentUrl" />

<!-- Facebook Meta Tags -->
<meta property="og:url" content="@currentUrl">
<meta property="og:type" content="@(ViewBag.OgType ?? "website")">
<meta property="og:title" content="@ViewBag.Title">
<meta property="og:description" content="@pageDescription">
<meta property="og:site_name" content="mostlylucid" />

<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="@ViewBag.Title">
<meta name="twitter:description" content="@pageDescription">

<!-- Meta Description -->
<meta name="description" content="@pageDescription" />

<!-- Article metadata for blog posts -->
@if (ViewBag.PublishedDate != null)
{
    <meta property="article:published_time" content="@(((DateTime)ViewBag.PublishedDate).ToString("yyyy-MM-ddTHH:mm:ssZ"))" />
    <meta property="article:author" content="Scott Galloway" />
}
@if (ViewBag.Categories != null)
{
    foreach (var category in ViewBag.Categories)
    {
        <meta property="article:tag" content="@category" />
    }
}
```

现在布局上写着 `ViewBag.Description` 如果设定“, ” 返回默认的“ .” , 则可以自动设置当前网页“ URL” 的 Canonical 網址 。

## @2._Auto@-}博客文章的创举描述

每个博客文章现在都从我的首个#155字元中, `Post.cshtml`:

```html
@using Mostlylucid.Shared.Helpers
@model Mostlylucid.Models.Blog.BlogPostViewModel

@{
    Layout = "_Layout";
    ViewBag.Title = $"{Model.Title} ({Model.Language.ConvertCodeToLanguage()})";

    // Generate description from plain text content (first 155 chars, truncate at word boundary)
    var plainText = Model.PlainTextContent ?? "";
    var description = plainText.Length > 155
        ? plainText.Substring(0, plainText.LastIndexOf(' ', 155)) + "..."
        : plainText;
    description = description.Replace("\n", " ").Replace("\r", "").Trim();
    ViewBag.Description = description;

    // Set article metadata
    ViewBag.OgType = "article";
    ViewBag.PublishedDate = Model.PublishedDate;
    ViewBag.Categories = Model.Categories;

    // Build canonical URL (without language suffix for English)
    var canonicalUrl = Model.Language == "en"
        ? $"https://{Context.Request.Host}/blog/{Model.Slug}"
        : $"https://{Context.Request.Host}/blog/{Model.Slug}/{Model.Language}";
}
```

关键点在这里 @: @%

1. **以单词边界进行排行** -# 我们找到在 @ MS K1}字符前的最后一个空格, 以避免将单词切换为一半 。
2. **换行新线** - Meta 描述应该是单一@ MS K1line
3. **设置套设 `og:type` 至 @"_article_"** @-_ 告诉社交平台这是篇文章#,}不是通用网页
4. **通过文章元数据** @- 已公布的日期和分类流向布局

## -=YTET -伊甸园字幕组=- 翻译:

这是富有的片段的大块 . 在您的博客文章视图中添加 JSON-LD脚本块@:

```html
<!-- JSON-LD Structured Data for Blog Post -->
<script type="application/ld+json">
{
    "@@context": "https://schema.org",
    "@@type": "BlogPosting",
    "headline": "@Model.Title",
    "description": "@description",
    "datePublished": "@Model.PublishedDate.ToString("yyyy-MM-ddTHH:mm:ssZ")",
    @if (Model.UpdatedDate.HasValue)
    {
        @:"dateModified": "@Model.UpdatedDate.Value.ToString("yyyy-MM-ddTHH:mm:ssZ")",
    }
    "author": {
        "@@type": "Person",
        "name": "Scott Galloway",
        "url": "https://mostlylucid.net/blog/aboutme"
    },
    "publisher": {
        "@@type": "Organization",
        "name": "mostlylucid",
        "logo": {
            "@@type": "ImageObject",
            "url": "https://mostlylucid.net/img/logo.svg"
        }
    },
    "mainEntityOfPage": {
        "@@type": "WebPage",
        "@@id": "@canonicalUrl"
    },
    "wordCount": @Model.WordCount,
    "inLanguage": "@Model.Language",
    "keywords": "@string.Join(", ", Model.Categories)",
    "image": "https://mostlylucid.net/img/social2.jpg"
}
</script>
```

注注: `@@` 逃离 `@` 在 Razor 视图中显示的振动符号@ - JSON-LD用途 `@context` 和 `@type` 否则将被解释为Razor语法.

此结构化数据告诉 Google:

- **这是哪类内容** @(_Blogpossting_)#
- **是谁写的** @(_Person 拥有一个 URL 学习更多@)}
- **出版和修改时**
- **A. 它所涵盖的专题** @(_}來自類別的關鍵字@)_%
- **持续了多久** “( 字数”“Count) ”
- **使用何种语言**

Google 可以使用此功能在搜索结果中显示丰富的片段@ , @ 包括作者信息@ MPK1_ 发布日期 @ MS K2} 和更多.\ {

## 4. 关键页面的独特描述

请不要忘了您的静态页面@. @ 每个人应该有一个独有的# ,}相关描述:{

```html
<!-- Home page -->
@{
    ViewBag.Title = "mostlylucid- Scott Galloway's Developer Blog";
    ViewBag.Description = "Technical blog covering ASP.NET Core, C#, Entity Framework, HTMX, Docker, and modern web development. Practical tutorials, NuGet packages, and open source projects.";
}

<!-- Blog index -->
@{
    ViewBag.Title = "Blog Posts";
    ViewBag.Description = "Technical articles on ASP.NET Core, C#, Entity Framework, Docker, and modern web development. Practical tutorials and real-world examples from a lead developer.";
}

<!-- Contact page -->
@{
    ViewBag.Title = "Contact Scott Galloway";
    ViewBag.Description = "Get in touch with Scott Galloway. Questions about ASP.NET Core, C#, web development, or collaboration opportunities? Send me a message.";
}

<!-- Search page -->
@{
    ViewBag.Title = "Search Results";
    ViewBag.Description = "Search through technical articles on ASP.NET Core, C#, Entity Framework, and web development. Find tutorials, guides, and solutions.";
}
```

# 其他SEO基本要求

## 粒子图

您需要一个站点映射@ . @ Here'}(这里是简单的控制器), 它能生成一个动态=:}*

```csharp
public class SiteMapController(
    IBlogViewService blogViewService,
    IHttpContextAccessor httpContextAccessor) : Controller
{
    [HttpGet]
    [ResponseCache(Duration = 43200)] // Cache for 12 hours
    public async Task<IActionResult> Index()
    {
        var pages = await blogViewService.GetPosts();
        var siteUrl = $"https://{httpContextAccessor.HttpContext?.Request.Host}";

        XNamespace sitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";

        var feed = new XDocument(
            new XDeclaration("1.0", "utf-8", null),
            new XElement(sitemap + "urlset",
                from page in pages
                select new XElement(sitemap + "url",
                    new XElement(sitemap + "loc", $"{siteUrl}/blog/{page.Slug}"),
                    new XElement(sitemap + "lastmod", page.PublishedDate.ToString("yyyy-MM-dd")),
                    new XElement(sitemap + "changefreq", "weekly"),
                    new XElement(sitemap + "priority", "0.8")
                )
            )
        );

        return Content(feed.ToString(), "text/xml");
    }
}
```

注册路线@: @%

```csharp
app.MapControllerRoute(
    name: "sitemap",
    pattern: "sitemap.xml",
    defaults: new { controller = "SiteMap", action = "Index" });
```

## 机器人@. @% txt

告诉搜索引擎您的站点映射的位置和要爬到什么位置@: @%

```csharp
app.MapGet("/robots.txt", async context =>
{
    var siteUrl = $"https://{context.Request.Host}";
    var robotsTxt = $"""
        User-agent: *
        Allow: /

        Sitemap: {siteUrl}/sitemap.xml
        """;

    context.Response.ContentType = "text/plain";
    await context.Response.WriteAsync(robotsTxt);
});
```

## RSS 种子服务

许多开发商使用 RSS Reader@. 拥有RSS feed 也帮助发现 < : {

```html
<link rel="alternate" type="application/atom+xml"
      title="RSS Feed for mostlylucid.net"
      href="https://mostlylucid.net/rss" />
```

# 关于图像 @ ?

您可能想知道如何为每个日志“. ” 生成独特的 OG 图像, 对于一个技术博客“ , ” It' 可能不值得为此付出努力 “. ” 您的交通来自 @: }

- **谷歌搜索** @-}描述比图像重要得多
- **RSS 接口** @ -_无图像
- **黑客新闻 #/#Reddit** 缩略图几乎看不见
- **直接链接** 分享網址的开发商@- @%

在Facebook和Twitter上竞相点击的营销网页上,

如果您想要生成它们 @ , 您可以使用 [图像共享](https://docs.sixlabors.com/articles/imagesharp/) @ ( @ i 已用于图像处理@ MS K1} 以在模板上覆盖文本@ MPK2\ {

```csharp
public async Task<string> GenerateOgImage(string title, string slug)
{
    using var image = await Image.LoadAsync("wwwroot/img/og-template.png");

    var font = SystemFonts.CreateFont("Arial", 48, FontStyle.Bold);

    image.Mutate(x => x.DrawText(
        new RichTextOptions(font)
        {
            Origin = new PointF(50, 200),
            WrappingLength = 1100
        },
        title,
        Color.White));

    var outputPath = $"wwwroot/og/{slug}.png";
    await image.SaveAsPngAsync(outputPath);
    return $"/og/{slug}.png";
}
```

但对于一个技术博客 '? ship'来说 你得到了什么?

# 测试您的 SEO

## Google Rich 成果测试

使用 [Google '_ZZ丰硕的結果測試](https://search.google.com/test/rich-results) 来验证您的结构化数据@.粘贴一个 URL, 它会告诉您 您的 JSON-LD 是有效的吗?

## 查看页面源

最简单的测试@- 查看页面源,并检查\:

- 是 `<meta name="description">` 此页面的独特性@ ? @%
- 是否有 `<link rel="canonical">`?
- 是否有 `<script type="application/ld+json">` 砖块@? @%

## Google 搜索控制台

在部署“,”后, 提交您的站点映射到 [Google 搜索控制台](https://search.google.com/search-console). 您也可以使用 URL 检查工具来查看 Google 如何看待您的页面, 并请求 re @ MS K1 indexing @.}

# 摘要摘要

修正是直截了当的“:”

{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}
|---------|-----|
| 静态元说明 @|动态 `ViewBag.Description` 以自动@- @% 生成内容@ |
@ |_ no canonical URL {|} 已添加 `<link rel="canonical">` 到布局@| @%
|没有结构化数据 `BlogPosting` @|+#每篇文章都有计划。
缺少文章元数据@| @% `article:published_time`, `article:author`, `article:tag` 元标记 @ | @%
| 静态页面描述 @| Home@, Blog, 联系人{, 搜索网页_|

关键洞察力 : **谷歌可以读懂你的心**如果每页的描述都相同, Google根本不知道 是什么使得每一页的独特和宝贵

让Google数周后重新访问您的网站@, @你应该看到改进: @.#SEO是一个漫长的游戏_,}但是这些基本原理是基础,

# 继续阅读

- [Google's SEO 启动指南](https://developers.google.com/search/docs/fundamentals/seo-starter-guide)
- [Schema.org 博客插图](https://schema.org/BlogPosting)
- [开放图表程序](https://ogp.me/)
- [Google Rich 成果测试](https://search.google.com/test/rich-results)
- [Google 搜索控制台](https://search.google.com/search-console)