当前位置: 首页 > news >正文

为 ASP.NET Core 程序制作 URL 的 301/302 跳转

如果你有一些需要重定向网页 URL 的情况,可以返回 HTTP 状态码 301/302 告诉浏览器或者搜索引擎访问新的 URL。本文描述如何在 ASP.NET Core 中进行重定向。


本文内容

    • HTTP 状态码 301/302
    • ASP.NET Core
    • 重定向中间件
    • 重定向
    • 小心缓存

HTTP 状态码 301/302

301 表示“Moved Permanently”,即永久移动。通过返回此状态码可以告知浏览器或者搜索引擎此 URL 已经永久移动到了新的 URL 地址。搜索引擎会使用新的 URL 来更新自己的搜索结果,而浏览器会将此 URL 重定向缓存起来,下次访问的时候直接使用新的 URL 来访问。

302 表示“Found”,发现;原始描述为“Moved Temporarily”,即临时移动。通过返回此状态码可以告知浏览器或者搜索引擎此 URL 临时移动到了新的 URL 地址。搜索引擎会使用此新的 URL 来抓取页面的内容但不会更新此 URL,而浏览器会访问新的 URL 但不会缓存此 URL 重定向。

还有其他的重定向的 HTTP 状态码:

  • 303 See Other
  • 307 Temporary Redirect
  • 308 Permanent Redirect

301/302 本来设计为移动资源的时候保持方法不变,但各大浏览器在实现的时候对于 POST 方法,有的实现成了 GET 方法,有的实现成了 POST 方法。于是在后来的 HTTP 标准中将浏览器的错误实现变成了标准,301 和 302 方法要求使用 GET 方法重定向。不过由于历史原因无法保证一定是改用 GET 方法,所以增加了 303 状态码要求一定使用 GET 方法重定向。随后将原来本应该正确实现的 301 和 302 重新定义成 307 和 308 状态码,要求重定向时不允许修改方法。

ASP.NET Core

ASP.NET Core 的 Blazor 框架生成的页面在路由的时候是不识别 .html 后缀的,而带有 .html 后缀的 URL 会被识别为静态文件。于是,如果创建了一个空的 Blazor 应用,当访问 https://blog.walterlv.com/post/redirect-middleware-for-asp-dotnet.html 网址的时候,会返回 404 Not Found,而不是路由到我的博客页面。

如果我们将此 URL 重定向到不带后缀的 URL,则可以被 Blazor 框架识别并正确显示对应的博客页面。

我们有两个不同的方式来实现这种 URL 的重定向:

  1. 做一个重定向的控制器 Controller,然后在控制器中重定向所有的博客页面
  2. 做一个重定向的中间件,对所有包含 .html 后缀的博客页面重定向到没有 .html 后缀的博客页面

不过,写一个 Controller 会要求这个 Controller 路由到几乎所有的 URL 上,对其他功能很不利,所以中间件是最合适的方式。

重定向中间件

    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
++          app.UseAutoRemoveHtmlExtension();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
            app.UseStaticFiles();
        }
    }

Startup 类的 Configure 方法中可以添加中间件。为了实现去掉 .html 后缀的中间件,我添加了一个自己的扩展方法 UseAutoRemoveHtmlExtension

/// <summary>
/// 自动移除所有的 .html 后缀,并永久重定向到没有 .html 后缀的网页。
/// </summary>
/// <param name="app"><see cref="IApplicationBuilder"/>。</param>
/// <returns><see cref="IApplicationBuilder"/>。</returns>
public static IApplicationBuilder UseAutoRemoveHtmlExtension(this IApplicationBuilder app) => app.Use(async (context, next) =>
{
    var urlPath = context.Request.Path.HasValue
        ? context.Request.Path.Value
        : "";
    if (urlPath.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
    {
        // 去掉 .html 后缀
        var url = urlPath[0..^5];
        context.Response.Redirect(url);
        context.Response.StatusCode = 301;
        return;
    }
    await next().ConfigureAwait(false);
});

实现自己的中间件实际上直接调用 IApplicationBuilder 中的 Use 方法即可,传入一个委托用来在 URL 处理过程中添加一个步骤。

两个参数,context 中包含了本次请求的一些上下文,包括域名、URL 路径,返回的 HTTP 状态码。调用 context.Response.Redirect 方法可以进行 302 跳转。如果需要改成 301 跳转,则直接设置 context.Response.StatusCode 方法即可。

接下来,对于不需要重定向的网址,我们直接交给后面的中间件处理,调用 await next()

重定向

如果你希望做其他种类的跳转,你也可以添加新的中间件,比如:

  1. 将 HTTP 重定向到 HTTPS(谷歌建议使用 301 跳转)
  2. 你可以在打开某个网页之前要求登录,于是做一个 302 跳转到登录页面;
  3. 你可以将一些已经过时的网页进行 301 跳转到新的网页;
    • 比如我将一些之前不太规范的博客 URL 重定向到统一的格式;
  4. 你可以在迁移服务的时候临时做一个 302 跳转。

小心缓存

请注意,301 重定向会被浏览器缓存。也就是说如果你重定向到了一个错误的网址,那么再次访问的话浏览器将直接访问这个错误的网址。如果希望浏览器停止重定向到这个错误的网址,需要清除浏览器的缓存。所以使用 301 的时候需要谨慎一些。


参考资料

  • HTTP 302 - 维基百科,自由的百科全书

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 使用 Frp 为你的 Web 服务添加 https 支持
  • 全民 https!使用 FreeSSL 申请免费的 https 证书
  • 如何设置 ASP.NET Core 程序监听的 IP 和端口
  • 收集的 Linux VPS 在线重装系统脚本
  • Linux 系统根目录下的文件夹
  • 修复 Windows 10 设置界面里面混乱的语言翻译
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • 用命令行执行 .NET 单元测试时,如何仅执行符合某些条件的单元测试
  • WPF 中如何绑定附加属性?XAML 中记得加括号,C# 中记得不能用字符串
  • VSCode:当匹配到结果时,如何一次性全部选中操作(复制 删除)?
  • Unity3D 入门:安装 Unity3D 并配置与 Visual Studio 的协作开发环境
  • 在 Visual Studio 2019 (16.5) 中查看托管线程正在等待的锁被哪个线程占用
  • 将 Windows Terminal 作为外部工具集成到其他工具 程序 代码中
  • Unity3D 入门:在 Visual Studio 里使用 Visual Studio Tools for Unity 全套工具
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Bootstrap JS插件Alert源码分析
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • ES6系统学习----从Apollo Client看解构赋值
  • java正则表式的使用
  • linux安装openssl、swoole等扩展的具体步骤
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Python - 闭包Closure
  • Vue组件定义
  • yii2权限控制rbac之rule详细讲解
  • 讲清楚之javascript作用域
  • 每天一个设计模式之命令模式
  • 那些年我们用过的显示性能指标
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • elasticsearch-head插件安装
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #android不同版本废弃api,新api。
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET CF命令行调试器MDbg入门(一)
  • .NET Core 版本不支持的问题
  • .NET Micro Framework初体验(二)
  • .NET 反射的使用
  • .NET连接MongoDB数据库实例教程
  • .NET上SQLite的连接
  • [17]JAVAEE-HTTP协议
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [ai笔记4] 将AI工具场景化,应用于生活和工作
  • [android学习笔记]学习jni编程
  • [AutoSar]BSW_OS 02 Autosar OS_STACK
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [c++] 单例模式 + cyberrt TimingWheel 单例分析
  • [CentOs7]搭建ftp服务器(2)——添加用户