第三單元 管道與中間件

来源:https://www.cnblogs.com/xuyubing/archive/2023/12/06/17878998.html
-Advertisement-
Play Games

1. 什麼是中間件 在ASP.NET Core中,中間件(Middleware)是一個可以處理HTTP請求或響應的軟體管道。 ASP.NET Core中給中間件組件的定位是具有非常特定的用途。例如,我們可能有需要一個中間件組件驗證用戶,另一個中間件來處理錯誤,另一個中間件來提供靜態文件,如JavaS ...


1. 什麼是中間件

在ASP.NET Core中,中間件(Middleware)是一個可以處理HTTP請求或響應的軟體管道。 ASP.NET Core中給中間件組件的定位是具有非常特定的用途。例如,我們可能有需要一個中間件組件驗證用戶,另一個中間件來處理錯誤,另一個中間件來提供靜態文件,如JavaScript文件,CSS文件,圖片等等。

中間件就是用於組成應用程式管道來處理請求和響應的組件 。

中間件可以認為有兩個基本的職責:

  1. 選擇是否將請求傳遞給管道中的下一個中間件。

  2. 可以在管道中的下一個中間件前後執行一些工作。

我們使用這些中間件組件在ASP.NET Core中設置請求處理管道,而正是這管道決定瞭如何處理請求。 而請求管道是由Startup.cs文件中的Configure()方法進行配置,它也是應用程式啟動的一個重要部分。

// 配置http 請求管道,由運行時調用
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage(); // 渲染錯誤頁中間件
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }
    app.UseStaticFiles(); // 使用靜態文件中間件
    
    app.UseRouting(); // 使用路由中間件
​
    app.UseAuthorization(); // 使用授權中間件
    // 終端節點中間件
    app.UseEndpoints(endpoints =>
                     {
                         endpoints.MapControllerRoute(
                             name: "default",
                             pattern: "{controller=Home}/{action=Index}/{id?}");
                     });
}
 

 

2. 中間件處理流程-請求管道

.Net Core管道(pipeline)是什麼?

簡單來說,就是從發起請求到返回結果的一個過程,在.Net Core中這裡面的處理是由中間件(middleware)來完成。 管道機制解釋 用戶在發起請求後,系統會自動生成一個請求管道(request pipeline),在這個請求管道中,可以通過run、map和use方法來配置請求委托(RequestDelegate),而在單獨的請求委托中定義的可重用的類和並行的匿名方法即為中間件,也叫做中間件組件。當發起請求後,系統會創建一個請求管道,在這個管道中,每一個中間件都會按順序處理(可能會執行,也可能不會被執行,取決於具體的業務邏輯),等最後一個中間件處理完後,又會按照相反的方向返回最終的處理結果。

例如,如果您有一個日誌記錄中間件,它可能只是記錄請求的時間,它處理完畢後將請求傳遞給下一個中間件以進行進一步處理。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(); // 添加控制器服務
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env,ILogger<Startup> logger)
{
    app.UseRouting();// 添加路由服務

    app.Use(next =>
            {
                logger.LogInformation("第1個中間件"); // 啟動時執行,只執行一次
                
                // 每次請求都會執行一次
                return async context =>
                {
                    logger.LogInformation("第1個中間件1-before");
                    await next(context);
                    logger.LogInformation("第1個中間件1-after");
                };
            });

    app.Use(next =>
            {
                logger.LogInformation("第2個中間件");// 啟動時執行,只執行一次

                 // 每次請求都會執行一次
                return async context =>
                {
                    logger.LogInformation("第2個中間件2-before");
                    await next(context);
                    logger.LogInformation("第2個中間件2-after");
                };
            });

    app.Use(next =>
            {
                logger.LogInformation("第3個中間件");// 啟動時執行,只執行一次

                 // 每次請求都會執行一次
                return async context =>
                {
                    logger.LogInformation("第3個中間件3-before");
                    await next(context);
                    logger.LogInformation("第3個中間件3-after");
                };
            });
    
    // 使用終端節點中間件會短路後面的中件間,所以,這個中間件最好放在最後
    app.UseEndpoints(endpoints =>
                     {
                         endpoints.MapControllerRoute(
                             name: "default",
                             pattern: "{controller=Home}/{action=Index}/{id?}");
                     });
}
info: Step3.Empty.Startup[0]
      第3個中間件
