本文參考ASP.NET5 官方文檔 Understanding ASP.NET 5 Web Apps,加入了一些個人理解,理解不對的地方希望大家能指出,互相學習。
ASP.NET 5 針對WEB編程引入了幾個新的基本概念,理解這些概念對快速開發WEB應用來說很重要。或許這些這些概念對你來說不是新的,但是對那些使用ASP.NET 和 Visual Studio 進行傳統的WEB應用開發的程序員來說,這些概念可能是新的。
本文主要內容包括:
-
ASP.NET 項目結構
-
Framework 運行時
-
project.json 文件
-
global.json 文件
-
wwwroot 文件夾
-
客戶端依賴管理
-
服務端依賴管理
-
應用程序啟動
ASP.NET 項目結構
跟之前的ASP.NET解決方案相比,ASP.NET 5 多了一個 Solution Items 文件夾,里邊有一個global.json 文件,而 WEB 項目被放在一個 src 文件夾中。新的結構里有一個特殊的 文件夾,並增加了
這樣一個節點。
打開項目的根目錄,發現增加了若干個新文件: bower.json, appsettings.json, gulpfile.js, package.json, project.json 和Startup.cs等。
同時,細心的童鞋會發現 global.asax, packages.config, web.config 這些文件都不見了。在 ASP.NET之前的版本中這些文件保存了大量的應用程序配置信息。但在ASP.NET5,這些信息和邏輯已經被重構到了更小,更集中的文件里。
運行時目標框架
ASP.NET 5 可在兩種運行時環境中工作:傳統的.NET Framework 和新的 .NET Core,默認情況下,應用程序將使用 .NET Framework 的完整版本運行。但我們也可以選擇使用 .NET Core 版本。
你可以在項目上 右鍵>屬性 來查看當前項目使用的運行時。
.NET Core--- 是 .NET Framework 一個子集,是一個新的,模塊化的(利用NuGet),跨平台的更小體積的運行時。使用 .NET Core 你可以為你的每一個應用程序部署其專有的.NET 運行時,也就是說你的應用程序將以部署的運行時版本運行,而不是以主機操作系統上安裝的運行時版本運行。一個應用程序的運行時的版本可以和其他應用程序的運行時版本不同並且可以並行運行。如果有需要你可以更新某個應用程序的運行時,但不會影響其他的應用程序。這將使得應用程序部署和架構更新變得更加簡單,而且較少影響運行在系統上的其他應用程序。
.NET Framework--- 目前.NET Core的API較之完整的.NET Framework還有很多的不足,因此大多數傳統的應用程序在ASP.NET 5 下只能使用完整版本的 .NET Framework運行,原因就是它們依賴的一些組件或類庫在.NET Core 中還沒有。 使用 .NET Framework 現有的應用程序和庫將繼續在運行時工作而不需要任何更改。
project.json 文件
這是 ASP.NET 5 新增的一個文件,它描述了項目的基本信息,依賴關系等。
{ "userSecretsId": "aspnet5-FeatureVote-bd1ba2ae-0e4f-4e48-8ffc-fe223c1dc3cd", "version": "1.0.0-*", "compilationOptions": { "emitEntryPoint": true }, "dependencies": { "Microsoft.ApplicationInsights.AspNet": "1.0.0-rc1", "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final", "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", "Microsoft.AspNet.Mvc": "6.0.0-rc1-final", "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final", "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final", "Microsoft.Extensions.Configuration": "1.0.0-rc1-final", "Microsoft.Extensions.Configuration.FileProviderExtensions" : "1.0.0-rc1-final", "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final", "Microsoft.Extensions.Logging": "1.0.0-rc1-final", "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final", "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final", "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final" }, "commands": { "web": "Microsoft.AspNet.Server.Kestrel --server.urls=http://localhost:5000" }, "frameworks": { "dnx461": { }, "dnxcore50": { } }, "exclude": [ "wwwroot", "node_modules" ], "publishExclude": [ "**.user", "**.vspscc" ], "scripts": { "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ] } }
-
userSecretsId 是應用程序的一個唯一ID,好像是和加密存儲數據有關,具體還不了解。
-
version 描述版本信息。
-
compilationOptions 里邊存放應用程序的編譯選項,如 emitEntryPoint 用來告訴編譯器這是一個應用程序還是一個類庫,如果是一個應用程序,則項目代碼里便必須要有
public static void Main()
方法(見Startup.cs 里邊的public static void Main(string[] args) => WebApplication.Run<Startup>(args);
)。 -
另外你還可以指定有關該項目的其他信息,如作者(authors )和說明(description)等。
-
dependencies 描述了項目的依賴關系,依賴項可以是 NuGet 包也可以是其它項目,依賴項版本可以具體制定,也可以使用通配符,使用通配符的時候ikeyi指定大版本,在小版本更新的時候會自動獲取最新的小版本(有點像nodenode的包)。
-
commands ASP.NET 5 支持很多命令行工具,該節點配置可以在命令行中運行的命令(例如,啟動一個網站或運行測試)。
-
frameworks 該部分指定編譯使用的目標框架和一些依賴關系。
-exclude 用於標記在編譯時排除的部分。 -
publishExclude 用於標記在發布網站時排除的部分。
-
scripts 描述自動化構建時的腳本。
global.json 文件
這個文件用來存放解決方案的總體配置信息,默認包含兩個配置節:projects
和 sdk
{ "projects": [ "src", "test" ], "sdk": { "version": "1.0.0-rc1-update1" } }
-
projects,指定在哪個文件夾里存放項目的源碼
-
sdk,指定Visual Studio打開解決方案時將使用的DNX(.Net Execution Environment)的版本。它在這里設置,而不是在project.json,是為了避免出現一個解決方案中的不同項目使用不同版本的SDK的情況。
wwwroot 文件夾
在ASP.NET 的早期版本中,項目所在的文件夾就是WEB 應用程序的根目錄,url請求對應着具體的文件,如http://xxxx/default.aspx
, 在后期的版本中,路由概念的加入使url 和 具體文件分離。 但是靜態文件的加載(js文件,css文件等)仍然基於它們的目錄結構。
這種基於文件的訪問方式存在很多問題,比如 如何保護項目的敏感文件不被訪問(如:web.config,global.asax),之前一般是采用黑名單的方式保證一些特定的文件或者文件類型不被訪問,但是這種方式比白名單的方式安全性要低。 ASP.NET 5還解決了某些文件在測試環境和生產環境是不同版本的問題(如:web.config)。
ASP.NET 5 的wwwroot 就是 WEB應用運行時的目錄,一些靜態文件,像appsettings.json 沒有放在
里邊,也就不用擔心會被訪問到,因此也沒有必要創建特殊規則來阻止訪問敏感文件。 ASP.NET 5 采用白名單的方式,即只有在wwwroot文件夾中的文件才可以通過Web請求訪問。wwwroot文件夾是默認的Web 應用所在的文件夾,如果要使用指定的文件夾,可以在project.json 里配置。
客戶端依賴管理
該依賴項文件夾里包含兩個子文件夾:bower 和 NPM,這是兩個包管理器,他們負責管理獲取客戶端的依賴項。 展開文件夾,可以看到每個工具目前管理的依賴項及其版本。
bower 和 NPM 的具體功能網上有很多介紹,這里不做詳細描述。
服務器端依賴管理
在解決方案資源管理器的引用文件夾下詳細展示了項目的引用項。這應該是大家比較熟悉的。不同點是它引用了兩個目標框架:完整的 DNX 4.5.1和 DNX Core 5.0,每個目標框架都有各自的引用關系,並且通過圖標可以區分出來引用的是一個組件還是一個NuGet 資源包或者是其它項目。這些依賴將在編譯的時候進行檢查,丟失的依賴項會從配置的NuGet包源(工具>NuGet包管理器>程序包管理器設置>程序包源)進行下載。
應用程序啟動
ASP.NET 5將程序分解為各種模塊,這些模塊可以按需單獨的添加到WEB應用程序里邊。這使得程序更加精簡。 如果你使用空模板創建一個 ASP.NET 5 應用,你會發現 Startup.cs 文件只有簡單的幾行代碼。 默認的WEB項目里 startup
類 把 configuration, MVC, EF, Identity services, logging, routes等處理程序連接起來. 它提供了一個很好的例子展示如何配置使用你的ASP.NET應用程序。startup
類 樣例里邊包含三個部分:構造函數,ConfigureServices
和 Configure
Configure
方法在ConfigureServices
方法之后被調用,用於配置中間件。
public Startup(IHostingEnvironment env) { // Set up configuration sources. var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); if (env.IsDevelopment()) { // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 builder.AddUserSecrets(); } builder.AddEnvironmentVariables(); Configuration = builder.Build(); }
我們可以在構造函數里邊看到應用是如何處理配置文件的。Configuration 是 startup
類的一個屬性,配置信息可以從各種來源(如JSON、XML或環境變量)來獲取,默認的模板中使用ConfigurationBuilder
通過appsettings.json 和環境變量信息來創建一個IConfiguration
實例,您也可以編寫自己的自定義configuration provider
, 可參考 Configuration。ConfigureServices
方法被用來指定哪些服務被提供給應用程序使用。在默認的模板里添加了3種服務: EF, Identity 和 MVC ,這里你可以根據需要來添加自己的服務。
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddEntityFramework() .AddSqlServer() .AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddMvc(); // Add application services. services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>(); }
Configure
方法在ConfigureServices
之后被運行時調用,在示例項目中,Configure
調用控制台來做日志。為開環境添加了幾個有用的功能,添加了靜態文件、身份和MVC路由的支持,注意,只在ConfigureServices 中添加身份 和 MVC 還不夠,它們還需要通過調用Configure
在請求管道中配置。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); if (env.IsDevelopment()) { app.UseBrowserLink(); app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } else { app.UseExceptionHandler("/Home/Error"); // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859 try { using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>() .CreateScope()) { serviceScope.ServiceProvider.GetService<ApplicationDbContext>() .Database.Migrate(); } } catch { } } app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear()); app.UseStaticFiles(); app.UseIdentity(); // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715 app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
你能看到,配置哪些服務是可用的,以及如何配置請求管道這些都完全是由Startup
類來完成,而不是使用 HTTP 模塊和通過web.config來配置處理程序。更多的信息,請參閱應用程序的啟動、配置和基本原理.