如何将值更新到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 IoC 循环依赖的处理

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 是 ...

  2. 使用nginx配置域名及禁止直接通过IP访问网站

    前段时间刚搭建好个人网站,一直没有关注一个问题,那就是IP地址也可以访问我的网站,今天就专门研究了一下nginx配置问题,争取把这个问题研究透彻. 1. nginx配置域名及禁止直接通过IP访问 先来 ...

  3. jQuery处理默认配置参数(将一个或多个对象的内容合并到目标对象)

    问题 我们在封装一个函数时, 需要别人传递一个json对象作为参数, 而用户可能只传入部分参数, 这是就可以利用$extend()来与合并到默认JSON参数合并. // 程序需要的参数 var def ...

  4. 《UNIX环境高级编程》(APUE) 笔记第五章 - 标准I/O库

    5 - 标准I/O库 Github 地址 1. 标准 I/O 库作用 缓冲区分配 以优化的块长度执行 I/O 等 使用户不必担心如何选择使用正确的块长度 标准 I/O 最终都要调用第三章中的 I/O ...

  5. 服务消费者(Feign-下)

    上一篇文章中已经讲述 Feign的基本用法,本章主要概述 FeignClient GET/POST/PUT/DELETE restful写法以及 Feign 拦截器,与配置优化方案,关闭HttpCli ...

  6. 资深阿里程序员一一为你解刨Web前端知识体系结构,付出与收获成正比!

    只要接触过前端,都会指导web前端的知识主要由三部分组成:分别为静态html,样式css,动态javascript(简称js)这三大部分组成.其三部分组成的一个体系的复杂程度不亚于其他一门技术的复杂程 ...

  7. 从别人的代码中学习golang系列--01

    自己最近在思考一个问题,如何让自己的代码质量逐渐提高,于是想到整理这个系列,通过阅读别人的代码,从别人的代码中学习,来逐渐提高自己的代码质量.本篇是这个系列的第一篇,我也不知道自己会写多少篇,但是希望 ...

  8. 听说你还没学Spring就被源码编译劝退了?30+张图带你玩转Spring编译

    源码学习第一步,Spring源码编译 之所以写这么一篇文章是因为群里的小伙伴在编译源码时碰到了问题,再加上笔者自身正准备做一个源码的注释版本,恰好也需要重新编译一份代码,至于为什么要将源码编译到本地就 ...

  9. c语言学习笔记第三章———数据和C

    B站有视频演示 本章将会讲解c语言的数据定义和使用,您将会了解int.float.double.char的含义,了解命名的规则,对c语言会有更加深刻的认识. 变量命名: 我们先讲上次视频没讲的变量命名 ...

  10. 状压DP之Mixed Up Cows G

    题目 传送们 大意 约翰家有N头奶牛,第i头奶牛的编号是Si,每头奶牛的编号都是唯一的.这些奶牛最近 在闹脾气,为表达不满的情绪,她们在挤奶的时候一定要排成混乱的队伍.在一只混乱的队 伍中,相邻奶牛的 ...