Signalr: 可选参数

创建于 2012-04-19  ·  19评论  ·  资料来源: SignalR/SignalR

我今天遇到的一个小问题。 如果服务器方法接受可选参数,并且客户端调用不包括可选参数,则客户端无法调用服务器方法(错误:值不能为null):

服务器:

public void GetAll(long Id, bool DoSomething=false)

客户:

myHub.GetAll(12);

最有用的评论

我认为可选参数无法按预期工作。 我们有一个不带参数的呼叫,我正在向其添加参数。

不幸的是,没有不破坏向后兼容性的方法是不可能的,因为我们的客户端代码当前不带参数调用,所以我得到System.IO.InvalidDataException:调用提供了0个参数,但是目标期望1-即使有一个_nullable可选parameter_。

如果我必须更改客户端以传递null,那么我将无法保持向后兼容性,也可能根本不使用可选参数😦

解决方法:添加并调用一个具有不同名称的新方法,如果未传递任何参数,则该方法将转发回原始方法。 令人失望的👎

所有19条评论

我们可以使方法解析更智能。

绝对是个好主意。 开始实际从事此工作,但后来恢复以尽快推动基本的动态集线器实施。

说到方法解析...
使用当前的实现,我们还可以添加方法重载支持。 也可以添加命名参数解析,但这将暗示对在客户端和服务器之间实际传递参数的方式进行一些修改(传递键值对,而不仅仅是传递值)。 你觉得呢

这是否也适用于Nullable参数? 我有一个带有3个参数的方法,最后一个参数是可为null的int(int?)。 如果将最后一个参数设置为null,则会出现异常:

值不能为空。
参数名称:o

在Newtonsoft.Json.Utilities.ValidationUtils.ArgumentNotNull(对象值,字符串parameterName)
在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处。d__9.MoveNext()

请注意,我尚未在服务器上为其设置默认值

我们将其作为v3候选版本移到新的存储库中

@JasonBSteele-我知道已经有一段时间了,但是您提到的问题已经解决。 期望在下一个版本中看到它。

我对这个问题的现状感到困惑。 是否已在任何SignalR版本中对其进行了修复?

@paulirwin

...

该修补程序位于7月发布的2.2.1中(https://github.com/SignalR/SignalR/releases/tag/2.2.1)

我重新测试了昨天遇到的问题,这是我的发现:
客户端将调用的Hub方法

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

所以现在我从中心方法中删除了可空性,并从客户端传递了0

根据您的发现重新打开...

我也有这个问题。 会解决吗?

听起来很简单,就是活页夹不会将null转换为Nullable<T> 。 我会调查

因此证明这实际上是设计使然。 实际上应该如何传递值为null的对象数组。 像这样使用您的示例
await _serviceRequestHubProxy.Invoke(nameof(ISomethingOnServerSide.EpicMethod), new object[] {null}).ConfigureAwait(false);

您正在做的是将参数解析器使用的params数组设置为null,而不是将null值传递给params数组。

该问题应该在当前版本中解决吗? 由于发布日期是5年前,但是可选参数仍然对我不起作用?

@AlameerAshraf-确切显示您要执行的操作。 我认为目前还没有任何计划改变这一领域。

我认为可选参数无法按预期工作。 我们有一个不带参数的呼叫,我正在向其添加参数。

不幸的是,没有不破坏向后兼容性的方法是不可能的,因为我们的客户端代码当前不带参数调用,所以我得到System.IO.InvalidDataException:调用提供了0个参数,但是目标期望1-即使有一个_nullable可选parameter_。

如果我必须更改客户端以传递null,那么我将无法保持向后兼容性,也可能根本不使用可选参数😦

解决方法:添加并调用一个具有不同名称的新方法,如果未传递任何参数,则该方法将转发回原始方法。 令人失望的👎

我真的认为应该支持可选的方法参数和重载-实际上这可能已经过期了,因为在使用SignalR时经常同时使用它们和违反直觉的做法很常见。

在2020年,方法重载有效,但可选参数无效,无论如何,我认为从非参数化调用参数化方法并保持向后兼容性仍然很容易。

此页面是否有帮助?
0 / 5 - 0 等级