ASP.NET Core MVC 從入門到精通之HttpContext

来源:https://www.cnblogs.com/hsiang/archive/2023/05/03/17368101.html
-Advertisement-
Play Games

隨著技術的發展,ASP.NET Core MVC也推出了好長時間,經過不斷的版本更新迭代,已經越來越完善,本系列文章主要講解ASP.NET Core MVC開發B/S系統過程中所涉及到的相關內容,適用於初學者,在校畢業生,或其他想從事ASP.NET Core MVC 系統開發的人員。 經過前幾篇文章... ...


隨著技術的發展,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,如下所示:

 1 namespace DemoCoreMVC.Services
 2 {
 3     public interface IStudentService
 4     {
 5         /// <summary>
 6         /// 保存類
 7         /// </summary>
 8         void Save();
 9     }
10 }
11 
12 namespace DemoCoreMVC.Services
13 {
14     public class StudentService : IStudentService
15     {
16         private readonly IHttpContextAccessor contextAccessor;
17 
18         public StudentService(IHttpContextAccessor contextAccessor)
19         {
20             this.contextAccessor = contextAccessor;
21         }
22 
23         public void Save()
24         {
25             var name = this.contextAccessor.HttpContext?.Request.Query["Name"];
26             Console.WriteLine(name);
27         }
28     }
29 }

在控制器中,通過構造函數的方式將IStudentService註入進去,如下所示:

 1 using DemoCoreMVC.Services;
 2 using Microsoft.AspNetCore.Mvc;
 3 
 4 namespace DemoCoreMVC.Controllers
 5 {
 6     public class StudentController : Controller
 7     {
 8         private readonly IStudentService studentService;
 9 
10         public StudentController(IStudentService studentService)
11         {
12             this.studentService = studentService;
13         }
14 
15         public IActionResult Save()
16         {
17             studentService.Save();
18             return Json("成功");
19         }
20 
21         public IActionResult Index()
22         {
23             return View();
24         }
25     }
26 }

在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表單內容,如下所示:

 1 <form action="~/Hello/Save" method="post">
 2     <div style="margin:10px;">
 3         <span>學號:</span>
 4         <input type="text" name="Id" />
 5     </div>
 6     <div style="margin:10px;">
 7         <span>姓名:</span>
 8         <input type="text" name="Name" />
 9     </div style="margin:10px;">
10     <div style="margin:10px;">
11         <span>年齡:</span>
12         <input type="text" name="Age" />
13     </div>
14     <div style="margin:10px;">
15         <span>性別:</span>
16         <input type="text" name="Sex" />
17     </div>
18     <div style="margin:10px;">
19         <input type="submit" name="submit" value="保存" />
20     </div>
21 </form>

HelloController中Save方法,如下所示:

 1 [HttpPost]
 2 public IActionResult Save()
 3 {
 4 
 5     var id = Request.Form["Id"];
 6     var name = Request.Form["Name"];
 7     var age = Request.Form["Age"];
 8     var sex = Request.Form["Sex"];
 9     var student = new Student()
10     {
11         Id = string.IsNullOrEmpty(id) ? 0 : int.Parse(id),
12         Name = name,
13         Age = string.IsNullOrEmpty(age) ? 0 : int.Parse(age),
14         Sex = sex
15     };
16     return Json(student);
17 }

運行測試,在瀏覽器中輸入網址【https://localhost:7116/Hello/add】進行測試,如下所示:

 

HttpRequest其它示例

 

HttpRequest中的其它示例,如下所示:

 1 public IActionResult Index()
 2 {
 3     Console.WriteLine($"Request.Host:{Request.Host}" );
 4     Console.WriteLine($"Request.Path:{Request.Path}");
 5     Console.WriteLine($"Request.Protocol:{Request.Protocol}");
 6     Console.WriteLine($"Request.ContentType:{Request.ContentType}");
 7     Console.WriteLine($"Request.Headers:");
 8     foreach(var header in Request.Headers)
 9     {
10         Console.WriteLine($"{header.Key}:{header.Value}");
11     }
12     Console.WriteLine($"Request.Cookies:");
13     foreach (var cookie in Request.Cookies)
14     {
15         Console.WriteLine($"{cookie.Key}:{cookie.Value}");
16     }
17     return View();
18 }

