2017-11-08 2 views
0

Ich verwende SignalR 2.2.2 (Neuestes Release) mit .NET 4.5.2SignalR keine benutzerdefinierten

Ich habe diesen Fehler deserialisieren Objekt:

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.

Das Problem ist:

Ich habe einen SignalR-Client (in .NET geschrieben, mit Signal.Client-Paket), die ein benutzerdefiniertes Objekt senden, auf diesem Objekt gibt es ein Array von Objekt als Schnittstelle (IPropertyValueData) eingegeben. Die Werte im Array sind eine Implementierung dieser Schnittstelle.

 this._connection.JsonSerializer.TypeNameHandling = TypeNameHandling.Auto; 
     this._connection.JsonSerializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects; 
     this._connection.JsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; 

und es macht es richtig, wie hier ein Auszug von dem, was vom Kunden gesendet wird:

"Properties":[ 
    { 
     "$id":"20", 
     "$type":"DF.MailFlow.Services.Contract.Data.MailDataProperty, DF.MailFlow.Services.Contract", 
     "Id":"5588ce9e-30fb-45b1-afbe-1e6ad0c3e8d4", 

Im signalR Client, ich habe verwenden TypeNameHandling.Auto konfiguriert

Also ist die Eigenschaft $ type definiert und der Wert ist korrekt. Aber trotzdem, der Server löst immer noch den Fehler aus, wenn die Nachricht empfangen wird.

Ich habe konfiguriert auch den Server TypeNameHandling.Auto zu verwenden, ist hier, wie die Nabe ausgebildet ist, (I Schloss Windsor als IoC verwenden):

 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))); 

Ich habe überprüft, dass, wenn die erste Nachricht ist empfangen, wird die Factory-Methode aufgerufen und die Einstellung hat immer noch den richtigen TypeNameHandling.Auto.

Getestet habe ich auch den Serializer auf diese Weise registrieren:

GlobalHost.DependencyResolver.Register(typeof(JsonSerializer),() => JsonSerializer.Create(serializerSettings)); 

aber keine Möglichkeit, die Server immer die gleichen Fehler auslösen, wenn die Nachricht empfangen wird.

Zusätzlich zu der Komplexität führt die Anwendung sowohl Signal- als auch Webapi-Komponente (in unterschiedlicher URL) aus. Ich habe überprüft, dass der Webapi keine JsonSerializer registriert, und Windsor Container ist für beide Komponenten identisch.

Irgendeine Idee?

Edit # 1:

ich auf diesem Ticket gerade lief https://github.com/SignalR/SignalR/issues/3304
gerade scheint unglaublich, dass ein Fehler dort für mehr als 3 Jahre ohne Update, das aufgeführt wird, auch wenn jemand ein PR (https://github.com/SignalR/SignalR/pull/3343) gemacht
So, jetzt eine Abhilfe ich versuche ... Dieses Problem

Antwort

0

zu finden klar aufgrund eines Fehlers in SignalR

Die Abhilfe in dieser 012.398 gepostetWerke, das heißt einen benutzerdefinierten Resolver registrieren:

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); 
    } 
} 

Die Diskussion darüber, wie diese Fehler zu beheben ist jetzt auf this ticket, so dass man dort finden konnte, wenn es wird (hoffentlich)

gelöst werden
Verwandte Themen