HTML网页中,img标签和Ajax请求是支持跳转(Redirect)的

我们知道在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();
            }
            else
            {
                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);
            }
            else
            {
                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标签显示。

HTML网页中,img标签和Ajax请求是支持跳转(Redirect)的

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

HTML网页中,img标签和Ajax请求是支持跳转(Redirect)的

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

HTML网页中,img标签和Ajax请求是支持跳转(Redirect)的

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

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <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>
<body>
    <div>
        <h1>Index view!</h1>
    </div>
    <div>
        <button id="btnCallAjax" >调用ajax</button>
    </div>
    <div>
        <img src="@Url.Action("ShowFirstPicture")" />
    </div>
    
</body>
</html>

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

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

HTML网页中,img标签和Ajax请求是支持跳转(Redirect)的

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

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

HTML网页中,img标签和Ajax请求是支持跳转(Redirect)的

从上面截图中,我们可以看到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