日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 运行原理解剖[2]:Hosting补充之配置介绍

發布時間:2023/12/4 asp.net 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 运行原理解剖[2]:Hosting补充之配置介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上一章ASP.NET Core 運行原理解剖[1]:Hosting中,我們介紹了 ASP.NET Core 的啟動過程,主要是對?WebHost?源碼的探索。而本文則是對上文的一個補充,更加偏向于實戰,詳細的介紹一下我們在實際開發中需要對?Hosting?做一些配置時經常用到的幾種方式。

WebHostBuild

WebHostBuild 用來構建 WebHost ,也是我們最先接觸的一個類,它提供了如下方法:

ConfigureAppConfiguration

Configuration 在 ASP.NET Core 進行了全新的設計,使其更加靈活簡潔,可以支持多種數據源。在 ASP.NET Core 1.x 中,我們是在Startup的構造函數中配置各種數據源的,而在 ASP.NET Core 2.0 中則移動了到Program中,這樣能與控制臺應用程序保持一致:

public static class WebHostBuilderExtensions{ ?

?public static IWebHostBuilder ConfigureAppConfiguration(this IWebHostBuilder hostBuilder, Action<IConfigurationBuilder> configureDelegate) ?
?
{ ? ?
? ? ?return hostBuilder.ConfigureAppConfiguration((context, builder) => configureDelegate(builder));} }
? ? ?public class WebHostBuilder : IWebHostBuilder{ ?
? ? ? ?private List<Action<WebHostBuilderContext, IConfigurationBuilder>> _configureAppConfigurationBuilderDelegates; ?
? ? ? ??public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate) ? ?{ ? ? ?
? ? ? ???if (configureDelegate == null){ ? ? ? ? ?
? ? ? ????throw new ArgumentNullException(nameof(configureDelegate));}_configureAppConfigurationBuilderDelegates.Add(configureDelegate); ? ? ? ?return this;} }

而_configureAppConfigurationBuilderDelegates委托會在 WebHostBuilder 的Build方法中執行,生成?IConfiguration?對象并以單例的形式注冊到 DI 系統中, 我們可以在Startup以及應用程序的任何地方,通過 DI 系統來獲取到。

而在?上一章?中也介紹過,在CreateDefaultBuilder中會通過該方法來添加appsettinggs.json等基本配置的配置源。

UseSetting

UseSetting 是一個非常重要的方法,它用來配置 WebHost 中的?IConfiguration?對象。需要注意與上面ConfigureAppConfiguration的區別, WebHost 中的 Configuration 只限于在 WebHost 使用,并且我們不能配置它的數據源,它只會讀取ASPNETCORE_開頭的環境變量:

private IConfiguration _config;

public WebHostBuilder(){_config = new ConfigurationBuilder().AddEnvironmentVariables(prefix: "ASPNETCORE_").Build(); }

而我們比較熟悉的當前執行環境,也是通過該_config來讀取的,雖然我們不能配置它的數據源,但是它為我們提供了一個UseSetting方法,為我們提供了一個設置_config的機會:

public string GetSetting(string key){ ?
?return _config[key]; }

而我們通過UseSetting設置的變量最終也會以MemoryConfigurationProvider的形式添加到上面介紹的ConfigureAppConfiguration所配置的IConfiguration對象中。

UseStartup

UseStartup 這個我們都比較熟悉,它用來顯式注冊我們的Startup類,可以使用泛性,Type , 和程序集名稱三種方式來注冊:

// 常用的方法
public static IWebHostBuilder UseStartup<TStartup>(this IWebHostBuilder hostBuilder) where TStartup : class{ ? ?
? ?return hostBuilder.UseStartup(typeof(TStartup)); }
// 通過指定的程序集來注冊 Startup 類

public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, string startupAssemblyName){ ?
?if (startupAssemblyName == null){ ? ? ?
? ?throw new ArgumentNullException(nameof(startupAssemblyName));} ?
? ??return hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName).UseSetting(WebHostDefaults.StartupAssemblyKey, startupAssemblyName); }
? ??// 最終的 Startup 類注冊方法,上面兩種只是一種簡寫形式

public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType){.... }

具體的注冊方式,在?上一章?也介紹過,就是通過反射創建實例,然后注入到 DI 系統中。

ConfigureLogging

ConfigureLogging 用來配置日志系統,在 ASP.NET Core 1.x 中是在Startup類的Configure方法中,通過ILoggerFactory擴展來注冊的,在 ASP.NET Core 中也變得更加簡潔,并且統一通過 WebHostBuild 來配置:

public static class WebHostBuilderExtensions{ ?

?public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action<ILoggingBuilder> configureLogging) ? ?{ ?
?? ? ?return hostBuilder.ConfigureServices(collection => collection.AddLogging(configureLogging));} ?
??
?? ??public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action<WebHostBuilderContext, ILoggingBuilder> configureLogging) ? ?{ ? ? ?
?? ?? ?return hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(context, builder)));} }

AddLogging 是Microsoft.Extensions.Logging提供的擴展方法,更具體的可以看我之前介紹的?ASP.NET Core 源碼學習之 Logging?系列。

ConfigureServices

在上面的幾個方法中,多次用到 ConfigureServices,而 ConfigureServices 與 Starup 中的 ConfigureServices 類似,都是用來注冊服務的:

private readonly List<Action<WebHostBuilderContext, IServiceCollection>> _configureServicesDelegates;

public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices){ ?
?if (configureServices == null){ ? ? ?
? ?throw new ArgumentNullException(nameof(configureServices));}_configureServicesDelegates.Add(configureServices); ?
? ? ?return this; }

但不同的是_configureServicesDelegates的執行時機較早,是在WebHostBuilder的Build方法中執行的,所以會參與 WebHost 中hostingServiceProvider的構建。

其它

WebHostBuild 中還有很多配置的方法,就不再一一細說,在這里簡單介紹一下:

  • UseContentRoot?使用UseSetting方法配置IConfiguration["contentRoot"],表示應用程序所在的默認文件夾地址,如 MVC 中視圖的查詢根目錄。

  • UseWebRoot?使用UseSetting方法配置IConfiguration["webroot"],用來指定可讓外部可訪問的靜態資源路徑,默認為wwwroot,并且是以contentRoot為根目錄。

  • CaptureStartupErrors?使用UseSetting方法配置IConfiguration["captureStartupErrors"],表示是否捕捉啟動時的異常,如果為ture,則在啟動時發生異常也會啟動 Http Server,并顯示錯誤頁面,否則,不會啟動 Http Server。

  • UseEnvironment?使用UseSetting方法配置IConfiguration["environment"],用來指定執行環境。

  • UseServer?用來配置 Http Server 服務,UseKestrel便是此方法的簡寫形式。

  • UseUrls?使用UseSetting方法配置IConfiguration["urls"],用來配置 Http 服務器地址,多個使用;分割。

  • UseShutdownTimeout?使用UseSetting方法配置IConfiguration["shutdownTimeoutSeconds"],用來設置 ASP.NET Core 停止時等待的時間。

  • DetailedErrors?表示是否顯示詳細的錯誤信息,可為true/false或1/0,默認為 false,但它沒有提供直接配置的方法,可以通過UseSetting來指定IConfiguration["detailedErrors"]。

ISartup

ISartup 是我們比較熟悉的,因為在我們創建一個默認的 ASP.NET Core 項目時,都會有一個Startup.cs文件,包含三個約定的方法,按執行順序排列如下:

1. ConfigureServices

ASP.NET Core 框架本身提供了一個 DI(依賴注入)系統,并且可以非常靈活的去擴展,很容易的切換成其它的 DI 框架(如 Autofac,Ninject 等)。在 ASP.NET Core 中,所有的實例都是通過這個 DI 系統來獲取的,并要求我們的應用程序也使用 DI 系統,以便我們能夠開發出更具彈性,更易維護,測試的應用程序。總之在 ASP.NET Core 中,一切皆注入。關于 “依賴注入” 這里就不再多說。

