ASP.NET/MVC/Core的HTTP請求流程

来源:https://www.cnblogs.com/xuhuale/archive/2018/11/30/10030878.html
-Advertisement-
Play Games

ASP.NET HTTP管道(Pipeline)模型 1. 先講一點,再深刻思考 一般我們都在寫業務代碼,優化頁面,優化邏輯之間內徘徊。也許我們懂得HTTP,HTTPS的GET,POST,但是我們大部分人是不知道ASP是如何去解析HTTP,或者IIS是如何去處理頁面請求。我們只知道WebForm拉控 ...


ASP.NET HTTP管道(Pipeline)模型

1. 先講一點,再深刻思考

一般我們都在寫業務代碼,優化頁面,優化邏輯之間內徘徊。也許我們懂得HTTP,HTTPS的GET,POST,但是我們大部分人是不知道ASP是如何去解析HTTP,或者IIS是如何去處理頁面請求。我們只知道WebForm拉控制項,MVC寫Controller,Action,卻不知道IIS,NetFrameWork幫我們做了很多事情。那接下我們就是要去瞭解IIS幫我們做了些啥事情。

2. 那啥叫管道(Pipeline)模型

  • 初理解Pipeline

    • 從一個現象說起,有一家咖啡吧生意特別好,每天來的客人絡繹不絕,客人A來到櫃臺,客人B緊隨其後,客人C排在客人B後面,客人D排在客人C後面,客人E排在客人D後面,一直排到店面門外。老闆和三個員工首先為客人A準備食物:員工甲拿了一個乾凈的盤子,然後員工乙在盤子里裝上薯條,員工丙再在盤子里放上豌豆,老闆最後配上一杯飲料,完成對客人A的服務,送走客人A,下一位客人B開始被服務。然後員工甲又拿了一個乾凈的盤子,員工乙又裝薯條,員工丙又放豌豆,老闆又配上了一杯飲料,送走客人B,客人C開始被服務。一直重覆下去。

    • 從效率方面觀察這個現象,當服務客人A時,在員工甲拿了一個盤子後,員工甲一直處於空閑狀態,直到送走客人A,客人B被服務。老闆自然而然的就會想到如果每個人都不停的幹活,就可以服務更多的客人,賺到更多的錢。老闆通過不停的嘗試想出了一個辦法。以客戶A,B為例闡述這個方法:員工甲為客戶A準備好了盤子後,在員工乙開始為客戶A裝薯條的同時,員工甲開始為客戶B準備托盤。這樣員工甲就可以不停的進行生產。整個過程如下圖,客戶們圍著咖啡吧台排隊,因為有四個生產者,一個老闆加三個員工,所以可以同時服務四個客戶。我們將目光轉向老闆,單位時間從他那裡出去的客戶數提高了將近四倍,也就是說效率提高將近四倍。

    這樣子,我們就很好理解了Pipeline了,那其實就是每個人絡繹不絕的做自己的事情,但個人事情又是整個流程的一部分,有點像工廠的小妹,只做包鞋底,但是這又是製造鞋的中間流程。一條流水,一條管道,一直處理下去。那每個HTTP請求,到了IIS也是這樣子的。

  • 針對Pipeline模型帶來的啟示,好處
    • 工作流的參考模型
      其實就是上面所說一樣,pipeline模型與工作流模型,都是鏈式的,就像一條生產線,各個組件的前後協同。
    • 服務framework的參考構建模型
      Pipeline模型的一個特點是,在其內部是以組建的模式來實現組合的(雖然這些組建有先後順序之分),它假如你把側重點放在它的鏈式組合上,而不是將側重點放在上面的工作流上(工作流的關註點是流程的先後順序),那麼完全可以用這種方式來搭建一個複雜的服務,當然這樣做的前提是,單個組件的粒度必須儘可能小並且耦合性極低。
      那其實就很像現在的微服務了,只不過微服務更大,服務對象是一個應用程式。
    Pipeline模型帶來的:流程式(有序)+可拆卸(配置),比普通的封裝機動性更好。
  • Pipeline模型的缺點
    每次它對於一個輸入(或者一次請求)都必須從鏈頭開始遍歷(參考Http Server處理請求就能明確),這確實存在一定的性能損耗。

3. 講完Pipeline,我們講他在IIS上的實現

