Шаблон опций в ASP. NET Core - как вернуть подопции в виде строки JSON (не строго типизированной) - PullRequest
0 голосов
/ 02 апреля 2020

В следующей документации показано, как использовать шаблон параметров в ASP. NET Core для создания строго типизированного класса параметров для доступа к JSON данным конфигурации.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options

Этот C# класс

public class MyOptions
{
    public string Option1 { get; set; }
    public int Option2 { get; set; }
}

представляет часть этого JSON файла конфигурации (первые два свойства root -уровня)

{
  "option1": "value1_from_json",
  "option2": -1,
  "subOptions": {
    "subOption1": "subvalue1_from_json",
    "subOption2": 200
  }
}

Я хочу добавить еще одно C# свойство с именем SubOptions в класс MyOptions , которое возвращает необработанные данные подсекции subOptions JSON. без создания строго типизированного класса для этого подраздела файла конфигурации JSON, но я не знаю, какой тип данных использовать (или вообще возможно ли это сделать).

Если Я использую string , я получаю ошибку времени выполнения при вызове service.Configure<MyOptions>(Configuration);, говоря: System.InvalidOperationException: 'Невозможно создать экземпляр типа' System.String ', так как отсутствует публикация c Конструктор без параметров.

Если я использую o bject или dynamici c, я получаю другую ошибку времени выполнения, когда service.AddSingleton(cfg => cfg.GetService<IOptions<MyOptions>>().Value); вызывается для регистрации экземпляра класса MyOptions, говоря: System.ArgumentNullException: 'Значение не может быть нулевым , Имя параметра: тип '

Если я использую JObject , я получаю {} назад, когда получаю доступ к свойству SubOptions объекта MyOptions, который вводится в мой API-контроллер.

Я знаю, что могу преобразовать подраздел в строковое свойство JSON путем экранирования данных подраздела, но я хочу избежать обработки подраздела как строки, и вместо этого оставьте это как raw JSON.

Можно ли делать то, что я хочу делать? Есть ли тип данных, который работает с шаблоном параметров, который позволит мне получить доступ к подразделу JSON без необходимости создания строго типизированного класса?

* Для фона я пытается создать метод API-контроллера, который возвращает содержимое подраздела JSON клиенту API. Я хочу избежать использования строго типизированного класса для подраздела, чтобы файл конфигурации JSON можно было редактировать на сервере, добавляя новые свойства и значения в подраздел, который будет возвращен клиенту API, без обновления кода C# и повторного развертывания службы API. Другими словами, я хочу, чтобы подраздел «1069 *» был «Dynami c», и просто вытащил его и отправил клиенту. *

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Вы можете получить необработанный объект конфигурации, установив для свойства SubOptions значение IConfigurationSection:

public class MyOptions
{
    public string Option1 { get; set; }
    public int Option2 { get; set; }
    public IConfigurationSection SubOptions { get; set; } // returns the "raw" section now
    public string SubOptions_take2 { get; set; }
}

, чтобы вы все равно связывали свой строго типизированный объект в файле Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(Configuration);
    ...
}

но здесь удача заканчивается, потому что, несмотря на то, что это целая секция - что касается связывателя опций, то все это уже десериализовано и проанализировано в иерархии значений. Кажется, нет простого способа собрать его обратно в одну строку. Внедрение IOptionsMonitor позволяет вам получить значения, выбрав .GetChildren(), но я не смог найти очевидный способ получить всю иерархию без написания собственного кода, чтобы просто рекурсивно обойти его (что я оставлю для вас, чтобы поиграть с вы чувствуете, что это стоит потраченных усилий):

public IndexModel(IOptionsMonitor<MyOptions> options)
{
    _options = options.CurrentValue;

    var subOptions = _options.SubOptions as ConfigurationSection;
    var children = subOptions.GetChildren(); // you see, the config has already been parsed into this hierarchy of items - it's too late to get the raw string value
    var s = JsonConvert.SerializeObject(children);
    // will produce something like this JSON:
    //[{"Path":"SubOptions:subOption1","Key":"subOption1","Value":"subvalue1_from_json"},{"Path":"SubOptions:subOption2","Key":"subOption2","Value":"200"}]    
}

одним из способов будет фактическое кодирование вашей json в виде строки в файле конфигурации:

"subOptions_take2": "{\"subOption1\": \"subvalue1_from_json\",\"subOption2\": 200}"

, тогда вы можете просто возьмите это позже:

public IndexModel(IOptionsMonitor<MyOptions> options)
{
    _options = options.CurrentValue;
    var subOptions_string = _options.SubOptions_take2;// this is valid json now: {"subOption1": "subvalue1_from_json","subOption2": 200}
}
0 голосов
/ 02 апреля 2020

Полагаю, вы можете использовать JObject из пакета Newtonsoft. Json - это JSON парсер и сериализатор по умолчанию в Asp. Net Core

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...