Как сделать ASP.NET Ядро (v3.1) Веб-API принимает параметр дочернего класса из тела

#c# #asp.net-core

Вопрос:

Сейчас я создаю API для приема информации о токенах третьих лиц и сохранения ее в БД. Определение класса, как:

 public class ThirdPartyBaseToken
{
    [JsonProperty("accessToken")]
    public virtual string AccessToken { get; set; }

    [JsonProperty("brand")]
    public virtual string Brand { get; set; }
}
 

И API в контроллере, как:

 public async Task<IActionResult> SaveTokenAsync([FromBody]ThirdPartyBaseToken tokenBody)
{
    var request = new SavingRequest
    {
        ThirdPartyToken = tokenBody.AccessToken,
        ……
        ……
    };
    
    await backendService.SaveAsync(request);

    return this.StatusCode(201);
}
 

Однако я встретил некоторые исключения, и после того, как я провел расследование, я обнаружил, что имена собственности от некоторых третьих лиц были «Доступны», но другие были «открыты».
В этом случае я создал дочерний класс, унаследованный от базового класса, и переопределил свойство JsonProperty, например:

 public class ThirdPartyChildToken: ThirdPartyBaseToken
{
    [JsonProperty("openToken")]
    public override string AccessToken { get; set; }
}
 

Я надеюсь, что как только появится свойство «OpenToken», API сможет принять его и правильно получить информацию о токене из accessToken.
К сожалению, я отладил локально и обнаружил, что параметр доступа по-прежнему равен нулю, что означает, что свойство JsonProperty(«OpenToken») не работало.

Не мог бы кто-нибудь дать мне несколько инструкций для решения этой проблемы?

Ответ №1:

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

 public string GetToken()
    => this.AccessToken ?? this.OpenToken ?? throw new Exception("Token is null.");
 

Это соглашение также имеет то преимущество, что вам не нужно указывать каждый [JsonProperty] атрибут явно.

Комментарии:

1. Спасибо, нет сомнений, что ваше решение может решить мою проблему, однако мне любопытно, смогу ли я найти элегантное решение. Если я не смогу найти какие-то лучшие решения, я применю ваше предложение.

2. @OceanSun Я знаю, что вы имеете в виду, но на самом деле я хотел сказать, что считаю это самым элегантным и правильным дизайном. Если вы найдете какие-либо другие решения, мне все равно было бы любопытно услышать.

3. Спасибо, я рассмотрел другое решение (я не уверен, что его можно достичь). Решение заключается в том, что я хочу создать новый атрибут с именем JsonProperties, унаследованный от JsonProperty, и этот дочерний класс может принимать несколько имен ключей JSON, таких как: [JsonProperties([«accessToken», «OpenToken»])] и переписать JsonHandler, чтобы принимать запросы от вызывающего. Но сейчас я воспользуюсь вашим решением, так как не хочу тратить больше времени на этот вопрос.

4. @OceanSun Держи меня в курсе. Это интересная проблема. Все еще не уверен, какой подход я бы предпочел. До сих пор я все еще нахожу это решение наиболее простым. Ваш тоже звучит неплохо, хотя я вижу некоторые проблемы, и, вероятно, это большая работа, так как я предполагаю, что вам придется написать пользовательский JsonSerializer.