3.1 Http請求帶伺服器的時候

  1. 當伺服器接收到一個Http請求的時候,IIS是如何去決定,並處理該請求。答案就是文件的“尾碼名”。

    伺服器獲取所請求的頁面或文件的尾碼名後,那伺服器就回去尋找能出來這些尾碼的應用程式。若是IIS找不到,並且文件沒有受到IIS的保護(保護:App_Code文件夾的文件,不保護:平常的JS文件等),就會直接返回給客戶端(瀏覽器,移動端等)

    那麼能處理尾碼名的程式叫什麼呢? ISAPI 應用程式(Internet Server Application Programe Interface,互聯網伺服器應用程式介面)。它其實是一個介面,起到一個代理的作用,他的主要工作就是將請求的頁面(文件)與處理該頁面(文件)的尾碼的處理程式進行一個映射。讓其可以爭取的去處理頁面(文件)。

    那這個應用程式長什麼樣子呢?
    • 我們打開IIS(server2003),隨意選中一個站點,滑鼠右擊屬性,然後選擇“主目錄”選項,接著選擇“配置”。然後就可以看到下麵的畫面。

    這邊我們能看到尾碼名與之可執行的文件路徑。
    接著我們找到“.axpx”的尾碼名,打開來看。

    我們可以發現".aspx"的尾碼名是有aspnet_isapi.dll來處理的,所以IIS將".aspx"頁面的請求交給這個dll,就不關心後面是如何處理了。所以我們現在知道了,ASP.NET只是伺服器(IIS)的一個組成部分而已,它是一個ISAPI擴展。

  2. 上面是server2003的情況,現在08以上變成了不是在屬性裡面了, 他變成了IIS中的“ISAPI篩選器”和“處理程式映射”了。

    1. 我們點擊“ISAPI篩選器”,可以出現發現,篩選器是分FrameWork與位數的,所以有四個。

    1. 我們進入處理程式映射,找出尾碼為“.aspx”的,可以發現有很多個,對應了framework與位數,並且有個處理程式,

    3.雙擊進入,可以看到可以到處理模塊的具體路徑,以及請求限制。

註意,這邊要是限制後,頁面(文件)只能以某種特定方式訪問。

3.2 宿主環境(Hosting)

從本質上講,Asp.Net 主要是由一系列的類組成,這些類的主要目的就是將 Http 請求轉變為對客戶端的響應。HttpRuntime 類是 Asp.Net 的一個主要入口,它有一個稱作 ProcessRequest的方法,這個方法以一個 HttpWorkerRequest 類作為參數。HttpRuntime 類幾乎包含著關於單個 Http 請求的所有信息:所請求的文件、伺服器端變數、QueryString、Http 頭信息 等等。Asp.Net 使用這些信息來載入、運行正確的文件,並且將這個請求轉換到輸出流中,一般來說,也就是 HTML 頁面。當然也可是是文件。

當頁面(文件)發生變動時,為了能夠卸載運行在同一進程中的應用程式,當然卸載也是為了重新新載入,Http請求被分放在相互隔離的應用程式域。也就是“AppDomain”。

那麼對於IIS來說,IIS依賴一個叫HTTP.SYS的內置驅動程式來監聽外部的HTTP請求,在操作系統啟動的時候,IIS會在HTTP.SYS中註冊自己的虛擬路徑。(註冊可以理解為,告訴HTTP.SYS哪些URL可以訪問,哪些不可以訪問,404就可以怎麼來的,就是這麼來的。)

如果是可以訪問的URL,那麼HTTP.SYS會將這個請求扔給IIS工作者進程。(就是我們所熟悉的W3WP.EXE,IIS5.0叫做ASPNET_WP.EXE)。
運行是每個進程都有一個身份標識,以及一系列的可選性能參數,其實就是應用程式池,唯一標識就是應用程式池名稱。

基礎的知識點都懂了,我們來看下一個大概的HTTP請求的過程

  1. HTTP.SYS接收Http請求信息。並將信息保存到HttpWorkRequest類中。
  2. 從相互隔離的AppDomain中載入HttPRuntime。
  3. 調用HttpRuntime的ProcessRequest方法。
  4. 程式猿創造世界
  5. IIS接收返回的數據流,重新返回給HTTP.SSY
  6. HTTP.SYS將數據返回給客戶端(瀏覽器)

3.3 接下來是重點,理解Pipeline

