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

本文地址:http://www.javashuo.com/article/p-orrcfkke-kb.html前端

O 前請提要

在第1期構建項目以後,咱們看到項目中有這樣的組成結構:web

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中。json

小提示:
儘管C#並不像Java那樣強制要求必須將各個數據實體分放到不一樣的文件中,但C#依然要求定義類的代碼文件必須和該文件中所定義的類(若是多個則任取其一)相同。此外,如非必要,咱們仍然建議將各個類定義分離到不一樣的文件中,除非:windows

  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>();
                });

這個函數的定義方式很特別,它使用了λ推演=>)的方式作的函數定義,但這可有可無,實際上表達的是:app

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 ...

相關文章
相關標籤/搜索