ASP.NET Core 中的重定向

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET Core 中的重定向相关的知识,希望对你有一定的参考价值。

前言

在《如何使用ASP.NET Core Web API实现短链接服务》中,我们使用了Redirect方法返回跳转状态码:

[HttpGet("shortUrl")]
public IActionResult GetUrl(string shortUrl)

    var hashids = new Hashids("公众号My IO", minHashLength: 6);
    var id = hashids.Decode(shortUrl)[0];
        
    var urlData = db.Get(id);

    return Redirect(urlData.Url);

Redirect方法会生成RedirectResult类实例,而RedirectResult构造函数可以传入 2 个 bool 值:

public RedirectResult(string url, bool permanent, bool preserveMethod)

那么,为它们赋不同值,对跳转状态码有什么影响呢?

探究

查找这 2 个参数的引用,我们最终定位到RedirectResultExecutor.cs[1]:

if (result.PreserveMethod)

    context.HttpContext.Response.StatusCode = result.Permanent ?
        StatusCodes.Status308PermanentRedirect : StatusCodes.Status307TemporaryRedirect;
    context.HttpContext.Response.Headers.Location = destinationUrl;

else

    context.HttpContext.Response.Redirect(destinationUrl, result.Permanent);

PreserveMethod = true

使用 Location 标头返回需要跳转的 Url。

Permanent 决定状态码:

Permanent状态码说明
false307临时重定向响应状态码,表示请求的资源暂时地被移动到了响应的 Location 所指向的 URL 上。
true308永久重定向响应状态码,说明请求的资源已经被永久的移动到了由 Location 指定的 URL 上

PreserveMethod = false

执行Response.Redirect方法进行跳转,内部实现如下:

public override void Redirect(string location, bool permanent)

    if (permanent)
    
        HttpResponseFeature.StatusCode = 301;
    
    else
    
        HttpResponseFeature.StatusCode = 302;
    

    Headers.Location = location;

其实和PreserveMethod = true的逻辑是一样的,只是返回的状态码不同:

Permanent状态码说明
false302表明请求的资源被暂时的移动到了由该HTTP响应的响应头Location 指定的 URL 上。
true301表明请求的资源已经被移动到了由 Location 头部指定的url上,是固定的不会再改变

综上,ASP.NET Core 中的重定向一共包含 4 种:

状态码PreserveMethodPermanent生成RedirectResult方法
301falsetrueRedirectPermanent()
302falsefalseRedirect()
307truefalseRedirectPreserveMethod()
308truetrueRedirectPermanentPreserveMethod()

Demo

那它们之间具体有什么差别呢?

编写如下代码:

[HttpGet("RedirectPermanent")]
[HttpPost("RedirectPermanent")]
public IActionResult RedirectPermanent()

    _logger.LogInformation("RedirectPermanent");
    return RedirectPermanent("MyIO");


[HttpGet("Redirect")]
[HttpPost("Redirect")]
public IActionResult Redirect()

    _logger.LogInformation("Redirect");
    return Redirect("MyIO");


[HttpGet("RedirectPreserveMethod")]
[HttpPost("RedirectPreserveMethod")]
public IActionResult RedirectPreserveMethod()

    _logger.LogInformation("RedirectPreserveMethod");
    return RedirectPreserveMethod("MyIO");


[HttpGet("RedirectPermanentPreserveMethod")]
[HttpPost("RedirectPermanentPreserveMethod")]
public IActionResult RedirectPermanentPreserveMethod()

    _logger.LogInformation("RedirectPermanentPreserveMethod");
    return RedirectPermanentPreserveMethod("MyIO");


[HttpGet("MyIO")]
[HttpPost("MyIO")]
public string MyIO()

    return this.Request.Method;
  • 所有方法都同时支持GETPOST方法

  • 所有方法都会重定向到同一个方法,显示当前请求方法

每个 API 都请求 2 遍,可以看到:

  • Permanent = true 的Get请求只会执行一次,后续会直接请求跳转后的地址

  • PreserveMethod = false 的POST请求,跳转后实际执行的Get请求

结论

如果想只发生一次重定向,则应考虑使用RedirectPermanent或者RedirectPermanentPreserveMethod

如果要为非 GET 请求使用重定向,则应考虑使用RedirectPreserveMethod或者RedirectPermanentPreserveMethod

添加微信号【MyIO666】,邀你加入技术交流群

参考资料

[1]

RedirectResultExecutor.cs: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/Infrastructure/RedirectResultExecutor.cs#L63

以上是关于ASP.NET Core 中的重定向的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core MVC RedirectToAction 不工作

ASP.NET 网页的重定向和传值

如何正确重定向到 ASP.NET Core Razor Pages 中的同一页面?

匿名端点重定向到安全 ASP.Net Core Web 应用程序中的登录屏幕

尝试从 ASP.NET Core MVC Razor 中的 _Layout 页面重定向时出错

ASP.NET Core 3.1 图像 URL 错误代码 302 重定向