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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 网站运行时修改设置如何自动生效

發(fā)布時間:2023/12/4 asp.net 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 网站运行时修改设置如何自动生效 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊藍字

關(guān)注我

在ASP.NET Core中,如果修改了appsettings.json中的設(shè)置,那么默認情況下就得重啟網(wǎng)站才能生效。有沒有辦法在修改設(shè)置后自動刷新并應(yīng)用呢?

背景

首先,我們看看默認模板建出來的 ASP.NET Core 網(wǎng)站,配置文件有兩個:

appsettings.json

appsettings.Development.json

前者用于生產(chǎn)環(huán)境,后者用于開發(fā)環(huán)境,在Debug模式下,會優(yōu)先使用?appsettings.Development.json?的設(shè)置。

在不顯示指定的情況下,Program.cs 中的CreateWebHostBuilder() 方法會讀取這兩個設(shè)置文件。為了便于維護,大家通常會創(chuàng)建一個對應(yīng)的class,用來強類型匹配設(shè)置項。比如這樣:

services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));

使用的時候用IOptions接口注入:

public Ctor(IOptions<AppSettings> settings)

如果你還不了解這種方法,可以參見我之前寫的文章:https://edi.wang/post/2016/10/9/read-appsettings-aspnet-core?(微信可能屏蔽了我的域名,復(fù)制到瀏覽器能打開)

問題

這種方法確實可以讀取配置文件,并使用強類型約束和使用。但個缺點就是在網(wǎng)站運行時,如果修改了 appsettings.json 中的配置項,是不會當(dāng)場生效的,必須重啟網(wǎng)站才能應(yīng)用。

比如我博客的網(wǎng)頁標題,是來源于配置文件里的 SiteTitle,如果我在網(wǎng)站運行時登錄服務(wù)器后臺,改成 "Edi.Wang Test",是不會生效的,必須得等下次網(wǎng)站重啟。

解決辦法

還是剛才我博客的例子,我給標題賦值用的方法是在Razor頁面里注入IOptions接口:

@inject IOptions<AppSettings> Settings

然后賦值:

@Settings.Value.SiteTitle

解決辦法非常簡單,換個接口,用IOptionsSnapshot就行啦,在C#類的構(gòu)造函數(shù)里注入的話也是一樣的改法:

@inject IOptionsSnapshot<AppSettings> Settings

對比一下這兩個接口:

IOptions

// Summary:

//? ? ?Used to retrieve configured TOptions instances.

//

// Type parameters:

//? ?TOptions:

//? ? ?The type of options being requested.

public interface IOptions<out TOptions> where TOptions : class, new()

IOptionsSnapshot

// Summary:

//? ? ?Used to access the value of TOptions for the lifetime of a request.

//

// Type parameters:

//? ?TOptions:

public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions>

where TOptions : class, new()

會發(fā)現(xiàn)?IOptionsSnapshot?會針對每個單獨的請求去重新讀取一次配置,而 IOptions 則是第一次讀取完以后就將對象保存在內(nèi)存里了。

聽說你想這樣做?

網(wǎng)上搜索到的方法通常讓你這樣做:修改Program.cs,在CreateWebHostBuilder()?方法里加入這么一段:

...

WebHost.CreateDefaultBuilder(args)

.ConfigureAppConfiguration((hostingContext, config) =>

{

? ? config.SetBasePath(Directory.GetCurrentDirectory());

? ? config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

? ? config.AddJsonFile("appsettings.Development.json", optional: false, reloadOnChange: true);

? ? config.AddEnvironmentVariables();

})

...

這段代碼的作用是,讓我們自己指定應(yīng)用啟動時加載哪些配置源,在這個案例里,我們依舊加載 appsettings.json 以及appsettings.Development.json。對于Json文件,有一個參數(shù)是reloadOnChange,表示是否在文件修改后,重新讀取并加載到內(nèi)存里,設(shè)為true。

這段代碼其實是沒有必要的,這樣改完代碼還是得重啟網(wǎng)站才能讓設(shè)置生效,原因在強類型約束的時候使用的IOptions接口。

關(guān)于為什么顯示指定reloadOnChange: true是沒有必要的,可以做個簡單測試:

我在appsettings.json里定義一個MySettings

{

? "Logging": {

? ? "LogLevel": {

? ? ? "Default": "Warning"

? ? }

? },

? "MySettings": {

? ? "Message": ".NET Core Rocks!"

? },

? "AllowedHosts": "*"

}

建立對應(yīng)的class

public class MySettings

{

? ? public string Message { get; set; }

}

注冊服務(wù)

public void ConfigureServices(IServiceCollection services)

{

//...

? ? services.Configure<MySettings>(Configuration.GetSection(nameof(MySettings)));

}

依賴注入并輸出結(jié)果

public class HomeController : Controller

{

? ? protected IConfiguration Configuration;


? ? protected MySettings MySettings { get; set; }


? ? public HomeController(

? ? ? ? IOptions<MySettings> settings = null,?

? ? ? ? IConfiguration configuration = null)

? ? {

? ? ? ? if (settings != null) MySettings = settings.Value;

? ? ? ? Configuration = configuration;

? ? }


? ? public IActionResult Index()

? ? {

? ? ? ? var m1 = MySettings.Message;

? ? ? ? var m2 = Configuration.GetSection("MySettings")["Message"];

? ? ? ? return Content($"m1:{m1}, m2:{m2}");

? ? }

}

這時候我并沒有寫 reloadOnChange: true,看看運行結(jié)果:

結(jié)果當(dāng)然兩者是一樣的。然后我們在運行時熱修改配置值

刷新網(wǎng)頁,發(fā)現(xiàn)只有m2有變化。而這并不要求我顯式指定reloadOnChange: true

要想讓兩者都取到最新的配置,使用上一節(jié)的方法,把m1的注入改成IOptionsSnapshot<MySettings>,現(xiàn)在再做熱修改,兩者都能立即生效:

破解謎團

剛才我們不指定reloadOnChange竟然也能做熱修改,令人懵逼?我猜想,這個reloadOnChange,在最新版本的ASP.NET Core(2.2)中可能是默認啟用的。關(guān)于這一點,我竟然沒有找到官方的資料,不能確定這個參數(shù)的具體作用。但是ASP.NET Core是開源的,不妨來看看源代碼:

代碼位置:https://github.com/aspnet/Extensions

最終發(fā)現(xiàn)原來CreateDefaultBuilder()方法里,真的默認設(shè)置為reloadOnChange為true:

大家可以親眼看看:

https://github.com/aspnet/Extensions/blob/master/src/Hosting/Hosting/src/Host.cs

好奇(注孤生)的程序員終于在折騰開源代碼后得到了滿足……

結(jié)論

ASP.NET Core 2.2 中如果要在運行時修改強類型配置,無需設(shè)置reloadOnChange = true,只需要使用IOptionsSnapshot接口即可大功告成!


總結(jié)

以上是生活随笔為你收集整理的ASP.NET Core 网站运行时修改设置如何自动生效的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。