在 DI 系統中,想要獲取服務,首先要進行注冊,而ConfigureServices方法便是用來注冊服務的。

public void ConfigureServices(IServiceCollection services){services.AddScoped<IUserService, UserService>(); }

如上,我們為IUserService接口注冊了一個UserService類型的實例。

2. ConfigureContainer(不常用)

ConfigureContainer 是用來替換 DI 框架的,如下,我們將 ASP.NET Core 內置的 DI 框架替換為?Autofac?:

public void ConfigureContainer(ContainerBuilder builder){builder.RegisterModule(new AutofacModule()); }

雖然 ASP.NET Core 自帶的 DI 系統只提供了構造函數注入,以及不支持命名實例等,但我喜歡它的簡潔,并且不太喜歡依賴太多第三庫,一直也只使用了內置的DI框架,因此對這個方法也不太了解,就不再多說。

3. Configure

Configure 接收一個IApplicationBuilder類型參數,而IApplicationBuilder在?上一章?中介紹過,它是用來構建請求管道的,因此,也可以說 Configure 方法是用來配置請求管道的,通常會在這里會注冊一些中間件。

public void Configure(IApplicationBuilder app){app.Use(next =>{ ? ? ? ?return async (context) =>{ ? ? ? ? ? ?await context.Response.WriteAsync("Hello ASP.NET Core!");};}); }

所謂中間件,也就是對?HttpContext?進行處理的一種便捷方式,下文會詳細來介紹。而如上代碼,我們注冊了一個最簡單的中間件,通過瀏覽器訪問,便可以看到 “Hello ASP.NET Core!” 。

通常,我們的 Startup 類并沒有去實現IStartup接口,這是因為我們在Configure方法中,大多時候可能需要獲取一些其它的服務,如我剛才注冊的IUserService,我們可以直接添加到 Configure 方法的參數列表當中:

public void Configure(IApplicationBuilder app, IUserService userService) { }

ASP.NET Core 會通過 DI 系統來解析到 userService 實例,但是 ASP.NET Core 中的 DI 系統是不支持普通方法的參數注入的,而是手動通過反射的方式來實現的:

services.AddSingleton(typeof(IStartup), sp => { ? ?
var hostingEnvironment = sp.GetRequiredService<IHostingEnvironment>(); ?
?var methods = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName); ?
??return new ConventionBasedStartup(methods); });

而通過反射也可以為我們帶來更大的靈活性,上面的LoadMethods方法會根據當前的執行環境名稱來查找適當的方法名:

public static StartupMethods LoadMethods(IServiceProvider hostingServiceProvider, Type startupType, string environmentName){ ?
?var configureMethod = FindConfigureDelegate(startupType, environmentName); }
?
?private static ConfigureBuilder FindConfigureDelegate(Type startupType, string environmentName){ ? ?
? ?var configureMethod = FindMethod(startupType, "Configure{0}", environmentName, typeof(void), required: true); ?
??return new ConfigureBuilder(configureMethod); }

更具體的可以查看?StartupLoader,ASP.NET Core 會根據當前環境的不同,而執行不同的方法:

public void ConfigureServices(IServiceCollection services) { }

public void ConfigureDevelopmentServices(IServiceCollection services) { }

public void ConfigureContainer(ContainerBuilder builder) {}

public void ConfigureDevelopmentContainer(ContainerBuilder builder) { }

public void Configure(IApplicationBuilder app) { }

public void ConfigureDevelopment(IApplicationBuilder app) { }

如上,當在Development環境上執行時,會選擇帶Development的方法來執行。

而在默認模版中是通過UseStartup<Startup>的方式來注冊?Startup?類的,我們也可以使用上面介紹的指定程序集名稱的方式來注冊:

public static IWebHost BuildWebHost(string[] args) =>WebHost.CreateDefaultBuilder(args).UseStartup("EmptyWebDemo").Build();

如上,我們指定在?EmptyWebDemo?中查找Startup類,這樣還有一個額外的好處,WebHost?同樣會根據當前的執行環境來選擇不同的Startup類(如StartupDevelopment),與上面介紹的Startup中方法的查詢方式一樣。

IHostingStartup

上面,我們介紹了Sartup,而一個項目中只能一個Sartup,因為如果配置多個,則最后一個會覆蓋之前的。而在一個多層項目中,Sartup類一般是放在展現層中,我們在其它層也需要注冊一些服務或者配置請求管道時,通常會寫一個擴展方法:

public static class EfRepositoryExtensions{ ? ?

public static void AddEF(this IServiceCollection services,string connectionStringName) ? ?{ ? ?services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(connectionStringName), opt => opt.EnableRetryOnFailure()));services.TryAddScoped<IDbContext, AppDbContext>();services.TryAddScoped(typeof(IRepository<,>), typeof(EfRepository<,>));...} ? ?

public static void UseEF(IApplicationBuilder app) ? ?{app.UseIdentity();} }

然后在 Startup 中調用這些擴展方法:

public void ConfigureDevelopmentServices(IServiceCollection services){services.AddEF(Configuration.GetConnectionString("DefaultConnection"); }

public void ConfigureDevelopment(IApplicationBuilder app){services.UseEF(); }

感覺這種方式非常丑陋,而在上一章中,我們知道 WebHost 會在 Starup 這前調用?IHostingStartup,于是我們便以如下方式來實現:

[assembly: HostingStartup(typeof(Zero.EntityFramework.EFRepositoryStartup))]

namespace Zero.EntityFramework{ ?

?public class EFRepositoryStartup : IHostingStartup{ ? ?
?
?? ?public void Configure(IWebHostBuilder builder) ? ? ? ?{builder.ConfigureServices(services =>{services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(connectionStringName), opt => opt.EnableRetryOnFailure()));services.TryAddScoped<IDbContext, AppDbContext>();services.TryAddScoped(typeof(IRepository<,>), typeof(EfRepository<,>));...}); builder.Configure(app => {app.UseIdentity();});}} }

如上,只需實現?IHostingStartup?接口,要清爽簡單的多,怎一個爽字了得!不過,還需要進行注冊才會被WebHost執行,首先要指定HostingStartupAttribute程序集特性,其次需要配置 WebHost 中的?IConfiguration[hostingStartupAssemblies],以便 WebHost 能找到我們的程序集,可以使用如下方式配置:

WebHost.CreateDefaultBuilder(args) ? ?// 如需指定多個程序集時,使用 ; 分割.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "Zero.Application;Zero.EntityFramework")

這樣便完成了?IHostingStartup?注冊,不過還需要將包含IHostingStartup的程序集放到?Bin?目錄下,否則根本無法加載。不過 ASP.NET Core 也提供了類似插件的方式來指定IHostingStartup程序集的查找位置,可通過設置DOTNET_ADDITIONAL_DEPS和ASPNETCORE_HOSTINGSTARTUPASSEMBLIES來實現,而這里就不再多說。

IHostingStartup?是由?WebHostBuilder?來調用的,執行時機較早,在創建?WebHost?之前執行,因此可以替換一些在 WebHost 中需要使用的服務。

IStartupFilter

IStartupFilter 是除Startup和HostingStartup之處另一種配置IApplicationBuilder的方式:

public interface IStartupFilter{ ?

?Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next); }

它只有一個Configure方法,是對 Starup 類中Configure方法的攔截器,給我們一個在Configure方法執行之前進行一些配置的機會。

讓我們實踐一把,先定義2個 StartupFilter:

public class A : IStartupFilter{ ?

?public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) ? ?{Console.WriteLine("This is A1!"); ? ? ?
? ?return app =>{Console.WriteLine("This is A2!");next(app);};} }
? ?
? ?public class B : IStartupFilter{ ?
? ??
? ??public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) ? ?{Console.WriteLine("This is B1!"); ? ? ?
? ???return app =>{Console.WriteLine("This is B2!");next(app);};} }

然后讓他們注冊到DI系統中,WebHost?在執行 Starup 類中Configure方法之前,會從 DI 系統中獲取所有的IStartupFilter來執行:

public void ConfigureServices(IServiceCollection services){services.AddSingleton<IStartupFilter, A>();services.AddSingleton<IStartupFilter, B>(); }public void Configure(IApplicationBuilder app){Console.WriteLine("This is Configure!");app.Use(next =>{ ? ? ? ?return async (context) =>{ ? ? ? ? ? ?await context.Response.WriteAsync("Hello ASP.NET Core!");};}); }

最終,它他的執行順序為:B1 -> A1 -> A2 -> B2 -> Configure 。

IHostedService

當我們希望隨著 ASP.NET Core 的啟動,來執行一些后臺任務(如:定期的刷新緩存等)時,并在 ASP.NET Core 停止時,可以優雅的關閉,則可以使用IHostedService,它有如下定義:

public interface IHostedService{ ?
? ? Task StartAsync(CancellationToken cancellationToken);
?? ?Task StopAsync(CancellationToken cancellationToken); }

很簡單,只有開始和停止兩個方法,它的用法大概是這個樣子的:

public class CacheHostService : IHostedService{ ? ?

private readonly ICacheService _cacheService; ?

?private CancellationTokenSource _cts; ?
? ?private Task _executingTask; ?
? ?
? ??public CacheHostService(ICacheService cacheService) ? ?{_cacheService = cacheService;} ?
? ??
? ???public Task StartAsync(CancellationToken cancellationToken) ? ?{_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);_executingTask = Task.Run(async () =>{ ? ? ? ? ? ? ? ?while (!_cts.IsCancellationRequested){Console.WriteLine("cancellationToken:" + _cts.IsCancellationRequested); ? ? ? ? ? ? ? ? ?
? ??? ?await _cacheService.Refresh(); ? ? ? ? ? ?
? ??? ? ? ? ? ?await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);}}); ? ? ?
? ??? ? ? ? ? ? ?return Task.CompletedTask;} ? ?
? ???
? ??? public async Task StopAsync(CancellationToken cancellationToken) ? ?{ ? ? ? ?// 發送停止信號,以通知我們的后臺服務結束執行。_cts.Cancel(); ? ? ? ?// 等待后臺服務的停止,而 ASP.NET Core 大約會等待5秒鐘(可在上面介紹的UseShutdownTimeout方法中配置),如果還沒有執行完會發送取消信號,以防止無限的等待下去。await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));cancellationToken.ThrowIfCancellationRequested();} }

如上,我們定義了一個在臺后每5秒刷新一次緩存的服務,并在 ASP.NET Core 程序停止時,優雅的關閉。最后,將它注冊到 DI 系統中即可:

public void ConfigureServices(IServiceCollection services){services.AddSingleton<ICacheService, CacheService>();services.AddSingleton<IHostedService, CacheHostService>(); }

WebHost?在啟動 HTTP Server 之后,會從 DI 系統中獲取所有的IHostedService,來啟動我們注冊的 HostedService,參見上一章?。

IApplicationLifetime

IApplicationLifetime用來實現 ASP.NET Core 的生命周期鉤子,我們可以在 ASP.NET Core 停止時做一些優雅的操作,如資源的清理等。它有如下定義:

public interface IApplicationLifetime{CancellationToken ApplicationStarted { get; }CancellationToken ApplicationStopping { get; }CancellationToken ApplicationStopped { get; } ?

?void StopApplication(); }

IApplicationLifetime已被 ASP.NET Core 注冊到 DI 系統中,我們使用的時候,只需要注入即可。它有三個CancellationToken類型的屬性,是異步方法終止執行的信號,表示 ASP.NET Core 生命周期的三個階段:啟動,開始停止,已停止。

public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime){appLifetime.ApplicationStarted.Register(() => Console.WriteLine("Started"));appLifetime.ApplicationStopping.Register(() => Console.WriteLine("Stopping"));appLifetime.ApplicationStopped.Register(() =>{Console.WriteLine("Stopped");Console.ReadKey();});app.Use(next =>{ ? ? ? ?return async (context) =>{ ? ? ? ? ? ?await context.Response.WriteAsync("Hello ASP.NET Core!");appLifetime.StopApplication();};}); }

