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标签显示。
我们还在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> <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请求日志,来看看发生了什么:
从上面截图中,我们可以看到浏览器在加载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项目下载: