ASP.NET Core項目為開發人員提供了面向 .NET Core 和/或 .NET Framework 的靈活性。 若要確定最合適的目標框架,請參閱《從.NET Framework遷移到.NET Core/.NET5的技術指南》。
面向 .NET Framework 時,項目需要引用單個 NuGet 包。
得益於有 ASP.NET Core 元包,面向 .NET Core 時可以避免進行大量的顯式包引用。 在項目中安裝 Microsoft.AspNetCore.App
元包:
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.App" /> </ItemGroup>
使用此元包時,應用不會部署元包中引用的任何包。 .NET Core 運行時存儲中包含這些資產,並已預編譯,旨在提升性能。 如需了解更多詳情,請參閱用於 ASP.NET Core 的 Microsoft.AspNetCore.App 元包。
ASP.NET Core 中簡化了 .csproj 文件格式。 下面是一些顯著的更改:
-
無需顯式添加,即可將文件視作項目的一部分。 服務於大型團隊時,這可減少出現 XML 合並沖突的風險。
-
沒有對其他項目的基於 GUID 的引用,這可以提高文件的可讀性。
-
無需在 Visual Studio 中卸載文件即可對它進行編輯:
ASP.NET Core 引入了啟動應用的新機制。 ASP.NET 應用程序的入口點是 Global.asax 文件。 路由配置及篩選器和區域注冊等任務在 Global.asax 文件中進行處理。
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } }
此方法會將應用程序和應用程序要部署到的服務器耦合在一起,並且它們的耦合方式會干擾實現。 為了將它們分離,引入了 OWIN 來提供一種更為簡便的同時使用多個框架的方法。 OWIN 提供了一個管道,可以只添加所需的模塊。 托管環境使用 Startup 函數配置服務和應用的請求管道。 Startup
在應用程序中注冊一組中間件。 對於每個請求,應用程序都使用現有處理程序集的鏈接列表的頭指針調用各個中間件組件。 每個中間件組件可以向請求處理管道添加一個或多個處理程序。 為此,需要返回對成為列表新頭的處理程序的引用。 每個處理程序負責記住並調用列表中的下一個處理程序。 使用 ASP.NET Core 時,應用程序的入口點是 Startup
,不再具有 Global.asax 的依賴關系。 結合使用 OWIN 和 .NET Framework 時,使用的管道應如下所示:using Owinusing System.Web.Http;
namespace WebApi {
//注意:默認情況下,所有請求都通過這個OWIN管道。或者,您可以通過添加appSetting來關閉此功能owin:AutomaticAppStartup with 值“false”。 //關閉此選項后,通過在RouteTable.routes上使用MapOwinPath或MapOwinRoute擴展在global.asax文件中添加路由,您仍然可以讓OWIN應用監聽特定路由 public class Startup { // 在啟動時調用一次以配置應用程序。 public void Configuration(IAppBuilder builder) { HttpConfiguration config = new HttpConfiguration(); config.Routes.MapHttpRoute("Default", "{controller}/{customerID}", new { controller = "Customer", customerID = RouteParameter.Optional }); config.Formatters.XmlFormatter.UseXmlSerializer = true; config.Formatters.Remove(config.Formatters.JsonFormatter); // config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true; builder.UseWebApi(config); } } }
這會配置默認路由,默認為 XmlSerialization 而不是 Json。 根據需要向此管道添加其他中間件(加載服務、配置設置、靜態文件等)。
ASP.NET Core 使用相似的方法,但是不依賴 OWIN 處理條目。 而是通過 Program.cs Main
方法(類似於控制台應用程序)來完成,並且 Startup
會通過該處進行加載。
using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; namespace WebApplication2 { public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); } }
Startup
必須包含 Configure
方法。 在 Configure
中,向管道添加必要的中間件。 在下面的示例(來自默認網站模板)中,擴展方法為管道配置以下支持:
- 錯誤頁
- HTTP 嚴格傳輸安全
- 從 HTTP 重定向到 HTTPS
- ASP.NET Core MVC
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); }
現在主機和應用程序已分離,這樣將來就可以靈活地遷移到其他平台。
若要獲取 ASP.NET Core Startup 和中間件的更深入的參考信息,請參閱 ASP.NET Core 中的 Startup
ASP.NET支持存儲設置。 這些設置可用於支持應用程序已部署到的環境(以此用途為例)。 常見做法是將所有的自定義鍵值對存儲在 Web.config 文件的 <appSettings>
部分中:
<appSettings> <add key="UserName" value="User" /> <add key="Password" value="Password" /> </appSettings>
應用程序使用 System.Configuration
命名空間中的 ConfigurationManager.AppSettings
集合讀取這些設置:
string userName = System.Web.Configuration.ConfigurationManager.AppSettings["UserName"]; string password = System.Web.Configuration.ConfigurationManager.AppSettings["Password"];
ASP.NET Core 可以將應用程序的配置數據存儲在任何文件中,並可在啟動中間件的過程中加載它們。 項目模板中使用的默認文件是 appsettings.json:
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } }, "AppConfiguration": { "UserName": "UserName", "Password": "Password" } }
將此文件加載到應用程序內的 IConfiguration
的實例的過程在 Startup.cs 中完成:
public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; }
應用讀取 Configuration
來獲得這些設置:
string userName = Configuration.GetSection("AppConfiguration")["UserName"]; string password = Configuration.GetSection("AppConfiguration")["Password"];
此方法有擴展項,它們可使此過程更加可靠,例如使用依存關系注入 (DI) 來加載使用這些值的服務。 DI 方法提供了一組強類型的配置對象。
// 假設AppConfiguration是表示AppConfiguration節點的強類型版本的類 services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));
若要獲取 ASP.NET Core 配置的更深入的參考信息,請參閱 ASP.NET Core 中的配置。
生成大型可縮放應用程序時,一個重要的目標是將組件和服務松散耦合。 依賴項注入不僅是可實現此目標的常用技術,還是 ASP.NET Core 的本機組件。
在 ASP.NET應用中,開發人員依賴第三方庫實現依存關系注入。 其中的一個庫是 Microsoft 模式和做法提供的 Unity。
實現打包 UnityContainer
的 IDependencyResolver
是使用 Unity 設置依存關系注入的一個示例:
1 using Microsoft.Practices.Unity; 2 using System; 3 using System.Collections.Generic; 4 using System.Web.Http.Dependencies; 5 6 public class UnityResolver : IDependencyResolver 7 { 8 protected IUnityContainer container; 9 10 public UnityResolver(IUnityContainer container) 11 { 12 if (container == null) 13 { 14 throw new ArgumentNullException("container"); 15 } 16 this.container = container; 17 } 18 19 public object GetService(Type serviceType) 20 { 21 try 22 { 23 return container.Resolve(serviceType); 24 } 25 catch (ResolutionFailedException) 26 { 27 return null; 28 } 29 } 30 31 public IEnumerable<object> GetServices(Type serviceType) 32 { 33 try 34 { 35 return container.ResolveAll(serviceType); 36 } 37 catch (ResolutionFailedException) 38 { 39 return new List<object>(); 40 } 41 } 42 43 public IDependencyScope BeginScope() 44 { 45 var child = container.CreateChildContainer(); 46 return new UnityResolver(child); 47 } 48 49 public void Dispose() 50 { 51 Dispose(true); 52 } 53 54 protected virtual void Dispose(bool disposing) 55 { 56 container.Dispose(); 57 } 58 }
創建 UnityContainer
的實例,注冊服務,然后將 HttpConfiguration
的依賴關系解析程序設置為容器的 UnityResolver
新實例:
public static void Register(HttpConfiguration config) { var container = new UnityContainer(); container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager()); config.DependencyResolver = new UnityResolver(container); // Other Web API configuration not shown. }
在必要時注入 IProductRepository
:
public class ProductsController : ApiController { private IProductRepository _repository; public ProductsController(IProductRepository repository) { _repository = repository; } // Other controller methods not shown. }
由於依存關系注入是 ASP.NET Core的組成部分,因此可以在 Startup.cs 的 ConfigureServices
方法中添加你的服務:
public void ConfigureServices(IServiceCollection services) { // 注冊應用服務 services.AddTransient<IProductRepository, ProductRepository>(); }
可在任意位置注入存儲庫,Unity 亦是如此。有關依賴關系注入的詳細信息,請參閱依賴關系注入。
Web 開發的一個重要環節是提供客戶端靜態資源的功能。 HTML、CSS、Javascript 和圖像是最常見的靜態文件示例。 這些文件需要保存在應用(或 CDN)的發布位置中,並且需要引用它們,以便請求可以加載這些文件。 在 ASP.NET Core 中,此過程發生了變化。
在 ASP.NET 中,靜態文件存儲在各種目錄中,並在視圖中進行引用。在 ASP.NET Core 中,靜態文件存儲在“Web 根”(<內容根>/wwwroot)中,除非另有配置。 通過從 Startup.Configure
調用 UseStaticFiles
擴展方法將這些文件加載到請求管道中:
public void Configure(IApplicationBuilder app) { app.UseStaticFiles(); }
如果面向 .NET Framework,請安裝 NuGet 包 Microsoft.AspNetCore.StaticFiles。
http://<app>/images/<imageFileName>
的位置訪問 wwwroot/images 文件夾中的圖像資產。
若要獲取在 ASP.NET Core 中提供靜態文件的更深入的參考信息,請參閱靜態文件。
ASP.NET Core 不支持多值 cookie。 為每個值創建一個 cookie。
出於安全原因,ASP.NET Core 中不壓縮身份驗證 cookie。 使用身份驗證 cookie 時,開發人員應將聲明信息數量減少到所需的量。
部分應用遷移的一種方法是創建 IIS 子應用程序,只將特定的路由從 ASP.NET 4.x 遷移到 ASP.NET Core,同時保留應用的 URL 結構。 例如,applicationHost.config 文件中應用的 URL 結構:
<sites> <site name="Default Web Site" id="1" serverAutoStart="true"> <application path="/"> <virtualDirectory path="/" physicalPath="D:\sites\MainSite\" /> </application> <application path="/api" applicationPool="DefaultAppPool"> <virtualDirectory path="/" physicalPath="D:\sites\netcoreapi" /> </application> <bindings> <binding protocol="http" bindingInformation="*:80:" /> <binding protocol="https" bindingInformation="*:443:" sslFlags="0" /> </bindings> </site> ... </sites>
目錄結構:
.
├── MainSite
│ ├── ...
│ └── Web.config
└── NetCoreApi
├── ...
└── web.config
ASP.NET 早期版本使用 [Bind]
屬性防止“過多發布”攻擊。 在 ASP.NET Core 中,輸入格式化程序的工作方式有所不同。 與輸入格式化程序一起用於分析 JSON 或 XML 時,[Bind]
屬性不再專用於防止過多發布。 數據源是使用 x-www-form-urlencoded
內容類型發布的表單數據時,這些屬性會影響模型綁定。
對於將 JSON 信息發布到控制器並使用 JSON 輸入格式化程序分析數據的應用程序,我們建議將 [Bind]
屬性替換為與 [Bind]
屬性定義的屬性相匹配的視圖模型。
其他項目遷移具體操作步驟,請參考以下博客:
參考文獻:
- https://docs.microsoft.com/zh-cn/aspnet/core/migration/proper-to-2x/?view=aspnetcore-5.0