我们知道在HTTP请求中,状态码301和302代表跳转,也叫重定向(Redirect)。

  • 301-Moved Permanently :永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替。
  • 302-Found :临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI。
  • 参考 HTTP状态码

    我们知道一个常规的HTTP请求(例如请求一个网页),是支持跳转(Redirect)的。经过实验发现,其实HTML网页上的img标签和Ajax请求,也是会自动处理HTTP跳转(Redirect)的。

    我们新建一个ASP.NET Core MVC项目AspNetCoreRedirectDemos,本文的例子基于ASP.NET Core 5.0项目。

    下面是项目中HomeController的代码:

    using AspNetCoreRedirectDemos.Models;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using System;
    using System.IO;
    namespace AspNetCoreRedirectDemos.Controllers
        public class HomeController : Controller
            private readonly ILogger<HomeController> _logger;
            private readonly bool redirectPicture = true;//图片请求是否跳转,true表示进行跳转
            private readonly bool redirectAjax = true;//Ajax请求是否跳转,true表示进行跳转
            public HomeController(ILogger<HomeController> logger)
                _logger = logger;
            public IActionResult Index()
                return View();
            public IActionResult ShowFirstPicture()
                if (!redirectPicture)
                    string path = AppDomain.CurrentDomain.BaseDirectory + "Files\\1.jpg";
                    byte[] data = null;
                    using (FileStream fs = new FileStream(path, FileMode.Open))
                        data = new byte[fs.Length];
                        fs.Read(data, 0, data.Length);
                    Response.ContentType = "image/jpeg";
                    Response.ContentLength = data.Length;
                    using (Stream stream = Response.Body)
                        stream.Write(data, 0, data.Length);
                    return new EmptyResult();
                    return RedirectToAction("ShowSecondPicture");//将访问ShowFirstPicture这个Action方法的请求,跳转到Action方法ShowSecondPicture
            public IActionResult ShowSecondPicture()
                string path = AppDomain.CurrentDomain.BaseDirectory + "Files\\2.jpg";
                byte[] data = null;
                using (FileStream fs = new FileStream(path, FileMode.Open))
                    data = new byte[fs.Length];
                    fs.Read(data, 0, data.Length);
                Response.ContentType = "image/jpeg";
                Response.ContentLength = data.Length;
                //Action方法ShowSecondPicture,返回图片2.jpg到客户端浏览器
                using (Stream stream = Response.Body)
                    stream.Write(data, 0, data.Length);
                return new EmptyResult();
            public IActionResult FirstAjaxResponse([FromBody] PersonRequestModel personRequestModel)
                if (!redirectAjax)
                    ResponseData responseData = new ResponseData()
                        StatusCode = 100,
                        Message = "奔驰,返回消息"
                    return Json(responseData);
                    return RedirectToAction("SecondAjaxResponse");//将访问FirstAjaxResponse这个Action方法的请求,跳转到Action方法SecondAjaxResponse
            public IActionResult SecondAjaxResponse()
                ResponseData responseData = new ResponseData()
                    StatusCode = 100,
                    Message = "宝马,返回消息"
                //Action方法SecondAjaxResponse,返回json数据到客户端浏览器
                return new JsonResult(responseData);
    

    我们在HomeController中,定义了ShowFirstPicture和ShowSecondPicture两个Action方法,HTML网页上的img标签会请求ShowFirstPicture方法获取图片数据流,而ShowFirstPicture方法会返回HTTP状态码302到客户端浏览器,让浏览器发送新的HTTP请求,跳转(Redirect)到ShowSecondPicture方法,然后ShowSecondPicture方法会返回图片文件2.jpg的数据到客户端浏览器,供img标签显示。

    我们还在HomeController中,定义了FirstAjaxResponse和SecondAjaxResponse两个Action方法,HTML网页上的JavaScript代码会发送Ajax请求给FirstAjaxResponse方法,而FirstAjaxResponse方法会返回HTTP状态码302到客户端浏览器,让浏览器发送新的HTTP请求,跳转(Redirect)到SecondAjaxResponse方法,然后SecondAjaxResponse方法会返回JSON数据到客户端浏览器。

    此外,我们还在HomeController中定义了两个bool类型的变量redirectPicture和redirectAjax,分别用来控制是否启用img标签和Ajax请求的跳转(Redirect),当变量值为true时,就表示启用跳转(Redirect)。

    下面是HomeController的Index.cshtml视图文件代码:

    Layout = null;
    <!DOCTYPE html> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="~/lib/jquery/dist/jquery.js" ></script> <script type="text/javascript" > $(function () { $("#btnCallAjax").click(function () { var ajaxData = {}; ajaxData.Name = "王大锤, Jack Wang"; ajaxData.Age = 38; $.ajax({ type: "POST", cache: false, contentType: "application/json; charset=utf-8", dataType: "json", url: "@Url.Action("FirstAjaxResponse")", data: JSON.stringify(ajaxData), success: function (data) { alert(JSON.stringify(data)) error: function (xhr, ts, et) { alert('服务调用失败!'); </script> </head> <h1>Index view!</h1> </div> <button id="btnCallAjax" >调用ajax</button> </div> <img src="@Url.Action("ShowFirstPicture")" /> </div> </body> </html>

    我们可以看到在视图代码中,使用了img标签和Ajax代码,来请求了HomeController的ShowFirstPicture和FirstAjaxResponse两个Action方法。

    接下来我们运行项目,跟踪浏览器的HTTP请求日志,来看看发生了什么:

    从上面截图中,我们可以看到浏览器在加载Index.cshtml视图文件生成的HTML网页后,img标签首先发出了HTTP请求到Action方法ShowFirstPicture,然后ShowFirstPicture方法返回了HTTP状态码302,告诉浏览器需要进行HTTP跳转(Redirect),所以img标签又发起了第二次HTTP请求到Action方法ShowSecondPicture,然后ShowSecondPicture方法返回了HTTP状态码200,将图片数据返回给了浏览器显示,符合我们的预期。

    接下来我们点击浏览器网页上的"调用ajax"按钮,来触发Ajax请求,继续跟踪浏览器的HTTP请求日志:

    从上面截图中,我们可以看到JavaScript代码首先发出了Ajax请求到Action方法FirstAjaxResponse,然后FirstAjaxResponse方法返回了HTTP状态码302,告诉浏览器需要进行HTTP跳转(Redirect),所以浏览器又发出了第二个Ajax请求到Action方法SecondAjaxResponse,然后SecondAjaxResponse方法返回了HTTP状态码200,将JSON数据返回给了浏览器显示,这说明Ajax也是可以自动处理HTTP跳转(Redirect)的。但是需要注意的是,我们看到第一次到Action方法FirstAjaxResponse的Ajax请求是POST的,但是第二次到Action方法SecondAjaxResponse的Ajax请求变成了GET的了,说明Ajax在自动处理HTTP跳转(Redirect)的时候,始终是用GET方法来发起跳转请求的,所以在实际开发中,不建议让Ajax来自动处理HTTP跳转(Redirect),而应该使用JavaScript代码来重新发起一个新的Ajax请求到跳转后的地址。

    本文通过例子来演示了在HTML网页上,img标签和Ajax请求是可以自动处理HTTP跳转(Redirect)的,但是Ajax会始终用GET方法来发起跳转请求,所以不推荐让Ajax来自动处理HTTP跳转(Redirect)。

    本文示例ASP.NET Core MVC项目下载:

    AspNetCoreRedirectDemos