前面講了那麼多,終於進入到重點,劃重點。
首先我們先知道了什麼是Pipeline,接著我們知道一個Http的請求過程。然後我們就知道了,原來Http請求到伺服器,原來是走這樣一條路。

但是我們忽略了,這個過程跟我們程式,跟我們代碼怎麼銜接起來的。
當Http請求進入 Asp.Net Runtime以後,它的管道由托管模塊(Managed Modules)和處理程式(Handlers)組成,並且由管道來處理這個 Http請求。這個就是所謂的ASP的Http管道模型了。

接下來我們看下這個管道模型是怎麼流動的。(WebForm)

  1. 首先進來肯定是HTTPRuntime,然後通過HttpApplicationFactory創建HttpApplication。
  2. HttpApplication會創建該次Http請求的HttpContext(上下文),那這個對象我們就很熟悉了,裡面就包括HttpRequest、HttpResponse、HttpSessionState等。
  3. 那接下來請求會通過一系列的Module(可以理解為車間,可以做通過的物品做事情),Module可以做一些執行某個實際工作前的事情。因為它會Http請求有完全的控制權。
  4. 當Http請求完,它會被HttpHandler處理。在這一步,也就是我們實際做的事情了,他可以完成我們.aspx的所有業務。WebForm的每個頁面都是繼承“Page”,而“Page”繼承了“IHttpHandler”介面

        public class Page : TemplateControl, IHttpHandler{
        // 代碼省略
        }
  5. HttpHandler處理完後,又會回到Module,這時可以做一些實際工作後的事情。
    我們很多事件,是不是有分前與後,就是這個道理。進行事件的前後攔截。
  6. 我們可以看下,在只有Module與Handler的情況,整個Http的流動走向,大概是這樣子

3.4 那講完WebForm的,我們來講MVC的

在IIS7之前,如IIS6或IIS5,請求處理管道分為兩個:IIS請求處理管道和ASP.NET管道,若客戶端請求靜態資源則只有IIS管道進行處理,而ASP.NET管道不會處理該請求。從IIS7開始兩個管道合二為一,稱為集成管道。其實就是我們IIS里會選擇到應用程式池的托管模式。

再次瞭解

  • IIS 6以及IIS 7經典模式
    早期的IIS版本中,IIS接收到一個請求時先判斷請求類型,如果是靜態文件直接由IIS處理;如果是一個ASP.NET請求類型,IIS把請求發送給IIS的擴展介面ASP.NET ISAPI DLL。ISAPI相當於ASP.NET應用的容器,這也是我們之前講的。

  • IIS 7 集成模式
    IIS 7和之前的版本區別比較大,IIS7直接把ASP.NET的運行管道流程集成到了IIS上。

    • 在IIS7中,ASP.NET請求處理管道Pipeline直接覆蓋了IIS本身的管道Pipeline,IIS整個流程按照ASP.ENT管道流程執行,例如BeginRequest、AuthenticateRequest、…、EndRequest。而不是通過插件擴展(ISAPI)形式,不同的內容(jpg、html、php等)通過不同的插件來執行。
    • IIS7的優勢體現在哪裡?開發人員可以實現自定義的HttpModule或者HttpHandler,然後直接集成到IIS上,例如,我可以自定義一個JpgHttpHandler,然後通過IIS的Handler部署方式,把JpgHttpHandler部署到IIS上,處理所有的請求格式為*.jpg的請求。

知道這些我們繼續瞭解MVC的管道模式

廢話不多說,直接上圖

廢話也不多說,直接走下流程(以我的方式理解)

廢話有點多

  1. 首先進入HttpRuntime,在一樣通過HttpApplicationFactory創建HttpApplication
  2. HttpApplication會創建該次Http請求的HttpContext(上下文),那這個對象我們就很熟悉了,裡面就包括HttpRequest、HttpResponse、HttpSessionState等。(這些都跟webform是一樣的)
  3. HttpApplication繼承IHttpHandler,接著我們開始走Module
  4. 然後我們進入到使用UrlRoutingModule(路由系統)UrlRoutingModule,從Http請求獲取Controller和Action以及路由數據。
  5. 接著匹配Route規則,獲取Route對象,解析對象。
  6. 請求IRouteHandler(MVCRouteHandler)
  7. 執行ProcessRequest方法,然後使用ControllerBulider獲取ControllerFactory
  8. 接著就調用到Controller,同樣的的方法到達Action,並執行
  9. 在執行Controller與Action可能會有各種認證,各種特性攔截
  10. 程式猿創造世界
  11. 返回ActionResult
  12. 響應Http
  13. 客戶端接收響應

