如何将值更新到appsetting.json?

我正在使用官方文档中IOptions描述的模式.

当我从中读取值时appsetting.json,这可以正常工作,但是如何更新值并将更改保存回来appsetting.json

在我的例子中,我有几个字段可以从用户界面编辑(由管理员用户在应用程序中).因此,我正在寻找通过选项访问器更新这些值的理想方法.

Matze..  32

在编写此答案时,似乎没有Microsoft.Extensions.Options包提供的组件具有将配置值写回的功能appsettings.json.

在我的一个ASP.NET Core项目中,我想让用户更改一些应用程序设置 - 这些设置值应该appsettings.json更准确地存储在可选appsettings.custom.json文件中,如果存在,则会添加到配置中.

像这样...

public Startup(IHostingEnvironment env)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("appsettings.custom.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables(); this.Configuration = builder.Build();
}

我宣布IWritableOptions<T>扩展的接口IOptions<T>; 这样我就可以替代IOptions<T>IWritableOptions<T>每当我想读写设置.

public interface IWritableOptions<out T> : IOptions<T> where T : class, new()
{
void Update(Action<T> applyChanges);
}

此外,我想出了IOptionsWriter一个组件,旨在用于IWritableOptions<T>更新配置部分.这是我对前面提到的接口的实现......

class OptionsWriter : IOptionsWriter
{
private readonly IHostingEnvironment environment;
private readonly IConfigurationRoot configuration;
private readonly string file; public OptionsWriter(
IHostingEnvironment environment,
IConfigurationRoot configuration,
string file)
{
this.environment = environment;
this.configuration = configuration;
this.file = file;
} public void UpdateOptions(Action<JObject> callback, bool reload = true)
{
IFileProvider fileProvider = this.environment.ContentRootFileProvider;
IFileInfo fi = fileProvider.GetFileInfo(this.file);
JObject config = fileProvider.ReadJsonFileAsObject(fi);
callback(config);
using (var stream = File.OpenWrite(fi.PhysicalPath))
{
stream.SetLength(0);
config.WriteTo(stream);
} this.configuration.Reload();
}
}

由于编写器不知道文件结构,我决定将段处理为JObject对象.访问者尝试查找请求的部分并将其反序列化为实例T,使用当前值(如果未找到),或者仅创建新实例(T如果当前值为)null.然后将此持有者对象传递给调用者,调用者将对其应用更改.比更改的对象转换回JToken将要替换该部分的实例...

class WritableOptions<T> : IWritableOptions<T> where T : class, new()
{
private readonly string sectionName;
private readonly IOptionsWriter writer;
private readonly IOptionsMonitor<T> options; public WritableOptions(
string sectionName,
IOptionsWriter writer,
IOptionsMonitor<T> options)
{
this.sectionName = sectionName;
this.writer = writer;
this.options = options;
} public T Value => this.options.CurrentValue; public void Update(Action<T> applyChanges)
{
this.writer.UpdateOptions(opt =>
{
JToken section;
T sectionObject = opt.TryGetValue(this.sectionName, out section) ?
JsonConvert.DeserializeObject<T>(section.ToString()) :
this.options.CurrentValue ?? new T(); applyChanges(sectionObject); string json = JsonConvert.SerializeObject(sectionObject);
opt[this.sectionName] = JObject.Parse(json);
});
}
}

最后,我实现了一个扩展方法,IServicesCollection允许我轻松配置可写选项访问器...

static class ServicesCollectionExtensions
{
public static void ConfigureWritable<T>(
this IServiceCollection services,
IConfigurationRoot configuration,
string sectionName,
string file) where T : class, new()
{
services.Configure<T>(configuration.GetSection(sectionName)); services.AddTransient<IWritableOptions<T>>(provider =>
{
var environment = provider.GetService<IHostingEnvironment>();
var options = provider.GetService<IOptionsMonitor<T>>();
IOptionsWriter writer = new OptionsWriter(environment, configuration, file);
return new WritableOptions<T>(sectionName, writer, options);
});
}
}

哪个可以用在ConfigureServices......

services.ConfigureWritable<CustomizableOptions>(this.Configuration,
"MySection", "appsettings.custom.json");

在我的Controller课程中,我可以要求一个IWritableOptions<CustomizableOptions>具有相同特征的实例IOptions<T>,但也允许更改和存储配置值.

private IWritableOptions<CustomizableOptions> options;

...

this.options.Update((opt) => {
opt.SampleOption = "...";
});

ceferrari..  30

简化版Matze的答案:

public interface IWritableOptions<out T> : IOptionsSnapshot<T> where T : class, new()
{
void Update(Action<T> applyChanges);
} public class WritableOptions<T> : IWritableOptions<T> where T : class, new()
{
private readonly IHostingEnvironment _environment;
private readonly IOptionsMonitor<T> _options;
private readonly string _section;
private readonly string _file; public WritableOptions(
IHostingEnvironment environment,
IOptionsMonitor<T> options,
string section,
string file)
{
_environment = environment;
_options = options;
_section = section;
_file = file;
} public T Value => _options.CurrentValue;
public T Get(string name) => _options.Get(name); public void Update(Action<T> applyChanges)
{
var fileProvider = _environment.ContentRootFileProvider;
var fileInfo = fileProvider.GetFileInfo(_file);
var physicalPath = fileInfo.PhysicalPath; var jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(physicalPath));
var sectionObject = jObject.TryGetValue(_section, out JToken section) ?
JsonConvert.DeserializeObject<T>(section.ToString()) : (Value ?? new T()); applyChanges(sectionObject); jObject[_section] = JObject.Parse(JsonConvert.SerializeObject(sectionObject));
File.WriteAllText(physicalPath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
}
} public static class ServiceCollectionExtensions
{
public static void ConfigureWritable<T>(
this IServiceCollection services,
IConfigurationSection section,
string file = "appsettings.json") where T : class, new()
{
services.Configure<T>(section);
services.AddTransient<IWritableOptions<T>>(provider =>
{
var environment = provider.GetService<IHostingEnvironment>();
var options = provider.GetService<IOptionsMonitor<T>>();
return new WritableOptions<T>(environment, options, section.Key, file);
});
}
}

用法:

services.ConfigureWritable<MyOptions>(Configuration.GetSection("MySection"));

然后:

private readonly IWritableOptions<MyOptions> _options;

public MyClass(IWritableOptions<MyOptions> options)
{
_options = options;
}

要将更改保存到文件:

_options.Update(opt => {
opt.Field1 = "value1";
opt.Field2 = "value2";
});

并且您可以将自定义json文件作为可选参数传递(默认情况下它将使用appsettings.json):

services.ConfigureWritable<MyOptions>(Configuration.GetSection("MySection"), "appsettings.custom.json");
  • 我不太确定“ MyOptions”,但是阅读此内容有助于我弄清楚。https://codingblast.com/asp-net-core-configuration-reloading-binding-injecting/ (2认同)

asp.net core 动态更新 appsetting.json方法的更多相关文章

  1. 解决asp.net core 日期格式 datetime Json返回 带T的问题

    原文:解决asp.net core 日期格式 datetime Json返回 带T的问题 记录一下: Startup中,将 services.AddMvc(); 改为: services.AddMvc ...

  2. asp.net core 3.0 MVC JSON 全局配置

    asp.net core 3.0 MVC JSON 全局配置 System.Text.Json(default) startup配置代码如下: using System.Text.Encodings. ...

  3. MFC编辑框接收数据动态更新与刷新方法代码示例-如何让编辑框内容实时更新

    MFC编辑框接收数据动态更新与刷新方法代码示例-如何让编辑框内容实时更新 关键代码: //发送数据通知 //from txwtech@163.com LRESULT CCommSampleDlg::O ...

  4. .NET 6 Preview 3 中 ASP.NET Core 的更新和改进

    原文:bit.ly/2Qb56NP 作者:Daniel Roth 译者:精致码农-王亮 .NET 6 预览版 3 现已推出,其中包括许多对新的 ASP.NET Core 改进.以下是本次预览版的新内容 ...

  5. 【译】.NET Core 3.0 Preview 3中关于ASP.NET Core的更新内容

      .NET Core 3.0 Preview 3已经推出,它包含了一系列关于ASP.NET Core的新的更新. 下面是该预览版的更新列表: Razor组件改进: 单项目模板 新的Razer扩展 E ...

  6. Asp.Net Core探索 之 appsettings.json

    appsettings.json是什么? 相信大家在.Net Framework的项目都会用的web.config,app.config这些文件,appsettings.json文件就是Asp.Net ...

  7. 问题:调用 ASP.Net Core WebAPI的HTTP POST方法时,从 [FromBody] 中读取的 MongoDB GeoJsonObjectModel成员总是null

    问题描述: POST/PUT to ASP.Net Core with [FromBody] to a MongoDB GeoJsonObjectModel member is always null ...

  8. 解析Asp.net Core中使用Session的方法

    2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Core中引 ...

  9. 5种设置ASP.NET Core应用程序URL的方法

    默认情况下,ASP.NET Core应用程序监听以下URL: http://localhost:5000 https://localhost:5001 在这篇文章中,我展示了5种不同的方式来更改您的应 ...

随机推荐

  1. Python3-subprocess模块-子进程管理

    简单介绍 subprocess模块可以创建新的进程,执行shell命令.Python脚本等 代码示例 import subprocess # 1.执行进程,并获取返回码 return_code = s ...

  2. 从零开始用electron整个跨平台桌面应用---基础配置篇

    1.安装node.npm node以及npm都需要是最新版本(版本过低有坑) 2.安装淘宝镜像cnpm(建议,下载较快) npm install -g cnpm --registry=https:// ...

  3. Redis系列(八):数据结构List双向链表中阻塞版本之BLPOP、BRPOP和LINDEX、LINSERT、LRANGE命令详解

    1.BRPOP.BLPOP BLPOP: BLPOP 是阻塞式列表的弹出原语. 它是命令 LPOP 的阻塞版本,这是因为当给定列表内没有任何元素可供弹出的时候, 连接将被 BLPOP 命令阻塞. 当给 ...

  4. Kali Day1

    一.最新版本的Kali Linux的账号名和密码都是kali. 如何切换root  步骤如下: 1. 设置密码 sudo passwd root 2. 切换身份 su 3. 图示 二.快捷键 1. K ...

  5. 《UNIX环境高级编程》(APUE) 笔记第十二章 - 线程控制

    12 - 线程控制 GitHub 地址 1. 线程限制 下图为与 线程操作 有关的一些 限制: 可以通过 sysconf 函数进行查询 . 2. 线程属性 可使用 pthread_attr_t 结构修 ...

  6. DOM对象增删元素

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  7. C++ MFC 文件操作(新建,删除,剪切,复制,读数据,写数据,重命名)

    源文件:http://pan.baidu.com/s/1ve0hV 这是运行mfc缺失的dll动态链接库:http://pan.baidu.com/s/17pGlT 哈哈,我也是初接触C++,基础的什 ...

  8. scrapy分布式抓取基本设置

    scrapy本身并不是一个为分布式爬取而设计的框架,但第三方库scrapy-redis为其扩展了分布式抓取的功能,在分布式爬虫框架中,需要使用某种通信机制协调各个爬虫工作 (1)当前的爬取任务,下载+ ...

  9. 主存到Cache直接映射、全相联映射和组相联映射

    转自:https://blog.csdn.net/dongyanxia1000/article/details/53392315 ---- Cache的容量很小,它保存的内容只是主存内容的一个子集,且 ...

  10. Python 之父说 Python 历史

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:鸿影洲冷 这篇文章主要内容来源于 Python 编程语言的最初设计者 ...