Небольшая проблема, с которой я столкнулся сегодня. Клиенту не удается вызвать серверный метод (ошибка: значение не может быть нулевым), если серверный метод принимает необязательные параметры, а клиентский вызов исключает необязательный параметр:
Сервер:
public void GetAll(long Id, bool DoSomething=false)
Клиент:
myHub.GetAll(12);
Мы можем улучшить разрешение методов.
Определенно хорошая идея. Начал фактически работать над этим, но вернулся к реализации базовой реализации динамических концентраторов как можно скорее.
Кстати о разрешении метода ...
В текущей реализации мы также можем добавить поддержку перегрузок методов. Можно было бы также добавить разрешение именованных параметров, но это потребовало бы некоторых изменений в том, как параметры фактически передаются между клиентом и сервером (передача пар ключ-значение вместо просто значений). Что ты думаешь?
Применимо ли это также к параметру, допускающему значение NULL? У меня есть метод с 3 параметрами, последний из которых является обнуляемым int (int?). Если я установлю последний параметр равным null, я получу исключение:
Значение не может быть нулевым.
Имя параметра: o
в Newtonsoft.Json.Utilities.ValidationUtils.ArgumentNotNull (значение объекта, String имя параметра)
в Newtonsoft.Json.Linq.JToken.FromObjectInternal (Object o, JsonSerializer jsonSerializer)
в Newtonsoft.Json.Linq.JToken.FromObject (Object o, JsonSerializer jsonSerializer)
в Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke T
в GeoTag.App.Core.Services.SignalRClientService.
Обратите внимание, что я не установил для него значение по умолчанию на сервере
Мы переместим это в новое репо в качестве кандидата v3.
@JasonBSteele - Я знаю, что это было давно, но проблема, о которой вы говорите, только что решена. Ожидайте увидеть это в следующем выпуске.
Я не понимаю, в каком состоянии находится эта проблема. Было ли это исправлено в каком-либо выпуске SignalR?
@paulirwin Нет
...
Исправление находится в версии 2.2.1, выпущенной в июле (https://github.com/SignalR/SignalR/releases/tag/2.2.1).
Я повторно проверил то, с чем столкнулся вчера, вот мои выводы:
Метод концентратора, который будет вызывать клиент
public async Task EpicMethod( int? daysTillNETStandard20 ) {}
Попытки вызова метода клиент-сервер .NET:
1. await _serviceRequestHubProxy.Invoke(nameof(ISomethingOnServerSide.EpicMethod), null).ConfigureAwait(false);
System.ArgumentNullException: Value cannot be null.
Parameter name: args
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke[TResult,TProgress](String method, Action`1 onProgress, Object[] args)
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke(String method, Object[] args)
2. await _serviceRequestHubProxy.Invoke(nameof(ISomethingOnServerSide.EpicMethod), null, null).ConfigureAwait(false);
System.InvalidOperationException: 'EpicMethod' method could not be resolved. Potential candidates are:
EpicMethod(daysTillNETStandard20:Nullable`1):Task
3. await _serviceRequestHubProxy.Invoke(nameof(ISomethingOnServerSide.EpicMethod), null, new object[] {}).ConfigureAwait(false);
System.InvalidOperationException: 'EpicMethod' method could not be resolved. Potential candidates are:
EpicMethod(daysTillNETStandard20:Nullable`1):Task
4. await _serviceRequestHubProxy.Invoke(nameof(ISomethingOnServerSide.EpicMethod), null, new object[] {null}).ConfigureAwait(false);
System.InvalidOperationException: 'EpicMethod' method could not be resolved. Potential candidates are:
EpicMethod(daysTillNETStandard20:Nullable`1):Task
поэтому на данный момент я удалил значение NULL из метода концентратора и передал 0 со стороны клиента
Повторное открытие в соответствии с вашим выводом ...
У меня тоже есть эта проблема. Разрешится?
Похоже на то, что связыватель не преобразует null
в Nullable<T>
. Я займусь расследованием.
Получается, что это на самом деле задумано. Как на самом деле следует передавать массив объектов со значением null. Как это на вашем примере
await _serviceRequestHubProxy.Invoke(nameof(ISomethingOnServerSide.EpicMethod), new object[] {null}).ConfigureAwait(false);
Что вы делали, так это устанавливали для массива params, который использует преобразователь параметров, значение null вместо передачи нулевого значения в массив params.
Предполагается, что проблема будет решена в текущей версии? Поскольку дата выпуска была 5 лет назад, но необязательные параметры все еще не работают для меня?
@AlameerAshraf - покажите, что именно вы пытаетесь сделать. Я не думаю, что на данный момент есть какие-либо планы что-либо менять в этой области.
Я не думаю, что необязательные параметры работают должным образом. У нас есть вызов без параметров, к которому я хочу добавить параметр.
К сожалению, нет способа сделать это без нарушения обратной совместимости, поскольку наш клиентский код в настоящее время вызывает без аргументов, я получаю System.IO.InvalidDataException: Invocation предоставляет 0 аргументов, но цель ожидает 1 - даже с одним необязательным параметром _nullable_.
Если мне нужно изменить своего клиента, чтобы передать значение null, я не смогу поддерживать обратную совместимость, а также могу вообще не использовать необязательный параметр 😦
Обходной путь: добавьте и вызовите новый метод с другим именем, который переадресуется обратно к исходному, если не передан параметр. Неутешительно
Я действительно думаю, что необязательные параметры метода и перегрузка должны поддерживаться - на самом деле это может быть запоздалым, поскольку обычно используются и те, и другие, а не интуитивно не использовать их при использовании SignalR.
Здесь в 2020 году перегрузка методов работает, но необязательные параметры - нет, в любом случае я думаю, что все еще легко просто вызвать параметризованный метод из непараметризованного и сохранить обратную совместимость.
Самый полезный комментарий
Я не думаю, что необязательные параметры работают должным образом. У нас есть вызов без параметров, к которому я хочу добавить параметр.
К сожалению, нет способа сделать это без нарушения обратной совместимости, поскольку наш клиентский код в настоящее время вызывает без аргументов, я получаю System.IO.InvalidDataException: Invocation предоставляет 0 аргументов, но цель ожидает 1 - даже с одним необязательным параметром _nullable_.
Если мне нужно изменить своего клиента, чтобы передать значение null, я не смогу поддерживать обратную совместимость, а также могу вообще не использовать необязательный параметр 😦
Обходной путь: добавьте и вызовите новый метод с другим именем, который переадресуется обратно к исходному, если не передан параметр. Неутешительно