接下來我們具體瞭解下細節

  • HttpApplication與HttpModule

    HTTP請求由ASP.NET運行時接管之後,HttpRuntime會利用HttpApplicationFactory創建或從HttpApplication對象池(.NET中類似的機制有線程池和字元串拘留池)中取出一個HttpApplication對象,同時ASP.NET會根據配置文件來初始化註冊的HttpModule,HttpModule在初始化時會訂閱HttpApplication中的事件來實現對HTTP請求的處理。

      public class HttpApplication : IComponent, IDisposable, IHttpAsyncHandler, IHttpHandler, IRequestCompletedNotifier, ISyncContext{   
    
       public HttpApplication();
       public ISite Site { get; set; }
       public IPrincipal User { get; }
       ...
      }

    很明顯我們可以看到HttpApplication繼承了IHttpHandler,是跟WebForm的Page是一樣的

  • Route

    一個HTTP請求會經過至少一個HttpModule的處理。UrlRoutingModule是非常重要的模塊,它是路由系統的核心。路由系統的職責是從請求URL中獲取controller和action的名稱以及其它請求數據。
    UrlRoutingModule根據當前請求的URL和RouteTable中已註冊的路由模板進行匹配並返回第一個和當前請求相匹配的路有對象Route,然後根據路有對象獲取路由數據對象RouteData(ASP.NET MVC中,路由數據必須包含controller和action的名稱),再有RouteData獲取IRouteHandler最終有IRouteHandler得到IHttpHandler

  • HttpHandler

    一個HTTP請求最終要進入HttpHanler中進行處理,一次HTTP請求只能被一個HttpHandler進行處理。

  • Controller
    IHttpHandler在ProcessRequest方法中對當前請求進行處理,在該方法中通過ControllerBuilder得到IControllerFactory然後通過反射的方式獲取Controller的類型。

  • Action

    ASP.NET MVC中ControllerBase是所有Controller的基類,在該類型的Execute方法中通過IActionInvoker的InvokeAction方法來執行對Action的調用。在Action執行前會進行模型綁定和模型認證操作。

  • Filters

    在ASP.NET MVC5中有常用的過濾器有5個:IAuthenticationFilter、IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilter。
    在ASP.NET MVC中所有的過濾器最終都會被封裝為Filter對象,該對象中FilterScope類型的屬性Scope和int類型屬性Order用於決定過濾器執行的先後順序,具體規則如下:
    Order和FilterScope的數值越小,過濾器的執行優先順序越高;
    Order比FilterScope具有更高的優先順序,在Order屬性值相同時FilterScope才會被考慮

      //數值越小,執行優先順序越高
      public enum FilterScope
      {
          Action= 30,
          Controller= 20,
          First= 0,
          Global= 10,
          Last= 100
      }
  • ActionResult

    Action執行完畢之後會返回ActionResult類型對象作為對此次請求進行處理的結果,對於不是ActionResult類型的返回值,ASP.NET MVC會將其轉換為ActionResult類型。

總結:那這個就是MVC模式下,一個大概的請求走向,在MVC的模式下,它的管道是啥樣子的。

3.5 看完MVC ,我們接著來看最牛的Core,誰叫它可以跨平臺呢【傲嬌】

既然Core是跨平臺的,那麼它不依托IIS,現在的IIS就是個擺設,它有獨立的Core的SDK,Core的RunTime。我們來一探究竟!

Core是跨平臺的,那他是怎麼實現的呢,其實他自己本身有自己的Kestrel Server,可以直接對外部提供服務。但是還需要有個反向代理伺服器將他保護起來,IIS就是其一,其他平臺有其他的方式。

上圖:

知識點:IIS 是通過 HTTP 的方式來調用我們的 ASP.NET Core 程式。而部署在IIS中時,並不需要我們手動來啟動 ASP.NET Core 的控制台程式,這是因為IIS新增了一個 AspNetCoreModule 模塊,它負責 ASP.NET Core 程式的啟動與停止,並能監聽 ASP.NET Core 程式的狀態,在我們的應用程式意外崩潰時重新啟動。

  • Hostting(宿主)

    IIS通過Http調用Core應用程式,所以我們肯定要創建一個Host來啟動Core,WebHost,上面我們也講到宿主,我們通過宿主在生成一系列的Http的上下文,環境等。整個http請求都在宿主內。
    • WebHost的創建

      public class Program{
      public static void Main(string[] args){
      CreateWebHostBuilder(args).Build().Run();
      }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
        }

      我們可以看到WeHost通過靜態本身來調用創建出來的。“CreateDefaultBuilder”用來做一些簡單的配置

      1. 註冊 Kestrel 中間件,指定 WebHost 要使用的 Server(HTTP伺服器)。
      2. 設置 Content 根目錄,將當前項目的根目錄作為 ContentRoot 的目錄。
      3. 讀取 appsettinggs.json 配置文件,開發環境下的 UserSecrets 以及環境變數和命令行參數。
      4. 讀取配置文件中的 Logging 節點,對日誌系統進行配置。
      5. 添加 IISIntegration 中間件。
      6. 設置開發環境下, ServiceProvider 的 ValidateScopes 為 true,避免直接在 Configure 方法中獲取 Scope 實例。

      接著指定Startup最終使用Build創建WebHost。緊接著使用Run將程式跑起來。

    • WebHost的啟動
      1. 初始化,構建 RequestDelegate
        RequestDelegate 是我們的應用程式處理請求,輸出響應的整個過程,也就是我們的 ASP.NET Core 請求管道。
        1. 調用 Startup 中的 ConfigureServices 方法
        2. 初始化 Http Server
          Server 是一個HTTP伺服器,負責HTTP的監聽,接收一組 FeatureCollection 類型的原始請求,並將其包裝成 HttpContext 以供我們的應用程式完成響應的處理。
        3. 創建 IApplicationBuilder
          IApplicationBuilder 用於構建應用程式的請求管道,也就是生成 RequestDelegate
        4. 配置 IApplicationBuilder
      2. 啟動 Server,監聽請求並響應
      3. 啟動 HostedService
        那這邊是簡單的講了下WebHost,具體的內容可以看下文章末尾的Core的鏈接。
  • Middleware(中間件),管道模型的構成
    • IApplicationBuilder
      首先,IApplicationBuilder 是用來構建請求管道的,而所謂請求管道,本質上就是對 HttpContext 的一系列操作,即通過對 Request 的處理,來生成 Reponse。因此,在 ASP.NET Core 中定義了一個 RequestDelegate 委托,來表示請求管道中的一個步驟,它有如下定義:
      public delegate Task RequestDelegate(HttpContext context);
      而對請求管道的註冊是通過 Func<RequestDelegate, RequestDelegate> 類型的委托(也就是中間件)來實現的。它接收一個 RequestDelegate 類型的參數,並返回一個 RequestDelegate 類型,也就是說前一個中間件的輸出會成為下一個中間件的輸入,這樣把他們串聯起來,形成了一個完整的管道。
      它有一個內部的 Func<RequestDelegate, RequestDelegate> 類型的集合(用來保存我們註冊的中間件)和三個核心方法:
      1. Use
      Use是我們非常熟悉的註冊中間件的方法,其實現非常簡單,就是將註冊的中間件保存到其內部屬性 _components 中。
      2. Build
      Hosting 的啟動中,便是通過該 Build 方法創建一個 RequestDelegate 類型的委托,Http Server 通過該委托來完成整個請求的響應
      3. Run
      在我們註冊的中間件中,是通過 Next 委托 來串連起來的,如果在某一個中間件中沒有調用 Next 委托,則該中間件將做為管道的終點,因此,我們在最後一個中間件不應該再調用 Next 委托,而 Run 擴展方法,通常用來註冊最後一個中間件
      4. New
      New 方法根據自身來“克隆”了一個新的 ApplicationBuilder 對象,而新的 ApplicationBuilder 可以訪問到創建它的對象的 Properties 屬性,但是對自身 Properties 屬性的修改,卻不到影響到它的創建者,這是通過 CopyOnWriteDictionary 來實現的

    所以 Core的管道其實就是Middleware來做的,每個都有前置,後置的處理步驟,中間可以調用其他Middleware。也可以並行走向。

