You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Razor Page中用标题替代ID显示在URL中?

在.NET 6 Razor Pages中实现SEO友好的博客详情URL(替换ID为标题)

要把博客详情页的URL从/blog-details/4改成包含文章标题的SEO友好格式,比如/blog-details/wo-de-di-yi-pian-net-bo-ke,可以按以下步骤操作:

1. 给文章添加Slug字段

首先在博客文章的数据模型(比如BlogPost)里新增Slug字段,类型为string,用来存储处理后的URL友好标题。这个字段需要满足:

  • 仅包含小写字母、数字、连字符(-)
  • 全局唯一(避免不同文章URL冲突)
  • 能对应到唯一一篇文章

新增文章时可以自动生成Slug,也允许后台手动调整(比如优化关键词)。

2. 修改Razor Page的路由规则

找到博客详情页(比如BlogDetails.cshtml),在页面顶部修改路由模板:

@page "/blog-details/{slug}"

或者在页面模型类上通过[PageRoute]属性配置:

[PageRoute("/blog-details/{slug}")]
public class BlogDetailsModel : PageModel
{
    // ... 模型逻辑
}

3. 调整详情页的查询逻辑

原来的OnGet方法通过id查询文章,现在改成用slug查询:

private readonly AppDbContext _context;

public BlogDetailsModel(AppDbContext context)
{
    _context = context;
}

public BlogPost BlogPost { get; set; }

public async Task<IActionResult> OnGetAsync(string slug)
{
    if (string.IsNullOrWhiteSpace(slug))
    {
        return NotFound();
    }

    BlogPost = await _context.BlogPosts
        .FirstOrDefaultAsync(p => p.Slug == slug);

    if (BlogPost == null)
    {
        return NotFound();
    }

    return Page();
}

4. 更新文章列表页的链接

在文章列表页(比如BlogList.cshtml),把原来指向详情页的链接从id参数换成slug参数:

@foreach (var post in Model.BlogPosts)
{
    <a asp-page="/BlogDetails" asp-route-slug="@post.Slug">@post.Title</a>
}

如果用代码生成URL,就改成:

var detailUrl = Url.Page("/BlogDetails", new { slug = post.Slug });

5. 实现Slug自动生成逻辑

写一个工具方法把文章标题转换成符合要求的Slug,示例代码:

using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;

public static class SlugHelper
{
    public static string GenerateSlug(string title)
    {
        // 移除重音符号
        var normalizedTitle = title.Normalize(NormalizationForm.FormD);
        var sb = new StringBuilder();
        
        foreach (var c in normalizedTitle)
        {
            var category = CharUnicodeInfo.GetUnicodeCategory(c);
            if (category != UnicodeCategory.NonSpacingMark)
            {
                sb.Append(c);
            }
        }
        
        // 移除特殊字符,替换空格为连字符,转小写
        var slug = sb.ToString().Normalize(NormalizationForm.FormC);
        slug = Regex.Replace(slug, @"[^a-zA-Z0-9\s-]", "");
        slug = Regex.Replace(slug, @"\s+", "-").ToLower();
        slug = Regex.Replace(slug, @"-+", "-").Trim('-');
        
        return slug;
    }
}

生成Slug后要检查数据库是否已存在相同值,如果存在可以追加数字(比如my-first-post-1)来保证唯一性。

6. 可选:兼容旧ID路由(避免404)

如果之前的ID格式URL已经被搜索引擎收录,为了不影响SEO,可以添加兼容逻辑:

  • 修改路由模板支持两种格式:
    @page "/blog-details/{identifier}"
    
  • 调整OnGet方法判断参数是ID还是Slug,并做301重定向(传递SEO权重):
    public async Task<IActionResult> OnGetAsync(string identifier)
    {
      BlogPost post = null;
      
      if (int.TryParse(identifier, out int id))
      {
          post = await _context.BlogPosts.FirstOrDefaultAsync(p => p.Id == id);
      }
      else
      {
          post = await _context.BlogPosts.FirstOrDefaultAsync(p => p.Slug == identifier);
      }
    
      if (post == null)
      {
          return NotFound();
      }
    
      // 如果是通过ID访问,301重定向到Slug URL
      if (int.TryParse(identifier, out _))
      {
          return RedirectToPage("/BlogDetails", new { slug = post.Slug }, permanent: true);
      }
    
      BlogPost = post;
      return Page();
    }
    

内容的提问来源于stack exchange,提问作者Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:17:30