深入淺出Dotnet Core的專案結構變化

老王Plus發表於2021-01-13

有時候,越是基礎的東西,越是有人不明白。

前幾天Review一個專案的程式碼,發現非常基礎的內容,也會有人理解出錯。

今天,就著這個點,寫一下Dotnet Core的主要型別的專案結構,以及之間的轉換和演化。

一、最基礎的應用Console

控制檯應用,是Dotnet Core乃至前邊的Dotnet Framework中,最基礎的專案。

我們來建立一個Console專案看一下:

% dotnet new console -o demo

建立完成後,開啟工程。工程裡只有一個檔案Program.cs,裡面只有一個方法Main

namespace demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

在Dotnet Core所有型別的專案中,Program.cs都是最開始的入口,main方法,也是最開始的入口方法。

這個工程中,還有一個檔案也需要了解一下,demo.csproj,這是這個專案的定義檔案:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

這裡面,OutputType告訴編輯器這個工程編譯後可以直接執行,TargetFramework定義執行的框架。

注意,這個框架字串有個對照表:net5.0對應的是.Net 5.0;如果你想用Dotnet Core 3.1,對應的字串是netcoreapp3.1,而不是net3.1。準確的說,3.1是.Net Core 3.1,而5.0是.Net 5.0。不用太糾結,微軟的命名規則而已。

    為了防止不提供原網址的轉載,特在這裡加上原文連結:https://www.cnblogs.com/tiger-wang/p/14267942.html

這就是控制檯應用Console的初始狀態。

下面,我們看看這個工程如何轉變為Web應用。

二、轉為Web應用

第一件事,我們需要改動demo.csproj專案定義檔案。

Web應用跑在WebHost上面,而不是從直接執行。所以,我們需要把OutputType項去掉。

另外,SDK也需要改一下。Console我們用的是Microsoft.NET.Sdk,Web應用要改成Microsoft.NET.Sdk.Web

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

改完儲存。

這時候,應該可以注意到,專案的發生了變化:

  • 依賴的框架從Microsoft.NETCore.App變成了兩個,多了一個Microsoft.AspNetCore.App,表明現在這是一個Asp.net Core的應用;
  • 專案中自動生成了一個目錄Properties,下面多了一個檔案launchSettings.json。這個檔案大家應該很熟悉,就不解釋了。

這時候,應用已經從Console轉為了Web應用。

Asp.Net Core框架提供了Host供Web載入。我們需要做的,是把Host構建器加到程式中。通常,我們需要兩個構建器:

  • 通用主機 Generic host builder
  • Web主機 Web host builder

1. 配置通用主機

通用主機在Microsoft.Extensions.Hosting.Host中,主要給Web應用提供以下功能:

  • 依賴注入
  • 日誌
  • 配置 IConfiguration
  • IHostedService實現

加入通用主機很簡單,就一個方法CreateDefaultBuilder

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

2. 配置Web主機

Web主機才是真正與Web相關的內容,主要實現:

  • Http支援
  • 設定Kestrol伺服器為Web伺服器
  • 新增IIS支援

加入Web主機,也是一個方法ConfigureWebHostDefaults

class Program
{
    static void Main(string[] args)
    {
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
            })
            .Build()
            .Run();
    }
}

這個方法用來新增Http請求管道並注入我們需要的服務。而注入我們需要的服務,就是我們最常見的Startup.cs的內容。

下面,我們先建立Startup.cs

namespace demo
{
    public class Startup
    {
    }
}

在前邊ConfigureWebHostDefaults中,加入Startup,並補齊程式碼:

class Program
{
    static void Main(string[] args)
    {
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .Build()
            .Run();
    }
}

這就是Program.cs中的完整程式碼了。整理一下,就是我們常見的樣子:

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

不過,到這兒還不能正常執行,因為Startup.cs現在還是空的。

3. 補齊Startup類

Startup類在Asp.net Core應用中有著重要的作用。這個類用於:

  • 使用DI容器注入服務
  • 設定Http Request管道以插入中介軟體

下面我們補齊所需的方法:

namespace demo
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
        }
    }
}

執行,到這兒,Web應用已經可以正常啟動了。

4. 給應用新增路由

Web應用啟動了,但裡面什麼也沒有,是空的。

要訪問Web應用中的任何資源,需要配置路由。這兒的路由,基本上就是傳入Http請求與資源之間的對映。

我們可以用下面的中介軟體來啟動路由:

  • UseRouting
  • UseEndpoints

加一下試試:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    app.UseEndpoints(endpoint => {
        endpoint.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello from Demo");
        });
    });
}

這次執行,瀏覽器中就看到正確的輸出了。

我們可以用MapGet對映更多資源:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    app.UseEndpoints(endpoint =>
    {
        endpoint.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello from Demo");
        });
        endpoint.MapGet("/test", async context =>
        {
            await context.Response.WriteAsync("Hello from Demo.Test");
        });
        endpoint.MapGet("/about", async context =>
        {
            await context.Response.WriteAsync("Hello from Demo.About");
        });
    });
}

到這兒,我們成功地把Console應用轉為了Web應用。

三、延伸內容

上面完成的Web應用,算是Web應用中的基礎。基於這個內容,我們還可以擴充套件到別的專案結構。

1. 改為MVC應用

需要在ConfigureServices 中注入AddControllersWithViews,並在Configure中新增MapDefaultControllerRoute

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoint =>
        {
            endpoint.MapDefaultControllerRoute();
        });
    }
}

2. 改為WebAPI應用

需要注入AddControllersMapControllers

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoint =>
        {
            endpoint.MapControllers();
        });
    }
}

3. 改為Razor應用

需要注入AddRazorPagesMapRazorPages

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoint =>
        {
            endpoint.MapRazorPages();
        });
    }
}

四、總結

看下來,其實過程很簡單。通過這種方式,能更進一步理解Dotnet Core的專案結構以及應用的執行過程。

希望對大家能有所幫助。

本文的配套程式碼在:https://github.com/humornif/Demo-Code/tree/master/0038/demo

微信公眾號:老王Plus

掃描二維碼,關注個人公眾號,可以第一時間得到最新的個人文章和內容推送

本文版權歸作者所有,轉載請保留此宣告和原文連結

相關文章