ASP.NET Core MVC 从入门到精通之HttpContext

news2024/11/17 13:38:06

随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生,或其他想从事ASP.NET Core MVC 系统开发的人员。 经过前几篇文章的讲解,初步了解ASP.NET Core MVC项目创建,启动运行,以及命名约定,创建控制器,视图,模型,接收参数,传递数据,路由,页面布局,wwwroot和客户端库,Razor语法,EnityFrameworkCore与数据库等内容,今天继续讲解ASP.NET Core MVC 中HttpContext等相关内容,仅供学习分享使用。

什么是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中,将服务添加到容器中,如下所示:

//增加一个默认的HttpContextAccessor
builder.Services.AddHttpContextAccessor();
//增加服务
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为例,如下所示:

HttpResponse

HttpResponse表示单个请求的传出内容,

状态码StatusCode

StatusCode是一个int类型,表示当前响应Http请求的状态,可以通过System.Net.HttpStatusCode(枚举)进行转换,常用的有以下几种:

  1. OK = 200,成功,这是最常用的一个响应状态码
  2. NotFound = 404, 未发现,即请求的信息不存在
  3. InternalServerError = 500,服务器内部错误
  4. Redirect = 302, 请求已被重定向

在Controller中,常见的状态码返回值,以被定义为方法,如:Ok(),NotFound()等,可以直接调用。

HttpResponse示例

在响应的Headers中,添加Author信息,如下所示:

public IActionResult Test2()
{
    Response.Headers.Add("Author", "公子小六");
    return Json("ABC");
}

在添加Headers时,如果是汉字,则会报下面一个错误,如下所示:

以上错误表示编码错误,汉字无效,需要进行编码转换,如下所示:

public IActionResult Test2()
{
    var author = HttpUtility.UrlEncode("公子小六", Encoding.UTF8);
    Response.Headers.Add("Author", author);
    return Json("ABC");
}

请求示例如下所示:

会话Session

由于Http请求是无状态的,单次请求完成后,就会进行释放,那么如何在无状态的请求中,保留一些相关的数据呢?这就用到了Session,Session在用户打开浏览器登录系统开始,到关闭浏览器退出系统结束,将用户请求的一些数据,以键值对的形式保存在服务器端的缓存中,可以解决无状态协议模式下数据的频繁传递传递,减少请求数据量,提高性能。Session一般应用在小型的单体应用程序中,对于大型的分布式程序,则不适用。

每一个用户的浏览器请求都有自己的Session内存块,不会和其他用户的请求相混淆。

要启用Session,首先需要在Program.cs中添加Session服务,和启用Session中间件,如下所示:

using DemoCoreMVC.Services;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using System.Text.Encodings.Web;
using System.Text.Unicode;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
});

builder.Services.Configure<KestrelServerOptions>(options =>
{
    options.AllowSynchronousIO = true;
});

//1. 往容器中添加Session服务,启用Session服务
builder.Services.AddSession();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

//2.使用Session中间件,主要用于拦截Http请求
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();

//1. 添加路由中间件EndpointRoutingMiddleware
app.UseRouting();
app.MapControllers();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");


app.Run();

Session属性和方法

在实际应用中,一般使用扩展方法SetString(key,value),GetString(key)进行Session值的设置和获取,如下所示:

注意,关于Session使用,有以下两点需要注意: 

  1. 在控制器中,可以直接使用Session属性
  2. 在非控制器中,可以使用请求上下文HttpContext进行获取。

Session示例

以常用的登录为例,实现如下功能:

  1. 用户打开登录页面,输入账号密码,点击登录按钮
  2. 验证用户名密码,验证成功后,保存Session,跳转到首页
  3. 首页获取Session中保存的内容,并通过ViewBag传递到客户端,显示在页面上。

首先创建控制器LoginController,如下所示:

namespace DemoCoreMVC.Controllers
{
    public class LoginController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Login()
        {
            var username = Request.Form["username"];
            var password = Request.Form["password"];
            if(username=="admin" && password == "abc123")
            {
                HttpContext.Session.SetString("username", username);
            }
            return Redirect("/Home");
        }
    }
}

然后创建Login/Index.cshtml视图,如下所示:

<form action="~/Login/Login" method="post">
    <div style="margin:10px;">
        <span style="display:inline-block; width:80px;">用户名:</span>
        <input type="text" name="username" />
    </div>
    <div style="margin:10px;">
        <span style="display:inline-block;width:80px;">密  码:</span>
        <input type="password" name="password" />
    </div style="margin:10px;">
    <div style="margin:10px;">
        <input type="submit" name="submit" value="登录" />
    </div>
</form>

修改HomeController中代码,如下所示:

public class HomeController : Controller
{

    public HomeController()
    {
    }

    public IActionResult Index()
    {
        var username = HttpContext.Session.GetString("username");
        ViewBag.Username = username;
        return View();
    }
}

Home/Index.cshtml中修改代码,获取ViewBag传递的值,如下所示:

<div class="text-center">
    <h1 class="display-4">Welcome @ViewBag.Username</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

以上就是Session示例的创建和获取的相关代码,页面测试如下所示:

Session唯一标识

每一个浏览器打开的Session都有一个唯一标识,在控制器中,可以通过HttpContext.Session.Id进行区分。可以在Program.cs中添加服务到容器时配置相关参数,如下所示:

//1. 往容器中添加Session服务,启用Session服务
builder.Services.AddSession(option =>
{
    option.IdleTimeout = TimeSpan.FromMinutes(10);
    option.Cookie.Name = "DemoMvcCore";
});

设置Session选项中的Cookie的名称后,会在浏览器客户端创建对应的值,如下所示:

参考文章

本篇文章主要参考内容如下:

1. https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.httpcontext?view=aspnetcore-7.0

2. https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.httprequest?view=aspnetcore-7.0

3. https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.httpresponse?view=aspnetcore-7.0

4. https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.isession?view=aspnetcore-7.0

以上就是ASP.NET Core MVC从入门到精通之HttpContext的全部内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/486005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kafka常见问题QA(六)

六、常见问题QA 6.1 无消息丢失如何配置 producer 调用方式 &#xff08;1&#xff09;网络抖动导致消息丢失&#xff0c;Producer 端可以进行重试。 &#xff08;2&#xff09;消息大小不合格&#xff0c;可以进行适当调整&#xff0c;符合 Broker 承受范围再发送。 不要使用…

【Linux Network】网络编程套接字

目录 1. 源IP地址与目的IP地址的认识 2. 端口号的认识 3. 套接字socket 4. TCP协议和UDP协议 5. 网络字节序 6. socket编程 7. socket编程接口 8. 使用UDP协议跨网络通信程序 Linux网络编程✨ 1. 源IP地址与目的IP地址的认识 在因特网上&#xff0c;一台主机和一个IP地址往往是…

【VM服务管家】VM4.2平台SDK_6.1 环境配置类

目录 2.1.1 环境配置&#xff1a;基于Csharp二次开发环境配置方法2.1.2 环境配置&#xff1a;基于MFC二次开发环境配置方法2.1.3 环境配置&#xff1a;基于Qt二次开发环境配置方法2.1.4 用户权限&#xff1a;普通以EXE方式启动Server的方法2.1.5 环境配置&#xff1a;程序启动后…

基于类别级正则化的无监督域自适应眼底图像分割

文章目录 Unsupervised Domain Adaptive Fundus Image Segmentation with Category-Level Regularization摘要方法Inter-domain Category RegularizationSource Domain Category RegularizationTarget Domain Category Regularization总损失 Unsupervised Domain Adaptive Fund…

总结目前敏捷开发框架(持续更新....)

文章目录 0 敏捷开发1 类型分类1.1. Scrum1. 2.极限编程&#xff08;XP&#xff09;1. 3. 快速应用程序开发 (RAD)1. 4. 动态系统开发方法&#xff08;DSDM&#xff09;1.5.统一流程&#xff08;UP&#xff09;1. 6. 精益方法1. 7. 看板1. 8.FDD&#xff08;功能驱动开发&#…

2023年最新版【接口自动化测试,web自动化测试,app自动化测试】全套自动化测试面试题

前言&#xff1a; 自动化测试是软件测试中的一个重要领域&#xff0c;它可以帮助企业提高软件开发质量、缩短测试周期和降低测试成本。随着信息技术的不断发展&#xff0c;自动化测试也在不断地创新和发展。本篇文章收集了2023年最新版的接口自动化测试、Web自动化测试和App自…

通俗理解CNN感受野的计算方法

x o u t x i n − k s 1 x_{out} \frac{x_{in} - k}{s} 1 xout​sxin​−k​1 如果不考虑padding&#xff0c;卷积输出的feature map的计算公式如上&#xff0c;那么 x i n ( x o u t − 1 ) ∗ s k x_{in} (x_{out} - 1) * s k xin​(xout​−1)∗sk。因此计算模型的感…

springbooot使用google验证码

springbooot使用google验证码 1、使用场景2、springboot使用google验证码1、引入依赖2、编写配置类3、编写控制层4、前端实现 1、使用场景 由于需要做一个前后端分离的项目&#xff0c;想着使用google验证码&#xff0c;由于年龄大了&#xff0c;这些知识啊&#xff0c;用完就…

防伪标志使用的全息薄膜,竟可合成大自然的“结构色”

大自然为生物赋予了各种各样的色彩&#xff0c;除了常见的赤橙黄绿青蓝紫外&#xff0c;还有反光效果很好的金属色等等。有趣的是&#xff0c;一些生物身上的颜色也能像金属那样闪闪发光&#xff0c;在不同光线下颜色甚至还会有变化。实际上&#xff0c;大自然很多色彩由色素产…

全注解下的SpringIoc 续6-多环境配置

我们都知道&#xff0c;在企业开发过程中&#xff0c;一个项目往往都会有开发、测试、仿真、生产等环境配置&#xff0c;除了使用配置中心&#xff08;比如Apollo等&#xff09;之外&#xff0c;Spring Boot也提供了不同环境之间切换的机制&#xff0c;下面让我们来一起看看。 …

Docker安全最佳实践

目录 1、探测容器开放端口和服务漏洞 2、宿主机、网络、镜像、DockerApi安全 3、更新Docker、日志、事件 4、Docker安全测试 5、Docker安全最佳实践 1、探测容器开放端口和服务漏洞 使用Nmap扫描Docker容器中的开放端口 使用docker ps命令获取正在运行的容器ID或名称。在…

密码学作业——置换密码部分

part1: encrypt加密函数_代码补充&#xff1a; /*请在此处添加*/cout<<Substition[plain[i]]; part2:Decrypt解密函数_代码补充: /*请在此处添加代码*/ cout<<ReverseTable[cipher[i]];part3:设置 转换表Substition[]部分: // 将i对应的置换表元素设为s1中对应…

prometheus实战之三:告警规则

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《prometheus实战》系列的第三篇&#xff0c;一起来学习prometheus的告警功能&#xff0c;如下图所示&#xff0c;整个告警功能分为规则和通…

Python使用AI animegan2-pytorch制作属于你的漫画头像/风景图片

Python使用AI animegan2-pytorch制作属于你的漫画头像 1. 效果图2. 原理3. 源码参考 git clone https://github.com/bryandlee/animegan2-pytorch cd ./animegan2-pytorch python test.py --photo_path images/photo_test.jpg --save_path images/animegan2_result.png1. 效果图…

全球首个机器人辅助试管婴儿降生

近日&#xff0c;两名通过机器人辅助受精手术成功诞生的女婴成为全球瞩目的焦点。这是全球首批由机器人成功辅助受精的婴儿案例&#xff0c;预示着未来生育技术的发展趋势。 以往&#xff0c;试管婴儿受精过程中将精子注入卵子内的环节都是由人工完成。胚胎技术人员需要在显微镜…

最简单的循环

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C语言和数据结构 &#x1f33c;博客专栏&#xff1a;C语言学习 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&am…

6. Docker——详说镜像

本章讲解知识点 Docker 镜像 Union File System&#xff08;联合文件系统&#xff09;技术 回说 Docker 镜像分层 Docker 镜像分层原理 1. Docker 镜像 镜像是一种轻量级、可执行的独立软件包&#xff0c;用来打包软件运行环境和基于运行环境开发的软件&#xff0c;它包含…

一文了解 Zebec Labs 投资的 Coral Finance,空投计划或在不久推出

在前不久&#xff0c;Zebec Labs 宣布对链上衍生品协议 Coral Finance 进行150万美元的投资&#xff0c;以帮助该协议完成早期启动并&#xff0c;并在后续持续的为其提供孵化支持。Coral Finance 将在不久部署在 Nautilus Chain 主网上。据了解&#xff0c;Coral Finance 是 Na…

【VM服务管家】VM4.2平台SDK_6.2 模块操作类

目录 2.2.1 流程操作&#xff1a;通过流程或Group设置输入输出图像的方法2.2.2 模块操作&#xff1a;设置输入图像、参数和ROI2.2.3 N点标定&#xff1a;清空标定点、生成标定文件2.2.4 分支字符&#xff1a;控制调试模式开关的方法2.2.5 条件检测&#xff1a;条件检测模块设置…

【GAMES101】02 Review Of Linear Algebra

1.点乘&#xff1a; 向量点乘 → 一个数值 点乘在图形学中的应用&#xff1a; 找到两个方向之间的夹角。找到一个向量投影到另一个向量上是什么样的。计算两个向量的方向&#xff08;是接近还是远离&#xff09;判定高光范围&#xff0c;从1&#xff08;重合&#xff…