1. 程式人生 > >ASP.NET Core 執行原理

ASP.NET Core 執行原理

1.1. 概述

在ASP.NET Core之前,ASP.NET Framework應用程式由IIS載入。Web應用程式的入口點由InetMgr.exe建立並呼叫託管。以初始化過程中觸發HttpApplication.Application_Start()事件。開發人員第一次執行程式碼的機會是處理Application_StartGlobal.asax中的事件。在ASP.NET Core中,Global.asax檔案不再可用,已被新的初始化過程替代。

640?wx_fmt=png&wxfrom=5&wx_lazy=1

ASP.NET Core 應用程式是在.NET Core 控制檯程式下呼叫特定的庫,這是ASP.NET Core應用程式開發的根本變化。所有的ASP.NET託管庫都是從Program

開始執行,而不是由IIS託管。也就是說.NET工具鏈可以同時用於.NET Core控制檯應用程式和ASP.NET Core應用程式。

using System;
using Microsoft.AspNetCore.Hosting;

namespace aspnetcoreapp
{
    public class Program
    {
        public static void Main(string[] args)
        {
           var host = new WebHostBuilder()

               .UseKestrel() //指定宿主程式為Kestrel

               .UseStartup<Startup>()// 呼叫Startup.cs類下的Configure 和 ConfigureServices

               .Build();

           host.Run();
        }
    }
}

以上是Program類中Main方法的示例程式碼,Main方法負責初始化Web主機,呼叫Startup和執行應用程式。主機將呼叫Startup類下面的ConfigureConfigureServices方法。

1.2. 檔案配置

1.2.1. Starup檔案配置

對於一個ASP.NET Core 程式而言,Startup 類是必須的。ASP.NET Core在程式啟動時會從Program類中開始執行,然後再找到UseStartup<Startup>中找到配置的Startup的類,如果不指定Startup類會導致啟動失敗。

Startup中必須定義Configure

方法,而ConfigureServices方法則是可選的,方法會在程式第一次啟動時被呼叫,類似傳統的ASP.NET MVC的路由和應用程式狀態均可在Startup中配置,也可以在此初始化所需中介軟體。

Configure

在ASP.NET Core 應用程式中Configure方法用於指定中介軟體以什麼樣的形式響應HTTP請求。

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;

namespace aspnetcoreapp
{  
    public class Startup

    {      
        public Startup(IConfiguration configuration)    
        {
            Configuration = configuration;
        }    
  
        public IConfiguration Configuration { get; }        

   
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {                        
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();

                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles(); //允許應用程式提供靜態資源
                                   
            app.UseMvc(routes =>
            {
                routes.MapRoute(

                    name: "default",

                    template: "{controller=Home}/{action=Index}/{id?}");

            }); //將MVC新增到管道並允許配置路由
        }
    }
}

ASP.NET Core是通過對IApplicationBuilder進行擴充套件來構建中介軟體的, 上面程式碼中每個use擴充套件方法都是將中介軟體新增到請求管道。也可以給Configure方法附加服務(如:IHostingEnvironment)這些服務在ConfigureServices方法中被初始化。

用ASP.NET Core專案模板新增的應用程式,預設新增的幾個中介軟體:

  • UseStaticFiles 允許應用程式提供靜態資源。

  • UseMvc 將MVC新增到管道並允許配置路由。

ConfigureServices

ConfigureServices方法是應用程式執行時將服務新增到容器中,用ASP.NET Core專案模板的時候預設會將MVC的服務新增到容器中:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
}

接下來舉一個例子,在實際應用中ConfigureServices方法和Configure方法配合使用,在ASP.NET Core中有一個UI開發框架 Telerik UI for ASP.NET Core,它有60多個UI元件,不僅支援ASP.NET Core的跨平臺佈署模式,而且還支援前端自適應渲染。

當在專案中應用 Telerik UI 的時候,首先在專案中引用相關的包,然後再在ConfigureServices方法中將 Kendo UI 服務新增到容器中:

public void ConfigureServices(IServiceCollection services)
{
    services.AddKendo();
}

接下來,在Configure中設定Kendo UI

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseKendo(env);
}

1.2.2. appsetting.json配置

Configuration API 提供了一個基於鍵-值對來配置應用程式的方法,在執行時可以從多個來源來讀取配置。鍵-值對可以分組形成多層結構。鍵-值對可以配置在不同的地方,如:檔案、記憶體等,其中放在記憶體中不能持久化,這裡筆者選擇將其配置在appsetting.json檔案裡面。

配置appsetting檔案

{
 "key1": "字串",
 "key2": 2,
 "key3":true,

 "parentObj": {
   "key1": "sub-key1"
 },
 "members": [
   {
     "name": "Lily",
     "age": "18"
   },
   {
     "name": "Lucy",
     "age": "17"
   }
 ]}

