Почему SignalR преобразует первые буквы ключей словаря в нижний регистр, когда сериализует словарь и отправляет его клиентам?

Вот что отправляется с сервера клиенту:

public class BattleHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        await Clients.Client(Context.ConnectionId).SendAsync("ConfigurationInfo",
            new Dictionary<string, string> { { "WtF", "WtF" } });

        await base.OnConnectedAsync();
    }
}

Вот что получает клиент:

{"wtF":"WtF"}

О чем свидетельствует следующий клиентский код:

const battle_connection = new signalR.HubConnectionBuilder().withUrl("/battlehub").build()

battle_connection.on("ConfigurationInfo", (bigDict) => {
    window.alert(JSON.stringify(bigDict))
})

Заметили изменение регистра в первой букве словарного ключа? Предполагалось, что будет отправлено "WtF", но вместо этого было отправлено "wtF".

Почему это происходит? Есть ли способ предотвратить это?

Любопытно, что это происходит только со словарными ключами: как видите, значения остаются неизменными. Кроме того, отправка только одной строки, не заключенной в словарь, не приводит к тому, что первая буква преобразуется в нижний регистр. List<string> также отправляется правильно.

Здесь действительно имеет значение регистр всех букв всех клавиш, поэтому приложение будет ошибаться, если какая-либо из них будет принудительно преобразована в нижний регистр! Хотя, конечно, мы можем придумать множество более или менее уродливых способов обойти эту проблему, но есть ли способ отключить это преобразование в сериализаторе SignalR?

ASP.NET Core 2.1


person Community    schedule 05.06.2018    source источник


Ответы (2)


Почему это происходит?

"Мы используем camelCase для имен в формате JSON, поскольку он лучше соответствует шаблонам JavaScript".
aspnet/SignalR#1415 (комментарий)

Есть ли способ предотвратить это?

... есть ли способ отключить это преобразование в сериализаторе SignalR?

Да.

services
    .AddSignalR()
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
    });
person aaron    schedule 05.06.2018
comment
Почему кто-то может подумать, что это хорошая идея?? Я надеюсь, что по умолчанию в 2.0 это не меняется. - person Donny V.; 28.01.2020
comment
@ДонниВ. Вы имеете в виду мой ответ или решение команды SignalR? - person aaron; 28.01.2020
comment
Решение команды SignalR. - person Donny V.; 28.01.2020
comment
@ДонниВ. - вещь, которая не упоминается, заключается в том, что причина, по которой это происходит, заключается в том, что SignalR отображает полезные данные в JSON, а JSON не различает словарь с ключами A, B и C, объект с именованными свойствами A, B, и C. Строго JSON на самом деле не поддерживает диктовки. Так что на самом деле команда SignalR решила переименовать свойства, чтобы они соответствовали соглашениям JavaScript для именованных свойств в классах, это раздражающий побочный эффект, что они делают это для dicts в C # DTO. Если вы, например. вместо этого используйте KeyValuePair[] , и этого не произойдет, потому что тогда ваш ключ dict не является именем свойства JSON. - person Jake Staines; 15.03.2021
comment
О боже, это потратило впустую около 1 часа моей жизни, пытаясь понять, почему имена свойств просто не привязывались к представлению. - person Kyle Whittington; 03.05.2021

person    schedule
comment
Это правильный ответ для .NET 5.0 и выше, поскольку ContractResolver больше не является свойством. - person Kyle Whittington; 03.05.2021