其它屬性示例截圖,如下所示:

註意:在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信息,如下所示:

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

在添加Headers時,如果是漢字,則會報下麵一個錯誤,如下所示:

以上錯誤表示編碼錯誤,漢字無效,需要進行編碼轉換,如下所示:

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

請求示例如下所示:

 

會話Session

 

由於Http請求是無狀態的,單次請求完成後,就會進行釋放,那麼如何在無狀態的請求中,保留一些相關的數據呢?這就用到了Session,Session在用戶打開瀏覽器登錄系統開始,到關閉瀏覽器退出系統結束,將用戶請求的一些數據,以鍵值對的形式保存在伺服器端的緩存中,可以解決無狀態協議模式下數據的頻繁傳遞傳遞,減少請求數據量,提高性能。Session一般應用在小型的單體應用程式中,對於大型的分散式程式,則不適用。

每一個用戶的瀏覽器請求都有自己的Session記憶體塊,不會和其他用戶的請求相混淆。

要啟用Session,首先需要在Program.cs中添加Session服務,和啟用Session中間件,如下所示:

 1 using DemoCoreMVC.Services;
 2 using Microsoft.AspNetCore.Server.Kestrel.Core;
 3 using System.Text.Encodings.Web;
 4 using System.Text.Unicode;
 5 
 6 var builder = WebApplication.CreateBuilder(args);
 7 
 8 // Add services to the container.
 9 builder.Services.AddControllersWithViews().AddJsonOptions(options =>
10 {
11     options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
12 });
13 
14 builder.Services.Configure<KestrelServerOptions>(options =>
15 {
16     options.AllowSynchronousIO = true;
17 });
18 
19 //1. 往容器中添加Session服務,啟用Session服務
20 builder.Services.AddSession();
21 
22 var app = builder.Build();
23 
24 // Configure the HTTP request pipeline.
25 if (!app.Environment.IsDevelopment())
26 {
27     app.UseExceptionHandler("/Home/Error");
28     // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
29     app.UseHsts();
30 }
31 
32 //2.使用Session中間件,主要用於攔截Http請求
33 app.UseSession();
34 app.UseHttpsRedirection();
35 app.UseStaticFiles();
36 
37 //1. 添加路由中間件EndpointRoutingMiddleware
38 app.UseRouting();
39 app.MapControllers();
40 app.UseAuthorization();
41 
42 app.MapControllerRoute(
43     name: "default",
44     pattern: "{controller=Home}/{action=Index}/{id?}");
45 
46 
47 app.Run();

 

Session屬性和方法

 

在實際應用中,一般使用擴展方法SetString(key,value),GetString(key)進行Session值的設置和獲取,如下所示:

註意,關於Session使用,有以下兩點需要註意: 

  1. 在控制器中,可以直接使用Session屬性
  2. 在非控制器中,可以使用請求上下文HttpContext進行獲取。

 

Session示例

 

以常用的登錄為例,實現如下功能:

  1. 用戶打開登錄頁面,輸入賬號密碼,點擊登錄按鈕
  2. 驗證用戶名密碼,驗證成功後,保存Session,跳轉到首頁
  3. 首頁獲取Session中保存的內容,並通過ViewBag傳遞到客戶端,顯示在頁面上。

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

 1 namespace DemoCoreMVC.Controllers
 2 {
 3     public class LoginController : Controller
 4     {
 5         public IActionResult Index()
 6         {
 7             return View();
 8         }
 9 
10         public IActionResult Login()
11         {
12             var username = Request.Form["username"];
13             var password = Request.Form["password"];
14             if(username=="admin" && password == "abc123")
15             {
16                 HttpContext.Session.SetString("username", username);
17             }
18             return Redirect("/Home");
19         }
20     }
21 }

然後創建Login/Index.cshtml視圖,如下所示:

 1 <form action="~/Login/Login" method="post">
 2     <div style="margin:10px;">
 3         <span style="display:inline-block; width:80px;">用戶名:</span>
 4         <input type="text" name="username" />
 5     </div>
 6     <div style="margin:10px;">
 7         <span style="display:inline-block;width:80px;">密  碼:</span>
 8         <input type="password" name="password" />
 9     </div style="margin:10px;">
