1. 程式人生 > >ASP.NET Core 2.0 : 三. 專案結構

ASP.NET Core 2.0 : 三. 專案結構

原文: ASP.NET Core 2.0 : 三. 專案結構

本章我們一起來對比著ASP.NET Framework版本看一下ASP.NET Core 2.0的專案結構.(此後的文章也儘量這樣對比著, 方便學習理解.)

關注差異, 也為專案遷移做準備.

ASP.NET Core 系列目錄

新建專案, 選擇型別

新建專案, 選擇.NET Core 有如下幾種型別可選, 分別是Console, ASP.NET Core 的空專案, Web API

我們選擇ASP.NET Core Web App(MVC), 沒有標註MVC的是採用Razor pages 的專案.

 

專案結構圖

新建的專案結構如下圖所示, 大體上和ASP.NET 的Framework版本差不多, 現在按照圖上的數字標記逐一做一下介紹(Controller、Model就不介紹了, View中單獨介紹一下幾個特殊View).

按照標註的數字逐個做一下簡單介紹, 先了解大概是幹什麼用的, 後面的文章會做詳細的研究.

介紹的時候我會對比大家熟悉的ASP.NET Framework版本, 方便理解.

① Dependencies 依賴項

這裡主要分兩部分, NuGet和SDK, 目前這兩部分下面都只有一項.

Nuget:

包含Microsoft.AspNetCore.All, 展開它看一下, 裡面MVC、Razor、EF以及SQLLite都要,

官方這樣說: 它包含了

  • ASP.NET Core 團隊支援的所有包。
  • Entity Framework Core 支援的所有包。
  • ASP.NET Core 和 Entity Framework Core 使用的內部和第三方依賴關係。 

猛地一看, 這是一非常大而全的包了, 和之前說的模組化有點不一致, 而且無緣無故的讓自己的專案引用了一些根本用不到的程式集, 非常不爽.

其實這些程式集不會隨著專案釋出一起出現在部署包中, 不止沒引用的, 包括引用的也不會. 這些已經存在於部署環境中了, 所以釋出包不會變大反而會變小, 不必擔心.

SDK:

SDk中包含了一項: Microsoft.NETCore.App, 它是.NET Core 的部分庫。 也就是 .NETCoreApp 框架。 它依賴於更小的 NETStandard.Library

相對於上面的Microsoft.AspNetCore.All, 它同樣是包含了一些程式集.但它似乎更"基礎"一些.

二者異同

Microsoft.AspNetCore.All中大部分都是Microsoft.開頭的一些程式集, 而Microsoft.NETCore.App中出現的大多數是我們熟悉的system.XXX的.

二者的關係就像ASP.NET相對於.NET, 此處是Asp.NetCore相對於.Net Core. 

SDK同樣是一個大而全的集和, 在部署的時候, SDK中的引用依然不會出現在部署包中, 如下圖, 是不是很精簡

 

② launchSettings.json

顧名思義, 這是一個啟動配置檔案, json格式的. 通過上面的專案結構圖可以發現, 常見的web.config或app.config等xml格式的config檔案找不到了,

都是json. 開啟這個json看一下. 一項項的不好解釋, 後來發現windows 中的 vs2017有個圖形化的配置介面(右鍵當前專案->屬性->除錯),

一個個介紹太麻煩了, 直接上圖感受一下.

圖下部分的Web伺服器配置是我們熟悉的URL、身份認證以及SSL等配置.

圖的上部分對應json中的profiles中定義的兩種配置,分別以IIS Express和以當前專案名HelloCore命名.

切換該選項下面的配置項也會隨之改變, 相當於是兩個頁, 每頁中的配置對應json中相應的節點. 

 

③ _Layout.cshtml

佈局模板, 簡單的說就是所有采用此模板的頁面擁有大體一致的佈局, 

舉個例子, 我們的頁面經常是這樣的結構:

Header、Footer和Navigation基本上是不變的, 開啟_Layout.cshtml, 我們可以看到一個@RenderBody()標識, 它其實就是來定義Content部分的, 

