1. 程式人生 > >初探ASP.NET Core 3.x (4) - 專案的重要組成

初探ASP.NET Core 3.x (4) - 專案的重要組成

目錄

  • O 前請提要
  • I 啟動部分
    • I.1 Program
    • I.2 Startup
      • I.2.1 這個類幹什麼呢??
      • I.2.2 特徵??
    • I.3 appsettings.json
    • I.4 launchSettings.json
  • II wwwroot目錄
    • II.1 靜態檔案??
  • III 常規目錄
    • III.1 Pages目錄和Views
      目錄
      • III.1.1 頁面??但是wwwroot裡不是也存放頁面了麼??
      • III.1.2 有什麼區別麼??
      • III.1.3 Shared子資料夾
    • III.2 Controller資料夾
    • III.3 Models資料夾
  • IV 其他

本文地址:https://www.cnblogs.com/oberon-zjt0806/p/12225807.html

O 前請提要

在第1期構建專案之後,我們看到專案中有這樣的組成結構:

MyASPWebApplication/
├─obj/
│ └─/一些檔案.../
├─Pages/
│ ├─Shared/
│ │ ├─_Layout.cshtml
│ │ └─_ValidationScriptsPartial.cshtml
│ ├─Error.cshtml
│ ├─Error.cshtml.cs
│ ├─Index.cshtml
│ ├─Index.cshtml.cs
│ ├─Privacy.cshtml
│ ├─Privacy.cshtml.cs
│ ├─_ViewImports.cshtml
│ └─_ViewStart.cshtml
├─Properties/
│ └─launchSettings.json
├─wwwroot/(empty)
├─appsettings.Development.json
├─appsettings.json
├─Program.cs
├─Startup.cs
└─MyASPWebApplication.csproj

這是初始生成專案所包含的目錄結構,這裡麵包含了很多東西,但是,我們還不清楚每個部分能做些什麼,充當怎樣的一個角色,以及哪些東西是最基礎的,這一節就來解決這些問題。
在第3期中我們從原理層面上了解了ASP.NET Core Web專案的一個基本的工作流程以及所包含的部分。

I 啟動部分

I.1 Program

按照絕大部分C#開發框架的慣例,Program類一般是程式的入口,裡面包含一個Main函式並被單獨放置於Program.cs中。

小提示:
儘管C#並不像Java那樣強制要求必須將各個資料實體分放到不同的檔案中,但C#依然要求定義類的程式碼檔案必須和該檔案中所定義的類(如果多個則任取其一)相同。此外,如非必要,我們仍然建議將各個類定義分離到不同的檔案中,除非:

  1. class Aclass B之間有比較大的實體關聯,例如依賴關係。
  2. class B只是class A的一個輔助工具性的類,例如class B只是針對class A的一個異常類等

ASP.NET Core產生的Program類如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

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

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

當然了,這裡public static void Main(string[] args)自然就是程式的入口了。裡面呼叫了他的下一個成員函式:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

這個函式的定義方式很特別,它使用了λ推演(=>)的方式做的函式定義,但這無關緊要,實際上表達的是:

public static IHostBuilder CreateHostBuilder(string[] args)
{
    IHostBuilder _ = Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults
    (
        webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        }
    )
}

這個函式主要呼叫了Host.CreateDefaultBuilder(args)靜態函式使用程式的引數針對服務主機(Host)的進行一個預設配置。綜上,Program類作為程式的入口,其所包含的配置內容大多面向於專案的頂層設施。

關於服務主機(泛型主機、Web主機)的相關概念以及配置過程,在以後期介紹。

I.2 Startup

在上面的結構中,我們不得不注意的另外專案便是Startup.cs。當然了,本著C#的開發原則,我們很容易瞭解到這個程式碼檔案中應當包含一個名為Startup的類。

Startup類位於當前專案的名稱空間下(也就是說類全稱為MyASPWebApplication.Startup)。這個類在專案被構建時被生成為這個樣子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace MyASPWebApplication
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

I.2.1 這個類幹什麼呢??

如你所見,這個類並不繼承於任一個其他的現有類,就是一個非常中規中矩的C#類。但事實上,這個類包含了這個Web應用程式被啟動時執行的配置行為。

為什麼一個普通的類就可以支配整個專案的配置呢?事實上,儘管被定義為一個普通的類,但Startup還是有一些特徵的。

I.2.2 特徵??

很明顯,這個類的定義相當簡單,除了建構函式外只有兩個函式和一個只讀屬性:

public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

這兩個成員函式的內容,表明了Startup的配置主要是兩個方面:

  1. ConfigureServices函式以控制反轉(IOC)的方式依賴注入(DI)專案中的 服務、
  2. Configure函式負責配置請求應用管道

這裡面出現了很多概念,比如管道、控制反轉、依賴注入之類的,這將在之後期中慢慢解釋。總之,這些內容是在WebApp執行期間被動態載入的配置。

而這個類最大的玄機在於,它在Program類中被引用過:

//---- Program.cs(節選) ----//
public static IHostBuilder CreateHostBuilder(string[] args)
{
    IHostBuilder _ = Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults
    (
        webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        }
    )
}

第8行中,webBuilder.UseStartup<Startup>()就通過webBuilder載入了這個類作為預設的Host配置。這也正是為什麼Startup作為一個普通的類就能夠作為配置類的原因。

I.3 appsettings.json

終於,我們聚焦於不是C#類的一個主要檔案了。這是一個json表格式的配置檔案。

