原文链接:https://www.cnblogs.com/hsiang/p/17368101.html
什么是HttpContext?
在B/S模式开发的程序中,客户端是浏览器,服务器端Web服务程序,HttpContext是连接客户端和服务器端程序的桥梁,交代了当前请求的环境信息,它封装了请求[Request]和响应[Response]及其他所有信息,示意图如下所示:
图一 内网访问程序
图二 反向代理访问程序
在示意图中,Kestrel 是一个基于 libuv 的跨平台ASP.NET Core web服务器。不清楚 Kerstrel 没关系,以后慢慢了解。
注意:HttpContext从客户端发起一个请求开始,到服务器端响应完成结束,每一个新的请求,都会创建一个新的HttpContext对象。
HttpContext属性
在HttpContext中,最常用的属性有3个【Request,Response,Session】具体属性如下表所示:
控制器中应用HttpContext
在控制器中,HttpContext作为控制器父类ControllerBase的属性存在,且Request和Response作为使用频率非常高的常用对像,控制器也声明成了属性,都可以直接使用。如下所示:
控制器外使用HttpContext
在应用程序中,控制器继承了Controller类,所以才能不用声明就可以直接使用HttpContext,但是除了控制器,还在其他的程序,那在其他程序中,如何使用HttpContext呢?
首先有一个服务接口IStudentService和服务实现类StudentService,其他中在StudentService中访问HttpContext,如下所示:
namespace DemoCoreMVC.Services {public interface IStudentService{/// <summary>/// 保存类/// </summary>void Save();} }namespace DemoCoreMVC.Services {public class StudentService : IStudentService{private readonly IHttpContextAccessor contextAccessor;public StudentService(IHttpContextAccessor contextAccessor){this.contextAccessor = contextAccessor;}public void Save(){var name = this.contextAccessor.HttpContext?.Request.Query["Name"];Console.WriteLine(name);}} }
在控制器中,通过构造函数的方式将IStudentService注入进去,如下所示:
using DemoCoreMVC.Services; using Microsoft.AspNetCore.Mvc;namespace DemoCoreMVC.Controllers {public class StudentController : Controller{private readonly IStudentService studentService;public StudentController(IStudentService studentService){this.studentService = studentService;}public IActionResult Save(){studentService.Save();return Json("成功");}public IActionResult Index(){return View();}} }
在Program.cs中,将服务添加到容器中,如下所示:
1 //增加一个默认的HttpContextAccessor 2 builder.Services.AddHttpContextAccessor(); 3 //增加服务 4 builder.Services.AddScoped<IStudentService, StudentService>();
经过以上3步,就可以实现在控制器之外的类中,访问HttpContext,测试示例,如下所示:
注意:在ASP.NET Core MVC项目中,对象的创建,优先从容器中获取,这样可以不需要考虑它的创建过程和构造参数。如:创建服务Service,控制器对象Controller,视图对象View,数据访问层Repository等内容。对于模型对象,如视图模型,数据模型等不依赖其他对象的类型,则可以通过New进行创建。
HttpRequest
HttpRequest表示单个请求的传入端,常用的Query用于获取Get请求传递的参数,Form用于获取Post请求传递的参数,如下所示:
HttpRequest示例
在本示例中,以Request.Form为例,获取Post方式传递的参数,客户端将所有需要传递的内容包括在Form表单内容,在服务器端Action中通过Request.Form["Key"]进行获取。如下所示:
Add.cshtml视图中Form表单内容,如下所示:
<form action="~/Hello/Save" method="post"><div style="margin:10px;"><span>学号:</span><input type="text" name="Id" /></div><div style="margin:10px;"><span>姓名:</span><input type="text" name="Name" /></div style="margin:10px;"><div style="margin:10px;"><span>年龄:</span><input type="text" name="Age" /></div><div style="margin:10px;"><span>性别:</span><input type="text" name="Sex" /></div><div style="margin:10px;"><input type="submit" name="submit" value="保存" /></div> </form>
HelloController中Save方法,如下所示:
[HttpPost] public IActionResult Save() {var id = Request.Form["Id"];var name = Request.Form["Name"];var age = Request.Form["Age"];var sex = Request.Form["Sex"];var student = new Student(){Id = string.IsNullOrEmpty(id) ? 0 : int.Parse(id),Name = name,Age = string.IsNullOrEmpty(age) ? 0 : int.Parse(age),Sex = sex};return Json(student); }
运行测试,在浏览器中输入网址【https://localhost:7116/Hello/add】进行测试,如下所示:
HttpRequest其它示例
HttpRequest中的其它示例,如下所示:
public IActionResult Index() {Console.WriteLine($"Request.Host:{Request.Host}" );Console.WriteLine($"Request.Path:{Request.Path}");Console.WriteLine($"Request.Protocol:{Request.Protocol}");Console.WriteLine($"Request.ContentType:{Request.ContentType}");Console.WriteLine($"Request.Headers:");foreach(var header in Request.Headers){Console.WriteLine($"{header.Key}:{header.Value}");}Console.WriteLine($"Request.Cookies:");foreach (var cookie in Request.Cookies){Console.WriteLine($"{cookie.Key}:{cookie.Value}");}return View(); }
其它属性示例截图,如下所示:
意:在Request的Get请求中,默认ContentType为空,Cookies如果没有设置,也为空。
Cookie存放于客户端浏览器中,可以通过浏览器开发者模式F12下进行查看,以www.bilibili.com为例,如下所示: