SignalR 不反序列化自定义对象
SignalR doesn't deserialize custom object
我在 .NET 4.5.2 中使用 SignalR 2.2.2(最新版本)
我有这个错误:
Could not create an instance of type
DF.ApplicationBlocks.IPropertyValueData. Type is an interface or
abstract class and cannot be instantiated. Path 'Properties[0].Id',
line 1, position 881.
问题是:
我有一个发送自定义对象的 SignalR 客户端(用 .NET 编写,使用 Signal.Client 包),在这个对象上有一个类型为接口 (IPropertyValueData) 的对象数组。数组中的值是此接口的实现。
在 signalR 客户端中,我配置为使用 TypeNameHandling.Auto :
this._connection.JsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
this._connection.JsonSerializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
this._connection.JsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
它正确地完成了,因为这是客户端发送的内容的摘录:
"Properties":[
{
"$id":"20",
"$type":"DF.MailFlow.Services.Contract.Data.MailDataProperty, DF.MailFlow.Services.Contract",
"Id":"5588ce9e-30fb-45b1-afbe-1e6ad0c3e8d4",
所以 $type 属性 被定义并且值是正确的。
但是无论如何,服务器在收到消息时仍然会触发错误。
我还配置了服务器以使用 TypeNameHandling.Auto,这是集线器的配置方式(我使用 Castle Windsor 作为 IoC):
var resolver = new WindsorDependencyResolver(WebAPILoader.Container);
var hubConfig = new HubConfiguration()
{
EnableJSONP = true,
EnableDetailedErrors = true,
EnableJavaScriptProxies = true,
Resolver = resolver
};
GlobalHost.DependencyResolver = resolver;
// Configure signalR and run it
app.UseCors(CorsOptions.AllowAll);
app.Map("/live", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR(hubConfig);
});
var serializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = serializerSettings;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
// Register in Castle.Windsor container
WebAPILoader.Container.Register(Castle.MicroKernel.Registration.Component
.For<JsonSerializer>()
.UsingFactoryMethod(() => JsonSerializer.Create(serializerSettings)));
我检查过当收到第一条消息时,工厂方法被调用并且设置仍然正确TypeNameHandling.Auto。
我也测试过用这种方式注册序列化程序:
GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => JsonSerializer.Create(serializerSettings));
但没办法,服务器收到消息时总是触发相同的错误。
增加了复杂性,应用程序 运行 signalr 和 webapi 组件(不同 url)。我检查过 webapi 没有注册任何 JsonSerializer,并且两个组件使用的 Windsor 容器是相同的。
有什么想法吗?
编辑#1:
这张票我刚运行https://github.com/SignalR/SignalR/issues/3304
似乎令人难以置信的是,一个错误被列在那里超过 3 年没有任何修复,即使有人做了 PR (https://github.com/SignalR/SignalR/pull/3343)
所以现在我正在尝试找到解决方法...
这个问题显然是由于 SignalR 中的错误
此 link 中发布的解决方法有效,即注册自定义解析器:
private class Resolver : DefaultParameterResolver
{
private readonly JsonSerializer _serializer;
public Resolver(JsonSerializer serializer)
{
_serializer = serializer;
}
private FieldInfo _valueField;
public override object ResolveParameter(ParameterDescriptor descriptor, Microsoft.AspNet.SignalR.Json.IJsonValue value)
{
if (value.GetType() == descriptor.ParameterType)
{
return value;
}
if (_valueField == null)
_valueField = value.GetType().GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic);
var json = (string)_valueField.GetValue(value);
using (var reader = new StringReader(json))
return _serializer.Deserialize(reader, descriptor.ParameterType);
}
}
关于如何解决此错误的讨论现在在 this ticket 上进行,所以当它(希望)得到解决时您可以在那里找到
我遇到了同样的问题,SignalR 显示自定义对象错误。我通过在所有 SignalR-related 代码中将对象的数据类型更改为 'dynamic' 不小心修复了它,例如:
// Bad
public void Receive_SendBoardObject(Board myboard)
// Good
public void Receive_SendBoardObject(dynamic myboard)
现在 SignalR 正确发送对象,没有错误!
我在 .NET 4.5.2 中使用 SignalR 2.2.2(最新版本)
我有这个错误:
Could not create an instance of type DF.ApplicationBlocks.IPropertyValueData. Type is an interface or abstract class and cannot be instantiated. Path 'Properties[0].Id', line 1, position 881.
问题是:
我有一个发送自定义对象的 SignalR 客户端(用 .NET 编写,使用 Signal.Client 包),在这个对象上有一个类型为接口 (IPropertyValueData) 的对象数组。数组中的值是此接口的实现。
在 signalR 客户端中,我配置为使用 TypeNameHandling.Auto :
this._connection.JsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
this._connection.JsonSerializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
this._connection.JsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
它正确地完成了,因为这是客户端发送的内容的摘录:
"Properties":[
{
"$id":"20",
"$type":"DF.MailFlow.Services.Contract.Data.MailDataProperty, DF.MailFlow.Services.Contract",
"Id":"5588ce9e-30fb-45b1-afbe-1e6ad0c3e8d4",
所以 $type 属性 被定义并且值是正确的。 但是无论如何,服务器在收到消息时仍然会触发错误。
我还配置了服务器以使用 TypeNameHandling.Auto,这是集线器的配置方式(我使用 Castle Windsor 作为 IoC):
var resolver = new WindsorDependencyResolver(WebAPILoader.Container);
var hubConfig = new HubConfiguration()
{
EnableJSONP = true,
EnableDetailedErrors = true,
EnableJavaScriptProxies = true,
Resolver = resolver
};
GlobalHost.DependencyResolver = resolver;
// Configure signalR and run it
app.UseCors(CorsOptions.AllowAll);
app.Map("/live", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR(hubConfig);
});
var serializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = serializerSettings;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
// Register in Castle.Windsor container
WebAPILoader.Container.Register(Castle.MicroKernel.Registration.Component
.For<JsonSerializer>()
.UsingFactoryMethod(() => JsonSerializer.Create(serializerSettings)));
我检查过当收到第一条消息时,工厂方法被调用并且设置仍然正确TypeNameHandling.Auto。
我也测试过用这种方式注册序列化程序:
GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => JsonSerializer.Create(serializerSettings));
但没办法,服务器收到消息时总是触发相同的错误。
增加了复杂性,应用程序 运行 signalr 和 webapi 组件(不同 url)。我检查过 webapi 没有注册任何 JsonSerializer,并且两个组件使用的 Windsor 容器是相同的。
有什么想法吗?
编辑#1:
这张票我刚运行https://github.com/SignalR/SignalR/issues/3304
似乎令人难以置信的是,一个错误被列在那里超过 3 年没有任何修复,即使有人做了 PR (https://github.com/SignalR/SignalR/pull/3343)
所以现在我正在尝试找到解决方法...
这个问题显然是由于 SignalR 中的错误
此 link 中发布的解决方法有效,即注册自定义解析器:
private class Resolver : DefaultParameterResolver
{
private readonly JsonSerializer _serializer;
public Resolver(JsonSerializer serializer)
{
_serializer = serializer;
}
private FieldInfo _valueField;
public override object ResolveParameter(ParameterDescriptor descriptor, Microsoft.AspNet.SignalR.Json.IJsonValue value)
{
if (value.GetType() == descriptor.ParameterType)
{
return value;
}
if (_valueField == null)
_valueField = value.GetType().GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic);
var json = (string)_valueField.GetValue(value);
using (var reader = new StringReader(json))
return _serializer.Deserialize(reader, descriptor.ParameterType);
}
}
关于如何解决此错误的讨论现在在 this ticket 上进行,所以当它(希望)得到解决时您可以在那里找到
我遇到了同样的问题,SignalR 显示自定义对象错误。我通过在所有 SignalR-related 代码中将对象的数据类型更改为 'dynamic' 不小心修复了它,例如:
// Bad
public void Receive_SendBoardObject(Board myboard)
// Good
public void Receive_SendBoardObject(dynamic myboard)
现在 SignalR 正确发送对象,没有错误!