info: Step3.Empty.Startup[0]
      第2個中間件
info: Step3.Empty.Startup[0]
      第1個中間件

// 發起請求之後
info: Step3.Empty.Startup[0]
      第1個中間件1-before
info: Step3.Empty.Startup[0]
      第2個中間件2-before
info: Step3.Empty.Startup[0]
      第3個中間件3-before
info: Step3.Empty.Startup[0]
      第3個中間件3-after
info: Step3.Empty.Startup[0]
      第2個中間件2-after
info: Step3.Empty.Startup[0]
      第1個中間件1-after

 

中間件順序

下圖顯示了 ASP.NET Core MVC 和 Razor Pages 應用的完整請求處理管道。 你可以在典型應用中瞭解現有中間件的順序,以及在哪裡添加自定義中間件。 你可以完全控制如何重新排列現有中間件,或根據場景需要註入新的自定義中間件。

 

3. 什麼是短路

中間件組件可以處理請求, 並決定不調用管道中的下一個中間件,從而使管道短路,官方微軟給了一個英文的名字叫“terminal middleware ”,翻譯為“終端中間件”。短路通常是被允許的,因為它可以避免一些不必要的工作。 例如, 如果請求的是像圖像或 css 文件這樣的靜態文件, 則 StaticFiles 中間件可以處理和服務該請求並使管道中的其餘部分短路。這個意思就是說,在我們的示例中, 如果請求是針對靜態文件, 則 Staticile 中間件不會調用 MVC 中間件,避免一些無謂的操作。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env,ILogger<Startup> logger)
{
    app.UseRouting();

    app.Use(next =>
            {
                logger.LogInformation("第1個中間件");

                return async context =>
                {
                    logger.LogInformation("第1個中間件1-before");
                    await next(context);
                    logger.LogInformation("第1個中間件1-after");
                };
            });

    // 後面的中件間將不會再執行了
    app.Use(next =>
            {
                logger.LogInformation("第2個中間件");

                return async context =>
                {
                    logger.LogInformation("短路了");
                    // await next(context); // 沒有調用即表示短路了
                };
            });
    
    app.Use(next =>
            {
                logger.LogInformation("第3個中間件");

                return async context =>
                {
                    logger.LogInformation("第3個中間件3-before");
                    await next(context);
                    logger.LogInformation("第3個中間件3-after");
                };
            });

    app.UseEndpoints(endpoints =>
                     {
                         endpoints.MapControllerRoute(
                             name: "default",
                             pattern: "{controller=Home}/{action=Index}/{id?}");
                     });
}
輸出結果:

info: Step3.Empty.Startup[0]
      第3個中間件
info: Step3.Empty.Startup[0]
      第2個中間件
info: Step3.Empty.Startup[0]
      第1個中間件

// 發起請求之後
info: Step3.Empty.Startup[0]
      第1個中間件1-before
info: Step3.Empty.Startup[0]
      短路了
info: Step3.Empty.Startup[0]
      第1個中間件1-after

 

app.Use 與 app.Run 的區別

它倆都可以添加一個中間件至請求管道中。

  1. Use 有權決定是否執行下一個中間件,如果不執行,則出現短路情況

  2. Run 是直接短路,不會執行後面的中間件。

 

4. 常用的系統中間件

1. 路由中間件

ASP.NET Core 控制器使用路由中間件來匹配傳入請求的 URL 並將它們映射到操作。 若要設置路由模板,則必須執行添加如下中間件至執行管道.

// 添加控制器與視圖服務
builder.Services.AddControllersWithViews();


// ....上面省略一些代碼
app.UseRouting();

 

路由模板:

  • 在啟動時 Program.cs 或在屬性中定義。

  • 描述 URL 路徑如何與操作相匹配。

  • 用於生成鏈接的 URL。 生成的鏈接通常在響應中返回。

