如果你有一些需要重定向網頁 URL 的情況,可以返回 HTTP 狀態碼 301/302 告訴瀏覽器或者搜索引擎訪問新的 URL。本文描述如何在 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 的重定向:
- 做一個重定向的控制器
Controller
,然後在控制器中重定向所有的博客頁面 - 做一個重定向的中間件,對所有包含
.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()
。
重定向
如果你希望做其他種類的跳轉,你也可以添加新的中間件,比如:
- 將 HTTP 重定向到 HTTPS(谷歌建議使用 301 跳轉)
- 你可以在打開某個網頁之前要求登錄,於是做一個 302 跳轉到登錄頁面;
- 你可以將一些已經過時的網頁進行 301 跳轉到新的網頁;
- 比如我將一些之前不太規範的博客 URL 重定向到統一的格式;
- 你可以在遷移服務的時候臨時做一個 302 跳轉。
小心緩存
請注意,301 重定向會被瀏覽器緩存。也就是說如果你重定向到了一個錯誤的網址,那麼再次訪問的話瀏覽器將直接訪問這個錯誤的網址。如果希望瀏覽器停止重定向到這個錯誤的網址,需要清除瀏覽器的緩存。所以使用 301 的時候需要謹慎一些。
參考資料
我的博客會首發於 https://blog.walterlv.com/,而 CSDN 會從其中精選發佈,但是一旦發佈了就很少更新。
如果在博客看到有任何不懂的內容,歡迎交流。我搭建了 dotnet 職業技術學院 歡迎大家加入。
本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名呂毅(包含鏈接:https://walterlv.blog.csdn.net/),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫。