如何将值更新到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. Spring和Springboot相关知识点整理

    简介 本文主要整理一些Spring & SpringBoot应用时和相关原理的知识点,对于源码不做没有深入的讲解. 1. 思维导图 右键新窗口打开可以放大. 说明 使用@Configurati ...

  2. Git报错信息

    1. 解决办法: 当在最后提交的时候,出现的错误. 解决办法: git remote rm origin 执行下面代码: git remote add origin https://github.co ...

  3. could not resolve property(无法解析属性)

    could not resolve property(无法解析属性) 顾名思义在写hql语句的时候,属性写错了! 请检查大小写,是实体类的,不是数据库表的! 一个一个检查,仔细看!

  4. Java基础Day08(多线程)

    多线程 1. 线程 1.1 什么是线程: 程序中负责执行的哪个东东就叫做线程(执行路线,进程内部的执行序列或者说是进程的子任务) 多线程执行时,在栈内存中,每一个执行线程都有自己所属的栈内存空间.进行 ...

  5. Oracle 11g数据脱敏

    Oracle 11g数据脱敏 前言 最近开发人员有个需求,导一份生产库的数据到测试库. 由于生产数据安全需要,需要并允许对导出的数据进行加密脱敏处理. 关于加密和脱敏 个人理解, 加密是通过一系列规则 ...

  6. Oracle查询表空间使用率很慢

    Oracle查询表空间使用率很慢 问题描述 执行查询表空间的语句,需要接近2min的时间才能执行完成. 以前也在其他客户的生产库遇到过一样的情况,当时是由于回收站的内容过多引起的. 不过这次的情况却不 ...

  7. 关于延迟段创建-P1

    文章目录 1 疑问点 2 环境创建 2.1 创建用户 2.2 创建表test 2.3 查看表的段信息 2.4 延迟段创建相关参数 1 疑问点 P1页有句话说道: 在Oracle 11.2.0.3.0以 ...

  8. Spring Aop基于注解的实现

    一.AspectOriented Programing,面向切面编程.   AOP主要用于日志记录,性能统计,安全控制(权限控制),事务处理,异常处理等.将日志记录,性能统计,安全控制,事务处理,异常 ...

  9. nodejs 本地压缩jpg,png图片(nodejs)

    使用nodejs实现本地压缩jpg,png图片. 使用到的包 1.images   用于压缩jpg npm install images yarn add images 2.imagemin 用于压缩 ...

  10. Docker可视化工具Portainer

    1 前言 从没想到Docker也有可视化的工具,因为它的命令还是非常清晰简单的.无聊搜了一下,原来已经有很多Docker可视化工具了.如DockerUI.Shipyard.Rancher.Portai ...