10     <div style="margin:10px;">
11         <input type="submit" name="submit" value="登錄" />
12     </div>
13 </form>

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

 1 public class HomeController : Controller
 2 {
 3 
 4     public HomeController()
 5     {
 6     }
 7 
 8     public IActionResult Index()
 9     {
10         var username = HttpContext.Session.GetString("username");
11         ViewBag.Username = username;
12         return View();
13     }
14 }

Home/Index.cshtml中修改代碼,獲取ViewBag傳遞的值,如下所示:

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

以上就是Session示例的創建和獲取的相關代碼,頁面測試如下所示:

 

Session唯一標識

 

每一個瀏覽器打開的Session都有一個唯一標識,在控制器中,可以通過HttpContext.Session.Id進行區分。可以在Program.cs中添加服務到容器時配置相關參數,如下所示:

1 //1. 往容器中添加Session服務,啟用Session服務
2 builder.Services.AddSession(option =>
3 {
4     option.IdleTimeout = TimeSpan.FromMinutes(10);
5     option.Cookie.Name = "DemoMvcCore";
6 });

設置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.cnblogs.com/hsiang/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關註個人公眾號,定時同步更新技術及職場文章


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • LOD:迪米特法則(Law of Demeter) CRP:合成復用原則(Composite Reuse Principle) DRY:不要重覆你自己原則 (Don’t Repeat Yourself Principle) KISS:KISS原則 (Keep It Simple and Stupid ...
  • move : 移動語義,得到右值類型 forward:類型轉發,能夠識別左值和右值類型 只有兩種形式的引用,左值引用和右值引用,萬能引用不是一種引用類型,它存在於模板的引用摺疊情況,但是能夠接受左值和右值 區分左值和右值得一個簡單方式就是能不能取地址 一個右值一旦有名字那麼就變成了左值 #inclu ...
  • 術語表 第一章 FizzBuzz 用來編程面試中篩選候選者的測試。 操作系統 扮演電腦物理組件與人之間的中間人的一個程式。 圖形用戶界面(GUI) 操作系統的一部分,用戶在屏幕上看到的內容。 開源 軟體不歸某個公司或個人所有,而是由一群志願者維護。 Windows 微軟推出的操作系統。 UNIX ...
  • 一個典型的單線程伺服器示例如下: while (true) { Socket socket = null; try { // 接收客戶連接 socket = serverSocket.accept(); // 從socket中獲得輸入流與輸出流,與客戶通信 ... } catch(IOExcepti ...
  • java面向對象三大特征即為:繼承封裝多態。而多態需要三大必要條件。分別是:繼承、方法重寫、父類引用指向子類對象。我們先一個一個來理解。 1、首先是繼承和重寫。這個很簡單。因為多態就是建立在不同的重寫之上的。也就是說多態就是在使用著一個方法的不同重寫。而重寫又是依賴著繼承關係。 2、這個父類引用指向 ...
  • 一:背景 1. 講故事 今天是五一的最後一天,想著長期都在 Windows 平臺上做開發,準備今天換到 Ubuntu 系統上體驗下,主要是想學習下 AT&T 風格的彙編,這裡 Visual Studio 肯定是裝不了了,還得上 VSCode,剛好前幾天買了一個小工控機,這裡簡單記錄下 零到一 的過程 ...
  • 方法重載 同一個類中,多個方法的名稱相同,但是形參列表不同。 方法重載的形式 同一個類中,方法名稱相同、形參列表不同 形參的個數、類型、順序不同 形參的名稱無關 方法重載的調用流程 當程式調用一個重載方法時,編譯器會根據參數列表的不同自動匹配最合適的方法,這種機制叫做方法重載的“重載解析”。 根據方 ...
  • 首碼和 一、介紹 ~~首碼,顧名思義就是一個東西前面的點綴...~~(bushi 其實打比方來說就是:假如有一字元串ABCD,那麼他的首碼就是A、AB、ABC、ABCD這四個從新從第一個字母一次往後開始拼接的字元串。當然這是字元串。但首碼和一般應用於數組,對於給定的數組a=[1,2,3,4],他的前 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...