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 正确发送对象,没有错误!