如果 SignalR 具有需要 class 实例的重载,则它不会调用服务器端方法
SignalR not invoking server-side method if it has an overload which expects an instance of a class
我在 my
中心有这个方法:
Public Sub SaveFields(ByVal changeSignal As String)
Dim foo As Integer = 5
End Sub
如果我像这样从客户端调用它:
testHub.server.saveFields("abc");
则SaveFields
调用成功。但是,如果我有这样的 Class
:
Public Class WOChangeSignal
Public WOID As Integer
Public FieldUpdates As Dictionary(Of String, String)
End Class
并为 SaveFields
添加重载,如下所示:
Public Sub SaveFields(ByVal changeSignal As WOChangeSignal)
Dim foo As Integer = 5
End Sub
Public Sub SaveFields(ByVal changeSignal As String)
Dim foo As Integer = 5
End Sub
然后我的电话
testHub.server.saveFields("abc");
会失败,就像我的调用一样
testHub.server.saveFields({
WOID: 1234,
FieldUpdates: [
{Key: 2, Value: 4},
{Key: 3, Value: 5}
]
});
因为 none 这些尝试实际上是在调用服务器端方法。因此,我认为问题出在需要 Class
实例的重载上。所以,我的问题如下:如果我添加期望 WOChangeSignal
参数的重载,为什么 SignalR 不调用重载的 none?
原来是这个原因:
/// <summary>
/// Searches the specified <paramref name="hub">Hub</paramref> for the specified <paramref name="method"/>.
/// </summary>
/// <remarks>
/// In the case that there are multiple overloads of the specified <paramref name="method"/>, the <paramref name="parameters">parameter set</paramref> helps determine exactly which instance of the overload should be resolved.
/// If there are multiple overloads found with the same number of matching parameters, none of the methods will be returned because it is not possible to determine which overload of the method was intended to be resolved.
/// </remarks>
/// <param name="hub">Hub to search for the specified <paramref name="method"/> on.</param>
/// <param name="method">The method name to search for.</param>
/// <param name="descriptor">If successful, the <see cref="MethodDescriptor"/> that was resolved.</param>
/// <param name="parameters">The set of parameters that will be used to help locate a specific overload of the specified <paramref name="method"/>.</param>
/// <returns>True if the method matching the name/parameter set is found on the hub, otherwise false.</returns>
public bool TryGetMethod(HubDescriptor hub, string method, out MethodDescriptor descriptor, IList<IJsonValue> parameters)
{
string hubMethodKey = BuildHubExecutableMethodCacheKey(hub, method, parameters);
if (!_executableMethods.TryGetValue(hubMethodKey, out descriptor))
{
IEnumerable<MethodDescriptor> overloads;
if (FetchMethodsFor(hub).TryGetValue(method, out overloads))
{
var matches = overloads.Where(o => o.Matches(parameters)).ToList();
// If only one match is found, that is the "executable" version, otherwise none of the methods can be returned because we don't know which one was actually being targeted
descriptor = matches.Count == 1 ? matches[0] : null;
}
else
{
descriptor = null;
}
// If an executable method was found, cache it for future lookups (NOTE: we don't cache null instances because it could be a surface area for DoS attack by supplying random method names to flood the cache)
if (descriptor != null)
{
_executableMethods.TryAdd(hubMethodKey, descriptor);
}
}
return descriptor != null;
}
正如我们所见,如果没有完全匹配,则描述符将为空。原来这是设计使然,给出的原因如下:
If only one match is found, that is the "executable" version,
otherwise none of the methods can be returned because we don't know
which one was actually being targeted
我在 my
中心有这个方法:
Public Sub SaveFields(ByVal changeSignal As String)
Dim foo As Integer = 5
End Sub
如果我像这样从客户端调用它:
testHub.server.saveFields("abc");
则SaveFields
调用成功。但是,如果我有这样的 Class
:
Public Class WOChangeSignal
Public WOID As Integer
Public FieldUpdates As Dictionary(Of String, String)
End Class
并为 SaveFields
添加重载,如下所示:
Public Sub SaveFields(ByVal changeSignal As WOChangeSignal)
Dim foo As Integer = 5
End Sub
Public Sub SaveFields(ByVal changeSignal As String)
Dim foo As Integer = 5
End Sub
然后我的电话
testHub.server.saveFields("abc");
会失败,就像我的调用一样
testHub.server.saveFields({
WOID: 1234,
FieldUpdates: [
{Key: 2, Value: 4},
{Key: 3, Value: 5}
]
});
因为 none 这些尝试实际上是在调用服务器端方法。因此,我认为问题出在需要 Class
实例的重载上。所以,我的问题如下:如果我添加期望 WOChangeSignal
参数的重载,为什么 SignalR 不调用重载的 none?
原来是这个原因:
/// <summary>
/// Searches the specified <paramref name="hub">Hub</paramref> for the specified <paramref name="method"/>.
/// </summary>
/// <remarks>
/// In the case that there are multiple overloads of the specified <paramref name="method"/>, the <paramref name="parameters">parameter set</paramref> helps determine exactly which instance of the overload should be resolved.
/// If there are multiple overloads found with the same number of matching parameters, none of the methods will be returned because it is not possible to determine which overload of the method was intended to be resolved.
/// </remarks>
/// <param name="hub">Hub to search for the specified <paramref name="method"/> on.</param>
/// <param name="method">The method name to search for.</param>
/// <param name="descriptor">If successful, the <see cref="MethodDescriptor"/> that was resolved.</param>
/// <param name="parameters">The set of parameters that will be used to help locate a specific overload of the specified <paramref name="method"/>.</param>
/// <returns>True if the method matching the name/parameter set is found on the hub, otherwise false.</returns>
public bool TryGetMethod(HubDescriptor hub, string method, out MethodDescriptor descriptor, IList<IJsonValue> parameters)
{
string hubMethodKey = BuildHubExecutableMethodCacheKey(hub, method, parameters);
if (!_executableMethods.TryGetValue(hubMethodKey, out descriptor))
{
IEnumerable<MethodDescriptor> overloads;
if (FetchMethodsFor(hub).TryGetValue(method, out overloads))
{
var matches = overloads.Where(o => o.Matches(parameters)).ToList();
// If only one match is found, that is the "executable" version, otherwise none of the methods can be returned because we don't know which one was actually being targeted
descriptor = matches.Count == 1 ? matches[0] : null;
}
else
{
descriptor = null;
}
// If an executable method was found, cache it for future lookups (NOTE: we don't cache null instances because it could be a surface area for DoS attack by supplying random method names to flood the cache)
if (descriptor != null)
{
_executableMethods.TryAdd(hubMethodKey, descriptor);
}
}
return descriptor != null;
}
正如我们所见,如果没有完全匹配,则描述符将为空。原来这是设计使然,给出的原因如下:
If only one match is found, that is the "executable" version, otherwise none of the methods can be returned because we don't know which one was actually being targeted