├── samples ├── Sample.WebAPI │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── WeatherForecast.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Sample.WebAPI.csproj │ ├── appsettings.json │ ├── Program.cs │ └── Controllers │ │ └── WeatherForecastController.cs └── Sample.ConsoleApp │ ├── Program.cs │ └── Sample.ConsoleApp.csproj ├── src └── ViewConfig │ ├── ConfigModel.cs │ ├── ViewConfigOptions.cs │ ├── DependencyInjectionExtensions.cs │ ├── ViewConfigOptionsExtensions.cs │ ├── ViewConfig.csproj │ ├── EmbeddedFilesHandle.cs │ ├── ViewConfigMiddleware.cs │ ├── ConfigurationRootExtensions.cs │ └── ViewConfigStaticFiles │ └── index.html ├── .gitignore ├── README.md └── ViewConfig.sln /samples/Sample.WebAPI/Startup.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpringLeee/ViewConfig/HEAD/samples/Sample.WebAPI/Startup.cs -------------------------------------------------------------------------------- /samples/Sample.WebAPI/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ViewConfig/ConfigModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ViewConfig 6 | { 7 | public class ConfigModel 8 | { 9 | public string Key { get; set; } 10 | 11 | public string Value { get; set; } 12 | 13 | public string Provider { get; set; } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/Sample.ConsoleApp/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using System; 3 | 4 | namespace Sample.ConsoleApp 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | ServiceCollection services = new ServiceCollection(); 11 | 12 | Console.WriteLine("Hello World!"); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/Sample.WebAPI/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Sample.WebAPI 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ViewConfig/ViewConfigOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace ViewConfig 7 | { 8 | public class ViewConfigOptions : IOptions 9 | { 10 | internal string Endpoint { get; set; } 11 | 12 | internal string Render { get; set; } 13 | 14 | public ViewConfigOptions Value => this; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /samples/Sample.ConsoleApp/Sample.ConsoleApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/Sample.WebAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "Sample.WebAPI": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": "true", 7 | "launchBrowser": false, 8 | "launchUrl": "viewconfig", 9 | "applicationUrl": "http://localhost:6003", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /.vs/ViewConfig/v16 6 | /src/ViewConfig/bin/Debug/netstandard2.0 7 | /src/ViewConfig/obj 8 | /samples/Sample.WebAPI/bin/Debug/net5.0 9 | /samples/Sample.WebAPI/obj 10 | /src/ViewConfig/bin/Debug 11 | /samples/Sample.ConsoleApp/bin/Debug/net5.0 12 | /samples/Sample.ConsoleApp/obj 13 | -------------------------------------------------------------------------------- /samples/Sample.WebAPI/Sample.WebAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/Sample.WebAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | "HttpReports": { 11 | "Transport": { 12 | "CollectorAddress": "http://localhost:5000/", 13 | "DeferSecond": 10, 14 | "DeferThreshold": 100 15 | }, 16 | "Server": "http://localhost:7000", 17 | "Service": "User", 18 | "Switch": true, 19 | "RequestFilter": [ "/api/health/*", "/HttpReports*" ], 20 | "WithRequest": true, 21 | "WithResponse": true, 22 | "WithCookie": true, 23 | "WithHeader": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/Sample.WebAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Sample.WebAPI 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ViewConfig/DependencyInjectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using ViewConfig; 6 | 7 | namespace Microsoft.Extensions.DependencyInjection 8 | { 9 | public static class DependencyInjectionExtensions 10 | { 11 | public static IApplicationBuilder UseViewConfig(this IApplicationBuilder app,Action options = null) 12 | { 13 | ViewConfigOptions opt = new ViewConfigOptions(); 14 | 15 | if (options != null) options.Invoke(opt); 16 | 17 | if (string.IsNullOrEmpty(opt.Endpoint)) opt.Endpoint = "/viewconfig"; 18 | 19 | if (string.IsNullOrEmpty(opt.Render)) opt.Render = "page"; 20 | 21 | return app.UseMiddleware(opt); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ViewConfig/ViewConfigOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ViewConfig; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | public static class ViewConfigOptionsExtensions 9 | { 10 | public static ViewConfigOptions Map(this ViewConfigOptions options,string endpoint = "/viewconfig") 11 | { 12 | options.Endpoint = endpoint; 13 | 14 | return options; 15 | } 16 | 17 | public static ViewConfigOptions RenderPage(this ViewConfigOptions options) 18 | { 19 | options.Render = "page"; 20 | return options; 21 | } 22 | 23 | public static ViewConfigOptions RenderText(this ViewConfigOptions options) 24 | { 25 | options.Render = "text"; 26 | return options; 27 | } 28 | 29 | public static ViewConfigOptions RenderJson(this ViewConfigOptions options) 30 | { 31 | options.Render = "json"; 32 | return options; 33 | } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /samples/Sample.WebAPI/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Sample.WebAPI.Controllers 9 | { 10 | [ApiController] 11 | [Route("[controller]")] 12 | public class WeatherForecastController : ControllerBase 13 | { 14 | private static readonly string[] Summaries = new[] 15 | { 16 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 17 | }; 18 | 19 | private readonly ILogger _logger; 20 | 21 | public WeatherForecastController(ILogger logger) 22 | { 23 | _logger = logger; 24 | } 25 | 26 | [HttpGet] 27 | public IEnumerable Get() 28 | { 29 | var rng = new Random(); 30 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 31 | { 32 | Date = DateTime.Now.AddDays(index), 33 | TemperatureC = rng.Next(-20, 55), 34 | Summary = Summaries[rng.Next(Summaries.Length)] 35 | }) 36 | .ToArray(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ViewConfig 介绍 2 | 3 | 在本文中,我们在.NET Core 程序中使用了 `ViewConfig` 组件来调试配置。 4 | 5 | 6 | ## 安装 7 | 8 | 通过Nuget搜索 `ViewConfig`,然后在程序中安装,这是一个.net standard 2.0 的组件。 9 | 10 | ![](https://blog-1259586045.cos.ap-shanghai.myqcloud.com/clipboard_20210330_054359.png) 11 | 12 | ## 设置 13 | 14 | 安装完成以后,需要修改 Startup.cs 文件的 Configure 方法,我们加一行代码 `UseViewConfig` 15 | 16 | ```csharp 17 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 18 | { 19 | if (env.IsDevelopment()) 20 | { 21 | app.UseViewConfig(); 22 | 23 | app.UseDeveloperExceptionPage(); 24 | app.UseSwagger(); 25 | 26 | // ... 27 | 28 | } 29 | ``` 30 | 31 | 这里建议在开发环境中使用,和Swagger一样, 然后我们启动程序,然后访问 `/viewconfig` 端点 32 | 33 | ![](https://blog-1259586045.cos.ap-shanghai.myqcloud.com/clipboard_20210330_062154.png) 34 | 35 | 上面列出了程序中所有的配置项,我们可以看到 Key,Value,也可以通过 Provider 知道配置来自与 appsetting.json 文件或者其他,可以通过下拉列表查看不同的 Provider 的配置信息。 36 | 37 | ## 自定义 38 | 39 | 默认使用的是 `/viewconfig` 端点,输出的是页面,当然也支持输出 json 和文本,像下面这样 40 | 41 | ```csharp 42 | // 自定义端点 43 | app.UseViewConfig(x => x.Map("/Info")); 44 | 45 | // 页面格式 46 | app.UseViewConfig(x => x.RenderPage()); 47 | 48 | // Json格式 49 | app.UseViewConfig(x => x.Map().RenderJson()); 50 | 51 | // 文本格式 52 | app.UseViewConfig(x => x.Map("/Info").RenderText()); 53 | ``` 54 | 55 | ## 总结 56 | 57 | ViewConfig 是一个非常简单的组件,可以帮助我们在.NET Core 程序中调试配置信息,接下来还会支持在.Net Core 控制台项目中使用,需要注意的是,我建议大家只在开发环境中使用它,希望可以对您有帮助。 58 | 59 | -------------------------------------------------------------------------------- /src/ViewConfig/ViewConfig.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | ViewConfig is a visual configuration component 7 | 8 | https://github.com/SpringLeee/ViewConfig 9 | https://github.com/SpringLeee/ViewConfig 10 | 0.0.3 11 | 12 | ViewConfig 13 | ViewConfig 14 | ViewConfig 15 | true 16 | true 17 | true 18 | snupkg 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/ViewConfig/EmbeddedFilesHandle.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace ViewConfig 12 | { 13 | internal class EmbeddedFilesHandle 14 | { 15 | static readonly Dictionary ResponseType = new Dictionary 16 | { 17 | { ".css","text/css"}, 18 | { ".html","text/html"}, 19 | { ".ico","image/x-icon"}, 20 | { ".png","image/png"}, 21 | { ".jpg","image/jpg"}, 22 | { ".js","application/javascript"}, 23 | { ".json","application/json;charset=utf-8"}, 24 | {".woff2","font/woff2" }, 25 | {".woff","font/woff" }, 26 | {".ttf","application/octet-stream" }, 27 | {".map","application/octet-stream" } 28 | }; 29 | 30 | private static Assembly _assembly; 31 | 32 | static EmbeddedFilesHandle() 33 | { 34 | _assembly = Assembly.GetExecutingAssembly(); 35 | } 36 | 37 | public static async Task IncludeEmbeddedFile(HttpContext context, string path) 38 | { 39 | context.Response.OnStarting(() => 40 | { 41 | if (context.Response.StatusCode == (int)HttpStatusCode.OK) 42 | { 43 | context.Response.ContentType = ResponseType[Path.GetExtension(path)]; 44 | } 45 | 46 | return Task.CompletedTask; 47 | }); 48 | 49 | path = "ViewConfig" + path.Replace("/", "."); 50 | 51 | var list = _assembly.GetManifestResourceNames().ToList(); 52 | 53 | using (var inputStream = _assembly.GetManifestResourceStream(path)) 54 | { 55 | if (inputStream == null) 56 | { 57 | context.Response.StatusCode = (int)HttpStatusCode.NotFound; 58 | return; 59 | } 60 | await inputStream.CopyToAsync(context.Response.Body); 61 | } 62 | } 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/ViewConfig/ViewConfigMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.Extensions.Configuration; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ViewConfig 9 | { 10 | internal class ViewConfigMiddleware 11 | { 12 | private readonly RequestDelegate _next; 13 | private readonly IConfiguration _config; 14 | private readonly ViewConfigOptions _options; 15 | 16 | public ViewConfigMiddleware(RequestDelegate next, IConfiguration config, ViewConfigOptions options) 17 | { 18 | _next = next; 19 | _config = config; 20 | _options = options; 21 | } 22 | 23 | public async Task InvokeAsync(HttpContext context) 24 | { 25 | if (context.Request.Path.HasValue) 26 | { 27 | var path = context.Request.Path.Value.ToLowerInvariant(); 28 | 29 | if (path == _options.Endpoint.ToLowerInvariant()) 30 | { 31 | _options.Render = string.IsNullOrEmpty(_options.Render) ? "page" : _options.Render; 32 | 33 | if (_options.Render == "page") 34 | { 35 | // Go to index 36 | await EmbeddedFilesHandle.IncludeEmbeddedFile(context, "/ViewConfigStaticFiles/index.html"); 37 | return; 38 | } 39 | 40 | if (_options.Render == "json") 41 | { 42 | context.Response.ContentType = "application/json;charset=utf-8"; 43 | 44 | var configData = (_config as IConfigurationRoot).GetViewConfig(); 45 | await context.Response.WriteAsync(configData.json); 46 | return; 47 | } 48 | 49 | if (_options.Render == "text") 50 | { 51 | var configData = (_config as IConfigurationRoot).GetViewConfig(); 52 | await context.Response.WriteAsync(configData.text); 53 | return; 54 | } 55 | 56 | } 57 | 58 | if (path.ToLowerInvariant() == "/guid30b0a20013760892e4eb5e93c60421ec") 59 | { 60 | var configData = (_config as IConfigurationRoot).GetViewConfig(); 61 | await context.Response.WriteAsync(configData.json); 62 | return; 63 | } 64 | } 65 | 66 | await _next(context); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ViewConfig.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewConfig", "src\ViewConfig\ViewConfig.csproj", "{E4BFB306-E67B-4EED-A651-30A1A1D258A4}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{98DD67F5-6449-4F2B-9BFB-BDAB327949CB}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DC84330F-C834-4737-944A-3A7AF531AB7A}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.WebAPI", "samples\Sample.WebAPI\Sample.WebAPI.csproj", "{F1195A21-EB48-42CE-95B7-A683BBBDB080}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.ConsoleApp", "samples\Sample.ConsoleApp\Sample.ConsoleApp.csproj", "{FCBF1A05-3710-4AFE-82B3-174E8F651044}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {E4BFB306-E67B-4EED-A651-30A1A1D258A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {E4BFB306-E67B-4EED-A651-30A1A1D258A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {E4BFB306-E67B-4EED-A651-30A1A1D258A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {E4BFB306-E67B-4EED-A651-30A1A1D258A4}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {F1195A21-EB48-42CE-95B7-A683BBBDB080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {F1195A21-EB48-42CE-95B7-A683BBBDB080}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {F1195A21-EB48-42CE-95B7-A683BBBDB080}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {F1195A21-EB48-42CE-95B7-A683BBBDB080}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {FCBF1A05-3710-4AFE-82B3-174E8F651044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {FCBF1A05-3710-4AFE-82B3-174E8F651044}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {FCBF1A05-3710-4AFE-82B3-174E8F651044}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {FCBF1A05-3710-4AFE-82B3-174E8F651044}.Release|Any CPU.Build.0 = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(NestedProjects) = preSolution 39 | {E4BFB306-E67B-4EED-A651-30A1A1D258A4} = {98DD67F5-6449-4F2B-9BFB-BDAB327949CB} 40 | {F1195A21-EB48-42CE-95B7-A683BBBDB080} = {DC84330F-C834-4737-944A-3A7AF531AB7A} 41 | {FCBF1A05-3710-4AFE-82B3-174E8F651044} = {DC84330F-C834-4737-944A-3A7AF531AB7A} 42 | EndGlobalSection 43 | GlobalSection(ExtensibilityGlobals) = postSolution 44 | SolutionGuid = {83DB04B3-9AF0-49DB-BCE4-82E2561503D0} 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /src/ViewConfig/ConfigurationRootExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.Encodings.Web; 7 | using System.Text.Json; 8 | 9 | namespace ViewConfig 10 | { 11 | public static class ConfigurationRootExtensions 12 | { 13 | public static (string json,string text) GetViewConfig(this IConfigurationRoot root) 14 | { 15 | List configs = new List(); 16 | 17 | var builder = new StringBuilder(); 18 | 19 | RecurseChildren(root, configs, builder, root.GetChildren(), ""); 20 | 21 | var json = System.Text.Json.JsonSerializer.Serialize(configs.OrderByDescending(x => x.Provider).ToList(), new JsonSerializerOptions 22 | { 23 | Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, 24 | WriteIndented = true 25 | 26 | }); 27 | 28 | return (json,builder.ToString()); 29 | } 30 | 31 | private static void RecurseChildren(IConfigurationRoot root, List configs, StringBuilder stringBuilder, IEnumerable children, string indent) 32 | { 33 | foreach (IConfigurationSection child in children) 34 | { 35 | (string Value, IConfigurationProvider Provider) valueAndProvider = GetValueAndProvider(root, child.Path); 36 | 37 | if (valueAndProvider.Provider != null) 38 | { 39 | configs.Add(new ConfigModel { 40 | 41 | Key = child.Path, 42 | Value = child.Value, 43 | Provider = valueAndProvider.Provider.ToString() 44 | 45 | }); 46 | 47 | stringBuilder 48 | .Append(indent) 49 | .Append(child.Key) 50 | .Append('=') 51 | .Append(valueAndProvider.Value) 52 | .Append(" (") 53 | .Append(valueAndProvider.Provider) 54 | .AppendLine(")"); 55 | } 56 | else 57 | { 58 | stringBuilder 59 | .Append(indent) 60 | .Append(child.Key) 61 | .AppendLine(":"); 62 | } 63 | 64 | RecurseChildren(root, configs, stringBuilder, child.GetChildren(), indent + " "); 65 | } 66 | } 67 | 68 | 69 | private static (string Value, IConfigurationProvider Provider) GetValueAndProvider(IConfigurationRoot root, string key) 70 | { 71 | foreach (IConfigurationProvider provider in root.Providers.Reverse()) 72 | { 73 | if (provider.TryGet(key, out string value)) 74 | { 75 | return (value, provider); 76 | } 77 | } 78 | 79 | return (null, null); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/ViewConfig/ViewConfigStaticFiles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ViewConfig 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |
19 | 20 |
21 |

ViewConfig

22 |
23 | 24 |
25 | 28 | 29 |
30 | 31 | 32 |
33 |
34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
KeyValueProvider
50 | 51 |
52 | 53 | 54 | 55 | 56 | 125 | 126 | 127 | 128 | --------------------------------------------------------------------------------