當然,我們實際上能看到兩個檔案:appsettings.jsonappsettings.Development.json。這兩個檔案的作用實際上沒有什麼實質性不同,只是應用的場合並不相同。當專案的執行環境為開發態(Development)的時候,優先使用appsettings.Development.json,否則使用另外一個。

初始狀態下,appsettings.json的內容為:

{
  "Logging": 
  {
    "LogLevel": 
    {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

這種檔案裡配置的內容多和資料有關。比如初始狀態下有的"Logging"子表包含了對日誌記錄的配置資訊。當然,又如當該WebApp使用資料庫時,有關資料庫的連線資訊(連線字串、超時等)也會被配置到這個json表中。

當然,在這張表中,我們也可以加入自己的配置資訊,在程式中可以通過Microsoft.Extensions.Configuration.IConfiguration物件讀取這個檔案裡的配置資訊。

關於此檔案中包含的配置項和配置方法也會在以後詳細探索。

I.4 launchSettings.json

這個檔案存在於Properties資料夾下,定義了專案的屬性:

{
  "iisSettings": {
    "windowsAuthentication": false, 
    "anonymousAuthentication": true, 
    "iisExpress": {
      "applicationUrl": "http://localhost:64571",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "MyASPWebApplication": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

這個也屬於配置檔案,主要配置的是專案的執行環境,例如偵聽埠等、環境模式、是否執行瀏覽器以及IIS反向代理的轉發埠等。

比如,在這個配置模式下,當專案以IIS Express反向代理的方式執行時,就會訪問http://localhost:64571,但如果不使用IIS而直接使用Kestrel來啟動,那麼專案地址就是http://localhost:5000

II wwwroot目錄

另外一個比較顯著的目錄是wwwroot。如果使用Visual Studio建立專案,我們能夠看到,這個wwwroot目錄和Properties目錄類似,有個特別的圖示:

這裡面目前是空的,不過這裡一般用於放置靜態檔案(Static Files)。

II.1 靜態檔案??

說白了,就是在執行期間不會發生變化的,一般是指資原始檔。
比如:靜態網頁(HTML)、靜態樣式表(CSS)、靜態瀏覽器指令碼(JS)、圖片、音訊等等等等。
wwwroot這個目錄就是放這些東西進去的。

服務端處理這些靜態檔案是通過StaticFiles這一中介軟體組成的。

// ---- Startup.cs(節選) ---- //

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }

第14行就是Startup類中對此中介軟體的註冊。

III 常規目錄

為了使專案更為有序的組織,一些檔案會被存放於一些目錄(資料夾)中,而這些目錄在ASP.NET Core下有約定的名稱。

III.1 Pages目錄和Views目錄

Pages資料夾存放的內容被稱為頁面,這裡用於存放Razor Pages開發模式下的Razor頁面。

Razor Pages是ASP.NET Core 2.x中提出的一種新的開發模式,聚焦於頁面,並以頁面為中心。

在MVC開發模式下,這個部分被替換為檢視,存放於Views資料夾中。儘管兩者之間有所不同,但我們目前要知道的是,這個資料夾裡的東西聚焦於前端。

III.1.1 頁面??但是wwwroot裡不是也存放頁面了麼??

是的,但是wwwroot裡面存放的是靜態頁面,而這裡面存放的頁面被稱為Razor頁面,是一種動態頁面。

III.1.2 有什麼區別麼??

當然有區別。雖然說這兩者到瀏覽器客戶端都會被解析為同樣的東西,但是對於服務端而言,這兩者有很大的區別。

存放於wwwroot中的頁面簡單來說就是寫死的頁面,這種頁面無論執行多少次,服務端資料如何變化,其頁面結果是不變的。

但動態頁面是不一樣的,動態頁面是保留了一定不變內容基礎之上又根據後端資料變化而被重新生成的。在瀏覽器上就被體現為,隨著後臺資料的變化,頁面的顯示結果會有所不同。

III.1.3 Shared子資料夾

無論是Pages還是Views,因為都存放帶有Razor標記的頁面,所以這兩個目錄下往往還有一個子目錄,稱為Shared。這個目錄主要存放的是共享的分部標記元素(我知道聽不明白,以後會解釋的)。

III.2 Controller資料夾

這個資料夾僅存在於MVC模式下,存放MVC模式當中的控制器(Controller,MVC中的C)。

控制器是一種特殊的類,ASP.NET Core中約定控制器類以Controller結尾。

在MVC中,控制器主要用於處理請求(Request)和路由(Routing)並提供響應。作用有些類似於Java中的Servlet。(具體內容和其他概念的以後介紹,以後介紹)

III.3 Models資料夾

如果WebApp關聯了資料庫,那麼資料庫中的資料必然存在一種資料模型,這種資料模型在關係理論中稱為關係模式,它實際上與面向物件理論中的類是對應的。

一般來說因為資料庫的資料組織方式和應用中組織方式的這種不同,因此在專案中處理這些資料就必須自己編寫資料訪問(DA)功能將資料庫中的關係元組轉化成應用可以使用的類物件,但是一個Web專案中的資料門類非常的多,這也就造成了關係模式也非常的多,要編寫的內容也就非常的多,那麼為了統一地、自動地處理和顯示這些資料,減輕重複編碼的負擔,一種稱為物件關係對映(ORM)的資料開發模式就產生了。

ORM的機制使得我們只需要在程式中寫出資料模型(類定義),而無需提供存取方法(這個由ORM提供,這個過程也被稱為資料繫結)。那麼Models目錄就是為了存放這些資料模型的。

IV 其他

除了上面這些之外,還有其他的東西,遇到再說。

To be continued ...