執行結果如下:

在上一章中我們提到過,?IApplicationLifetime?的啟動信號是在?WebHost?的StartAsync方法中觸發的,而沒有提到停止信號的觸發,在這里補充一下:

internal class WebHost : IWebHost{ ?

?public async Task StopAsync(CancellationToken cancellationToken = default(CancellationToken)) ? ?{.... ? ? ? ?// 設置 Task 的超時時間,上文在 IHostedService 中提到過var timeoutToken = new CancellationTokenSource(Options.ShutdownTimeout).Token; ? ? ? ?if (!cancellationToken.CanBeCanceled){cancellationToken = timeoutToken;} ? ? ? ?else{cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken).Token;} ? ? ? ?// 觸發 Stopping 信號_applicationLifetime?.StopApplication(); ? ? ? ?// 停止 Http Serverif (Server != null){ ? ? ? ? ? ?await Server.StopAsync(cancellationToken).ConfigureAwait(false);} ? ? ? ?// 停止 我們注冊的 IHostServiceif (_hostedServiceExecutor != null){ ? ? ? ? ? ?await _hostedServiceExecutor.StopAsync(cancellationToken).ConfigureAwait(false);} ? ? ? ?// 發送 Stopped 通知_applicationLifetime?.NotifyStopped();} }

總結

本文詳細介紹了對 WebHost 的配置,結合?上一章,對 ASP.NET Core 的啟動流程也基本清楚了,下一章就來介紹一下請求管道的創建,敬請期待!

參考資料:

  • ASP-NET-Core-2-IHostedService

  • ASPNET-Core-2.0-Stripping-Away-Cross-Cutting-Concerns

  • Looking-at-asp-net-cores-iapplicationlifetime


相關文章:?

  • .NET Core 2.0 正式發布信息匯總

  • .NET Standard 2.0 特性介紹和使用指南

  • .NET Core 2.0 的dll實時更新、https、依賴包變更問題及解決

  • .NET Core 2.0 特性介紹和使用指南

  • Entity Framework Core 2.0 新特性

  • 體驗 PHP under .NET Core

  • .NET Core 2.0使用NLog

  • 升級項目到.NET Core 2.0,在Linux上安裝Docker,并成功部署

  • 解決Visual Studio For Mac Restore失敗的問題

  • ASP.NET Core 2.0 特性介紹和使用指南

  • .Net Core下通過Proxy 模式 使用 WCF

  • .NET Core 2.0 開源Office組件 NPOI

  • ASP.NET Core Razor頁面 vs MVC

  • Razor Page–Asp.Net Core 2.0新功能 ?Razor Page介紹

  • MySql 使用 EF Core 2.0 CodeFirst、DbFirst、數據庫遷移(Migration)介紹及示例

  • .NET Core 2.0遷移技巧之web.config配置文件

  • asp.net core MVC 過濾器之ExceptionFilter過濾器(一)

  • ASP.NET Core 使用Cookie驗證身份

  • ASP.NET Core MVC – Tag Helpers 介紹

  • ASP.NET Core MVC – Caching Tag Helpers

  • ASP.NET Core MVC – Form Tag Helpers

  • ASP.NET Core MVC – 自定義 Tag Helpers

  • ASP.NET Core MVC – Tag Helper 組件

  • ASP.NET Core 運行原理解剖[1]:Hosting

原文地址:http://www.cnblogs.com/RainingNight/p/hosting-configure-in-asp-net-core.html


.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

總結

以上是生活随笔為你收集整理的ASP.NET Core 运行原理解剖[2]:Hosting补充之配置介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。