操作既支持傳統路由,也支持屬性路由。 通過在控制器或操作上放置路由可實現屬性路由。 有關詳細信息,請參閱混合路由

路由模板示例匹配 URI請求 URI…
hello /hello 僅匹配單個路徑 /hello
{Page=Home} / 匹配並將 Page 設置為 Home
{Page=Home} /Contact 匹配並將 Page 設置為 Contact
{controller}/{action}/{id?} /Products/List 映射到 Products 控制器和 List 操作。
{controller}/{action}/{id?} /Products/Details/123 映射到 Products 控制器和 Details 操作,並將 id 設置為 123。
{controller=Home}/{action=Index}/{id?} / 映射到 Home 控制器和 Index 方法。 id 將被忽略。
{controller=Home}/{action=Index}/{id?} /Products 映射到 Products 控制器和 Index 方法。 id 將被忽略。

設置傳統路由

app.UseRouting();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run(); // 必須添加一個終節點
路由模板 "{controller=Home}/{action=Index}/{id?}":

匹配 URL 路徑,例如 /Products/Details/5

通過標記路徑來提取路由值 { controller = Products, action = Details, id = 5 }。 如果應用有一個名為 ProductsController 的控制器和一個 Details 操作,則提取路由值會導致匹配:

public class ProductsController : Controller
{
    public IActionResult Details(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
MyDisplayRouteInfo 由 Rick.Docs.Samples.RouteInfo NuGet 包提供,會顯示路由信息。

/Products/Details/5 模型綁定 id = 5 的值,以將 id 參數設置為 5。 有關更多詳細信息,請參閱模型綁定。

{controller=Home} 將 Home 定義為預設 controller。

{action=Index} 將 Index 定義為預設 action。

{id?} 中的 ? 字元將 id 定義為可選。

預設路由參數和可選路由參數不必包含在 URL 路徑中進行匹配。 有關路由模板語法的詳細說明,請參閱路由模板參考。

匹配 URL 路徑 /。

生成路由值 { controller = Home, action = Index }。

controller 和 action 的值使用預設值。 id 不會生成值,因為 URL 路徑中沒有相應的段。 / 僅在存在 HomeController 和 Index 操作時匹配:

public class HomeController : Controller
{
    public IActionResult Index() { ... }
}
使用前面的控制器定義和路由模板,為以下 URL 路徑運行 HomeController.Index 操作:

/Home/Index/17

/Home/Index

/Home

/

URL 路徑 / 使用路由模板預設 Home 控制器和 Index 操作。 URL 路徑 /Home 使用路由模板預設 Index 操作。

簡便方法 MapDefaultControllerRoute:

app.MapDefaultControllerRoute();
替代:

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

屬性路由
// 添加控制器與視圖服務
builder.Services.AddControllersWithViews();


// ....上面省略一些代碼 
// app.UseRouting(); // 此行代碼已經不需要了
app.MapControllers(); // 映射控制器
MapControllers 調用它來映射屬性路由控制器。

在以下示例中:

HomeController 匹配一組類似於預設傳統路由 {controller=Home}/{action=Index}/{id?} 匹配的 URL。

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
將針對任意 URL 路徑 /、/Home、/Home/Index 或 /Home/Index/3 執行 HomeController.Index 操作。

此示例重點介紹屬性路由與傳統路由之間的主要編程差異。 屬性路由需要更多輸入才能指定路由。 傳統預設路由會更簡潔地處理路由。 但是,屬性路由允許並需要精確控制應用於每項操作的路由模板。

對於屬性路由,控制器和操作名稱在操作匹配中不起作用,除非使用標記替換。 以下示例匹配與上一個示例相同的 URL:

public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
以下代碼對 action 和 controller 使用標記替換:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("[controller]/[action]")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("[controller]/[action]")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}
以下代碼將 [Route("[controller]/[action]")] 應用於控制器:

[Route("[controller]/[action]")]
public class HomeController : Controller
{
    [Route("~/")]
    [Route("/Home")]
    [Route("~/Home/Index")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

 

在前面的代碼中,Index 方法模板必須將 /~/ 預置到路由模板。 應用於操作的以 /~/ 開頭的路由模板不與應用於控制器的路由模板合併。

有關路由模板選擇的信息,請參閱路由模板優先順序

 

路由約束(可選)

路由約束在傳入 URL 發生匹配時執行,URL 路徑標記為路由值。 路徑約束通常檢查通過路徑模板關聯的路徑值,並對該值是否為可接受做出對/錯決定。 某些路由約束使用路由值以外的數據來考慮是否可以路由請求。 例如,HttpMethodRouteConstraint 可以根據其 HTTP 謂詞接受或拒絕請求。 約束用於路由請求和鏈接生成。

警告

請勿將約束用於輸入驗證。 如果約束用於輸入驗證,則無效的輸入將導致 404(找不到頁面)響應。 無效輸入可能生成包含相應錯誤消息的 400 錯誤請求。 路由約束用於消除類似路由的歧義,而不是驗證特定路由的輸入。

下表演示示例路由約束及其預期行為:

約束示例匹配項示例說明
int {id:int} 123456789, -123456789 匹配任何整數
bool {active:bool} true, FALSE 匹配 truefalse。 不區分大小寫
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm 在固定區域性中匹配有效的 DateTime 值。 請參閱前面的警告。
decimal {price:decimal} 49.99, -1,000.01 在固定區域性中匹配有效的 decimal 值。 請參閱前面的警告。
double {weight:double} 1.234, -1,001.01e8 在固定區域性中匹配有效的 double 值。 請參閱前面的警告。
float {weight:float} 1.234, -1,001.01e8 在固定區域性中匹配有效的 float 值。 請參閱前面的警告。
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638 匹配有效的 Guid
long {ticks:long} 123456789, -123456789 匹配有效的 long
minlength(value) {username:minlength(4)} Rick 字元串必須至少為 4 個字元
maxlength(value) {filename:maxlength(8)} MyFile 字元串不得超過 8 個字元
length(length) {filename:length(12)} somefile.txt 字元串必須正好為 12 個字元
length(min,max) {filename:length(8,16)} somefile.txt 字元串必須至少為 8 個字元,且不得超過 16 個字元
min(value) {age:min(18)} 19 整數值必須至少為 18
max(value) {age:max(120)} 91 整數值不得超過 120
range(min,max) {age:range(18,120)} 91 整數值必須至少為 18,且不得超過 120
alpha {name:alpha} Rick 字元串必須由一個或多個字母字元組成,a-z,並區分大小寫。
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 字元串必須與正則表達式匹配。 請參閱有關定義正則表達式的提示。
required {name:required} Rick 用於強制在 URL 生成過程中存在非參數值

警告

如果使用 System.Text.RegularExpressions 處理不受信任的輸入,則傳遞一個超時。 惡意用戶可能會向 RegularExpressions 提供輸入,從而導致拒絕服務攻擊。 使用 RegularExpressions 的 ASP.NET Core 框架 API 會傳遞一個超時。

 

可向單個參數應用多個用冒號分隔的約束。 例如,以下約束將參數限製為大於或等於 1 的整數值:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

 

警告

驗證 URL 的路由約束並將轉換為始終使用固定區域性的 CLR 類型。 例如,轉換為 CLR 類型 intDateTime。 這些約束假定 URL 不可本地化。 框架提供的路由約束不會修改存儲於路由值中的值。 從 URL 中分析的所有路由值都將存儲為字元串。 例如,float 約束會嘗試將路由值轉換為浮點數,但轉換後的值僅用來驗證其是否可轉換為浮點數。

 

疑惑解答:

1. 當訪問一個Web 應用地址時,Asp.Net Core 是怎麼執行到ControllerAction的呢?

答:程式啟動的時候會把所有的Controller 中的Action 映射存儲到routeOptions 的集合中,Action 映射成Endpoint終結者 的RequestDelegate 委托屬性,最後通過UseEndPoints 添加EndpointMiddleware 中間件進行執行,同時這個中間件中的Endpoint 終結者路由已經是通過Rouing匹配後的路由。

2. EndPoint 跟普通路由又存在著什麼樣的關係?

答:Ednpoint 終結者路由是普通路由map 轉換後的委托路由,裡面包含了路由方法的所有元素信息EndpointMetadataCollectionRequestDelegate 委托。

3. UseRouing()UseAuthorization()UseEndpoints() 這三個中間件的關係是什麼呢?

答:UseRouing 中間件主要是路由匹配,找到匹配的終結者路由EndpointUseEndpoints 中間件主要針對UseRouing 中間件匹配到的路由進行 委托方法的執行等操作。 UseAuthorization 中間件主要針對 UseRouing 中間件中匹配到的路由進行攔截 做授權驗證操作等,通過則執行下一個中間件UseEndpoints(),具體的關係可以看下麵的流程圖:

 

上面流程圖中省略了一些部分,主要是把UseRouing 、UseAuthorization 、UseEndpoint 這三個中間件的關係突顯出來。

 

 

2. 異常中間件

UseExceptionHandler : 將中間件添加到管道,該中間件將捕獲異常,記錄異常,併在備用管道中重新執行請求。如果響應已啟動,則不會重新執行請求。

UseDeveloperExceptionPage: 從管道捕獲同步和非同步異常實例,並生成 HTML 錯誤響應。

if (!app.Environment.IsDevelopment()) // 非開發環境下,可以顯示自定義錯誤頁
{
    app.UseExceptionHandler("/Home/Error");
}
else
{
    app.UseDeveloperExceptionPage(); // 開發人員錯誤頁
}

 

 

3. 靜態資源中間件

預設情況下,靜態文件(如 HTML、CSS、圖像和 JavaScript)是 ASP.NET Core 應用直接提供給客戶端的資產。

靜態文件存儲在項目的 Web 根目錄中。 預設目錄為 {content root}/wwwroot,但可通過 UseWebRoot 方法更改目錄。 有關詳細信息,請參閱內容根目錄Web 根目錄

Web 應用程式項目模板包含 wwwroot 文件夾中的多個文件夾:

  • wwwroot

    • css 樣式文件

    • js 腳本文件

    • lib 第三方前端庫

    • images 圖片文件

 

預設 Web 應用模板在 Program.cs 中調用

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

-Advertisement-
Play Games
更多相關文章
  • 作者:Lxlxxx 鏈接:https://juejin.cn/post/7221461552343072828 前言 繼上次線上CPU出現了報警,這次服務又開始整活了,風平浪靜了沒幾天,看生產日誌服務的運行的時候,頻繁的出現OutOfMemoryError,就是我們俗稱的OOM,這可還行! 頻繁的O ...
  • 上一篇介紹了scikit-learn中的幾個玩具數據集,本篇介紹scikit-learn提供的一些真實的數據集。玩具數據集:scikit-learn 基礎(01)--『數據載入』之玩具數據集 1. 獲取數據集 與玩具數據集不同,真實的數據集的數據不僅數據特征多,而且數據量也比較大,所以沒有直接包含在 ...
  • 在今天的課上,我們深入討論了封裝、反射和單例模式這幾個重要的概念。我不想過多地贅述它們的細節,但是請大家務必記住它們的基本語法規則,因為這也是面向對象章節的結束。我希望大家能夠牢牢掌握這些知識點,為未來的學習打下堅實的基礎。 ...
  • 外接矩形、外接圓: 1 import cv2 2 import numpy 3 4 img = cv2.imread('../img/img.png', -1) 5 ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) 6 con ...
  • 1. _Layout.cshtml 佈局頁 佈局視圖和我們在Asp.Net MVC一樣,佈局視圖_Layout.cshtml使得所有視圖保持一致的外觀變得更加容易,因為我們只有一個要修改的佈局視圖文件,更改後將立即反映在整個應用程式的所有視圖中。 在 ASP.NET Core MVC 中,有一些視圖 ...
  • 如果是首次安裝Dev只需要下麵兩步流程就可以 第一步安裝試用的最新版 Devexpress 22.2.4這步看直接去官網,安裝官方試用的就可以 第二步安裝破解補丁關閉防火牆或360 然後打開 DevExpress.Universal.Patch 選擇22.2 版本 和對應的visual studio ...
  • create database MvcUnit4; go use MvcUnit4; go create table Product ( Id bigint primary key, ProductName varchar(30), CategoryName varchar(30), Price d ...
  • 前言 上一篇,我們實現了基於 DotNetty 的通信基礎模塊的搭建,本篇,主要實現待發佈 Web 項目的集成。 創建待發佈項目 為了測試, 我創建了一個基於 .NET 4.8 的 Web 項目 OpenDeploy.TestWebProject 我本機的代碼倉儲路徑是: D:\Projects\B ...
一周排行
    -Advertisement-
    Play Games
  • 在C#中使用SQL Server實現事務的ACID(原子性、一致性、隔離性、持久性)屬性和使用資料庫鎖(悲觀鎖和樂觀鎖)時,你可以通過ADO.NET的SqlConnection和SqlTransaction類來實現。下麵是一些示例和概念說明。 實現ACID事務 ACID屬性是事務處理的四個基本特征, ...
  • 我們在《SqlSugar開發框架》中,Winform界面開發部分往往也用到了自定義的用戶控制項,對應一些特殊的界面或者常用到的一些局部界面內容,我們可以使用自定義的用戶控制項來提高界面的統一性,同時也增強了使用的便利性。如我們Winform界面中用到的分頁控制項、附件顯示內容、以及一些公司、部門、菜單的下... ...
  • 在本篇教程中,我們學習瞭如何在 Taurus.MVC WebMVC 中進行數據綁定操作。我們還學習瞭如何使用 ${屬性名稱} CMS 語法來綁定頁面上的元素與 Model 中的屬性。通過這些步驟,我們成功實現了一個簡單的數據綁定示例。 ...
  • 是在MVVM中用來傳遞消息的一種方式。它是在MVVMLight框架中提供的一個實現了IMessenger介面的類,可以用來在ViewModel之間、ViewModel和View之間傳遞消息。 Send 接受一個泛型參數,表示要發送的消息內容。 Register 方法用於註冊某個對象接收消息。 pub ...
  • 概述:在WPF中,通過EventHandler可實現基礎和高級的UI更新方式。基礎用法涉及在類中定義事件,併在UI中訂閱以執行更新操作。高級用法藉助Dispatcher類,確保在非UI線程上執行操作後,通過UI線程更新界面。這兩種方法提供了靈活而可靠的UI更新機制。 在WPF(Windows Pre ...
  • 概述:本文介紹了在C#程式開發中如何利用自定義擴展方法測量代碼執行時間。通過使用簡單的Action委托,開發者可以輕鬆獲取代碼塊的執行時間,幫助優化性能、驗證演算法效率以及監控系統性能。這種通用方法提供了一種便捷而有效的方式,有助於提高開發效率和代碼質量。 在軟體開發中,瞭解代碼執行時間是優化程式性能 ...
  • 概述:Cron表達式是一種強大的定時任務調度工具,通過配置不同欄位實現靈活的時間規定。在.NET中,Quartz庫提供了簡便的方式配置Cron表達式,實現精準的定時任務調度。這種靈活性和可擴展性使得開發者能夠根據需求輕鬆地制定和管理定時任務,例如每天備份系統日誌或其他重要操作。 Cron表達式詳解 ...
  • 概述:.NET提供多種定時器,如System.Windows.Forms.Timer適用於UI,System.Web.UI.Timer用於Web,System.Diagnostics.Timer用於性能監控,System.Threading.Timer和System.Timers.Timer用於一般 ...
  • 問題背景 有同事聯繫我說,在生產環境上,訪問不了我負責的common服務,然後我去檢查common服務的health endpoint, 沒問題,然後我問了下異常,timeout導致的System.OperationCanceledException。那大概率是客戶端的問題,會不會是埠耗盡,用ne ...
  • 前言: 在本篇 Taurus.MVC WebMVC 入門開發教程的第四篇文章中, 我們將學習如何實現數據列表的綁定,通過使用 List<Model> 來展示多個數據項。 我們將繼續使用 Taurus.Mvc 命名空間,同時探討如何在視圖中綁定並顯示一個 Model 列表。 步驟1:創建 Model ...