ASP.NET Core 請求管道的構建過程,以及一些幫助我們更加方便的來配置請求管道的擴展方法。在 ASP.NET Core 中,至少要有一個中間件來響應請求,而我們的應用程式實際上只是中間件的集合,MVC 也只是其中的一個中間件而已。簡單來說,中間件就是一個處理http請求和響應的組件,多個中間件構成了請求處理管道,每個中間件都可以選擇處理結束,還是繼續傳遞給管道中的下一個中間件,以此串聯形成請求管道。通常,我們註冊的每個中間件,每次請求和響應均會被調用,但也可以使用 Map , MapWhen ,UseWhen 等擴展方法對中間件進行過濾。

3.6總結

那我們分析了以往微軟的3種形式底下的Web,分別是WebForm,MVC,Core,其中WebForm與MVC雷士,依托於IIS,不同的就是ISAPI的不同。前者的ISAPI以插件形式存在IIS,而後者將其整合成一套。Core跨平臺,IIS只是他的一個反向代理伺服器,HTTP請求帶Core的程式,運行Core。
但是我覺得他們內容是基本不變的,HTTP請求,進來在彼此的AppDomain中創建HttpContext,然後就開始走Pipeline走流程,WebFrom走PageIHTTPHandler與其相關的IModule,而MVC是Global.asax繼承HttpApplication,HttpApplication又繼承IHTTPHandler,接下來WebFrom與MVC就各自走各自的Pipeline。Core卻不是這樣,它的Pipeline採用了Middleware(中間件)的形式。俄羅斯套娃,一步一步走Pipeline。最終都是響應客戶端,一個HTTP請求,從開始到結束。

感謝張子陽的博客-WebForm
感謝雪飛鴻的博客-MVC
感謝雨夜朦朧-Core


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

-Advertisement-
Play Games
更多相關文章
  • AdminLTE 一個基於 bootstrap 的輕量級後臺模板,這個前端界面個人感覺很清爽,對於一個大後端的我來說,可以減少較多的時間去承擔前端的工作但又必須去獨立去完成一個後臺系統開發的任務,並且,文檔還算比較齊全,對著demo可以完成一個基本的前端框架搭建了。大家如有更為好看的又方便後端上手的 ...
  • 搞了一天多,才勉強搞出了一個不緊湊的六邊形統計圖,是真的菜。 這裡ECharts的用法與06說的同一種,直接使用帶all的js 先上個效果圖,用面積來表示人數的多少 1. 參數option的tooltip和title還是一樣設置 2. 還有一個grid,這是用來設置y軸的實際長度的。(我把y軸隱藏了 ...
  • 在C#中 JArray japroimg = new JArray(); strproimg.ToString();這樣會導致tostring之後的字元串中會有大量的空格 使用 japroimg.ToString(Newtonsoft.Json.Formatting.None, null);的fom ...
  • ef開發模式有3種:DateBase First(資料庫優先)、Model First(模型優先)和Code First(代碼優先)。這裡我用的是code first 一個簡單的例子: 簡單介紹一下Database.SetInitializer方法 一:資料庫不存在時重新創建資料庫 Database ...
  • 一、什麼是Dapper? Dapper是一款輕量級Orm框架,它是屬於半自動的,它和Entity Framework和NHibernate不同,它只有一個單文件,沒有很複雜的配置,如果你喜歡原生Sql語句,而且又是喜歡Orm框架,那麼Dapper對於你來說是再適合不過了。 二、Dapper優點我也是 ...
  • .net core執行dotnet ef migrations createmodel等命令出錯 執行dotnet ef migrations createmodel、dotnet ef migrations add initial等命令出錯,報錯信息為:No project was found. ...
  • 事情起源:公司視頻播放一直是採用的嵌入瀏覽器組件實現視頻的預覽回放等功能。這種實現方式要求客戶使用IE瀏覽器。 最近上線項目使用Html 5開發,要求IE11。項目中使用了視頻播放功能,如果全部升級到IE11問題多,工作量大。 存在的主要問題: 有些系統開發較早,不能在IE11上運行。 部分客戶電腦 ...
  • 本想接著上一篇詳解泛型接著寫一篇使用泛型時需要註意的一個性能問題,但是後來想著不如將之前的詳解XX系列更正為現在的效率優化XX系列,記錄在工作時遇到的一些性能優化的經驗和技巧,如果有什麼不足,還請大家多多指出; 在使用集合時,通常為了防止裝箱操作而選擇List<T>、Dictionary<TKey, ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...