一個分層結構的 JSON 檔案,鍵(如:key1)作為索引器,值作為引數,型別可以為:字串、數字、布林、物件、陣列。下面具體來看下在應用中怎樣使用。

在應用程式載入和應用配置檔案

public static IConfigurationRoot Configuration { get; set; }
public static void Main(string[] args = null)
{  
    var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json");

    Configuration = builder.Build();
    Console.WriteLine($"key1 = {Configuration["key1"]}");
    Console.WriteLine($"key2 = {Configuration["key2"]}");
    Console.WriteLine($"subkey1 = {Configuration["parentObj:key1"]}");
    Console.WriteLine();

    Console.WriteLine("members:");
    Console.Write($"{Configuration["members:0:name"]}, ");
    Console.WriteLine($"age {Configuration["members:0:age"]}");
    Console.Write($"{Configuration["members:1:name"]}, ");
    Console.WriteLine($"age {Configuration["members:1:age"]}");
    Console.WriteLine();

    Console.WriteLine("Press a key...");
    Console.ReadKey();
}

由於載入的是一個JSON檔案,所以檔案載入進來以後程式可以直接將它當作一個JSON物件來使用。如果有過動態語言使用經驗的同學來說這種方式就比較熟悉了。只在這裡訪問屬性的時候將平時常見的.變成了:,這和寫的JSON物件更接近。

1.3. 處理管道(中介軟體)

在ASP.NET Core應用程式中使用中介軟體,應用程式所做的任何事情(包括伺服器中的靜態檔案)都是由中介軟體來完成的。沒有任何中介軟體的應用程式在請求的出錯時候簡單返回404 Not Found。中介軟體可以讓您完全控制請求的處理方式,並且讓您的應用程式更加精簡。

當接收到一個請求時,請求會交給中介軟體構成的中介軟體管道進行處理,管道就是由多箇中間件構成,請求從一箇中間件的一端進入,從中介軟體的另一端出來,每個中介軟體都可以對HttpContext請求開始和結束進行處理。

在ASP.NET Core中可以用Run、Map和Use三種方式來配置HTTP管道。

Run 方法稱為短路管道(因為它不會呼叫 next 請求委託)。因此,Run方法一般在管道尾部被呼叫。Run 是一種慣例,有些中介軟體元件可能會暴露他們自己的 Run方法,而這些方法只能在管道末尾處執行。下面兩段程式碼是等效的,因為Use沒有呼叫next方法

Run方法示例程式碼

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   app.Run(async context =>
       {
            await context.Response.WriteAsync("environment " + env);
       });
}

Use方法不執行next時示例程式碼

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Use(async (context, next) =>
        {
            await context.Response.WriteAsync("environment " + env);

        });
}

在.NET Core 中約定了 Map* 擴充套件被用於分支管道,當前的實現已支援基於請求路徑或使用謂詞來進入分支。Map擴充套件方法用於匹配基於請求路徑的請求委託。Map只接受路徑,並配置單獨的中介軟體管道的功能。

private static void HandleMapUrl(IApplicationBuilder app)
{
    app.Run(async context =>
    {      
         await context.Response.WriteAsync("Map Url Test Successful");
    });
}
public void ConfigureMapping(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Map("/mapurl", HandleMapUrl);
}

上例中是一個用Map方法來接受路徑進入分支管道,也就是說所有基於 /mapurl 路徑請求都會被管道中的 HandleMapUrl 方法所處理;如果想用謂詞來進入中介軟體分支,則要使用 MapThen 方法。MapThen 方法允許以一種非常靈活的方式構建中間管道。比如可以檢測查詢字串是否具有 “branch” 來進入分支:

private static void HandleBranch(IApplicationBuilder app)
{
    app.Run(async context =>
    {      
        await context.Response.WriteAsync("Branch used.");
    });
}
public void Configure(IApplicationBuilder app)
{
    app.MapWhen(context => 
        {
            return context.Request.Query.ContainsKey("branch");
        }
    , HandleBranch);
}

1.4 總結

  • 這節講解了 ASP.NET Core 在執行時首先載入 Program 類下面的 Main 方法,在 Main 方法中指定託管伺服器,並呼叫 Startup 類中的 Configure 和 ConfigureServices 方法等完成初始化;
  • 在 ASP.NET Core 中 HTTP 請求是以中介軟體管道的形式進行處理,每個中介軟體都可以在 HTTP 請求開始和結束對它進行處理;
  • ASP.NET Core 可以構建跨平臺應用,服務執行在 Http.Sys(僅適用於Windows平臺)和 Kestrel 上,不需要用IIS進行託管,所以相比傳統 ASP.NET 來說效能更高效也更加靈活。

原文連結:https://blog.csdn.net/sD7O95O/article/details/78126384