繼承此模板的頁面只需要提供這部分內容即可.

當然, 常見的還有類似@RenderSection("Scripts", required: false)這樣的標識, 引用此模板的頁面可以將該頁的特定JS的引用放在對應的Section中.

引用此模板, 只需在頁首如下配置即可.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

每個頁都配置比較麻煩? ⑥ _ViewStart.cshtml 會幫忙.

④ _ValidationScriptsPartial.cshtml

<environment include="Development">
    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>

開啟此頁面, 可以看到一些這樣的引用, validation 顧名思義是用來做驗證的, 我們經常看到這樣的頁面

當輸入的格式不正確的時候, 給出提示, 最早我們經常是在輸入後或者提交前用js將輸入的內容正則驗證一下, 

這個不用那麼麻煩了, 我們通過如下程式碼引用_ValidationScriptsPartial.cshtml, 也就是採用jquery-validation來做驗證

@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")
}

注意: 預設的_Layout模板是未引用的, 因為不是所有頁面都需要有輸入操作.

Model中設定驗證方式

        [Required(ErrorMessage ="使用者名稱不能為空!")]
        [Display(Name = "使用者名稱")]
        public string UserName { get; set; }

        [EmailAddress(ErrorMessage ="Email格式不正確!")]
        [Required]
        [Display(Name = "EMail")]
        public string EMail { get; set; }

在頁面新增驗證即可:

<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
    <label asp-for="Email"></label>
    <input asp-for="Email" class="form-control" />
    <span asp-validation-for="Email" class="text-danger"></span>
</div>

validation細化起來內容還很多, 此處只是大概介紹一下, 後文會專題研究.

⑤ _ViewImports.cshtml

先不說這個, 再說一個消失了的Web.config. 就是Framework版本的MVC專案中的View目錄下的那個.

在View中引用Model等的時候, 為了避免寫using .... , 我們可以在這個config中新增這些引用

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="FrameworkMVCTest" />
        <add namespace="FrameworkMVCTest.Model" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

現在開啟_ViewImports.cshtml,

@using HelloCore
@using HelloCore.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

這裡其實就是實現了上面的功能.

有一個比較特別的地方就是比原版MVC多了個@addTagHelper

在上文的validation中我們看到過這樣的程式碼

    <label asp-for="Email"></label>
    <input asp-for="Email" class="form-control" />
    <span asp-validation-for="Email" class="text-danger"></span>

原來我們是這樣寫的

@Html.LabelFor(m => m.EMail)
@Html.EditorFor(m => m.EMail)
@Html.ValidationMessageFor(m=>m.EMail)

初步看來這個 TagHelper 和 HtmlHelper 有點像, 具體先了解這麼多, 後文細化.

⑥ _ViewStart.cshtml

這個開啟就一句話,

@{
    Layout = "_Layout";
}

這個頁面中的內容會在所有View執行前執行, 現在這句話就是給所有的View一個預設的Layout模板.

所以在View中這樣寫

@{
    Layout = null;
}

和這樣寫

@{

}

是不一樣的, 第一種是告訴這個View不採用任何模板.

第二種寫法是什麼都不幹, 所以它會採用_ViewStart.cshtml中指定的模板.

 

當然, 這個_ViewStart.cshtml的作用不只是寫這麼一句話, 我們還可以在這寫一些其他需要"通用"執行的內容.

⑦ wwwroot

看這名字好像是IIS的預設網站根目錄, 它包含了所有的"前端"的靜態檔案,  css、image、JS以及一個名為lib的資料夾.

lib中預設內容是bootstrap和jquery.

在Startup中, 會呼叫一個無引數的UseStaticFiles()方法, 將此目錄標記到網站根目錄.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //.....        
    app.UseStaticFiles();
    //.....

}

具體靜態檔案的路徑及相關自定義配置, 授權等後文詳細研究.

⑧ appsettings.json和appsettings.Development.json

這就是原來的framework版本的MVC的Web.config檔案了.

不過這個算是夠精簡的了, 預設情況沒幾句話,只有對於log日誌的相關配置,

當然正常專案中我們要配置的肯定不止這一點, 舉個例子, 資料庫連線

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

 

⑨ bundleconfig.json

預設檔案內容如下:

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    // Optionally specify minification options
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    // Optionally generate .map file
    "sourceMap": false
  }
]

 

這裡主要涉及兩個概念:

1.Bunding

     可以理解為繫結或者合併, 也就是把幾個檔案合併成一個大檔案, 減少請求次數.

     上文的程式碼可以看到, inputFiles 是一個數組, 而outputFileName 是一個單獨的檔名, 

  以css為例, inputFiles裡面已經有一個檔案 wwwroot/css/site.css, 假如現在頁面還需要一個wwwroot/css/skin.css,

  如果不做合併, 頁面開啟的時候就需要分別請求這兩個檔案, 做了合併之後, 即將這個skin.css檔案也寫入陣列中, 只要請求

  /css/site.min.css這一個檔案即可. 

2.Minification

  翻譯為縮減, 即將程式碼中註釋和多餘空格等刪除, 甚至將變數名改為一個字元來縮減檔案的大小.

      例如下面的JS程式碼

AddAltToImg = function (imageTagAndImageID, imageContext) {
    ///<signature>
    ///<summary> Adds an alt tab to the image
    // </summary>
    //<param name="imgElement" type="String">The image selector.</param>
    //<param name="ContextForImage" type="String">The image context.</param>
    ///</signature>
    var imageElement = $(imageTagAndImageID, imageContext);
    imageElement.attr('alt', imageElement.attr('id').replace(/ID/, ''));
}

      縮減後的程式碼:

AddAltToImg=function(n,t){var i=$(n,t);i.attr("alt",i.attr("id").replace(/ID/,""))};

      一下就減少了好多.

通過以上兩種方式組合不但減少了請求次數,還減小了請求的靜態檔案的總大小, 從而提高載入時間和效能.

 

在上文檢視_layout模板檔案的時候我們就見過這樣的程式碼:

 

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>

詳細的配置說明暫時不說, 大概的意思就是在Development模式下載入未繫結和縮減的檔案, 方便閱讀和除錯.

和非Development情況下,載入處理過的檔案來提高效能.

⑩ Program.cs

    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }

這裡有一個非常熟悉的Main方法, 也就是應用的起點, 啟動後通過UseStartup<Startup>()指定下文的Startup啟動檔案進行啟動.

⑪ Startup.cs

這是Mvc Core非常重要的地方, 包括載入配置, 通過依賴注入載入元件, 註冊路由等都在此處進行.

預設的程式碼中:

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

            app.UseStaticFiles(); //指定靜態檔案

//設定路由 app.UseMvc(routes
=> { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }

如上圖所示, 預設情況下設定了兩種不同狀態下的錯誤頁, 指定靜態檔案並且設定了路由.

在這裡, 我們可以向管道中通過中介軟體的方式插入我們需要的工作內容.

比如我們還可以用app.UseAuthentication()來做身份驗證.

 

我們使用 UseRun 和 Map 來配置 HTTP 管道。 

Use 方法可使管道短路(即不呼叫 next 請求委託)。 

Run 是一種約定,並且某些中介軟體元件可公開在管道末尾執行的 Run[Middleware] 方法。

Map* 擴充套件用作約定來建立管道分支。

 

此處涉及內容非常多, 比如管道機制、路由註冊、身份認證等都需要專題研究.

⑫ .bowerrc和bower.json 

bower是一款優秀的前端包及依賴管理工具,.bowerrc指定了檔案位置, bower.json則進行了詳細的配置,如下面的bootstrap和jquery

{
  "name": "asp.net",
  "private": true,
  "dependencies": {
    "bootstrap": "3.3.7",
    "jquery": "2.2.0",
    "jquery-validation": "1.14.0",
    "jquery-validation-unobtrusive": "3.2.6"
  }
}

 詳細的使用方法就不在這裡介紹了.

 

小結:

剛新建的專案的結構大體就是這樣,  主要功能介紹完了就是一個個詳細研究了.

 

ASP.NET Core 系列目錄