2016-06-15 15 views
5

Korzystanie .NET Core RC2. Działa SignalR, ale próbuje odzyskać właściwości camelCase w JSON.SignalR .NET Core camelCase JSON Contract Resolver

Dla API używam ...

services.AddMvc().AddJsonOptions(o => { 
    o.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
}); 

Może jest po prostu nic w miejscu jeszcze SignalR (mimo wszystko, to nawet nie miała jeszcze do pracy ...), ale zastanawiam się, czy ktoś się zorientowali to jeszcze? Próbowałem już kilku rzeczy, takich jak ...

services.AddTransient<IContractResolver, CamelCasePropertyNamesContractResolver>(); 

... ale nie ma go.

Ktoś jeszcze to działa?

+2

Te pytania i odpowiedzi dotyczą .net 4.5/4.6, a nie core. – PersonThing

Odpowiedz

11

Na podstawie this issue z repozytorium SignalR Core, nie ma natywnego sposobu robienia tego od teraz, ale można utworzyć niestandardowy resolver umowy, jak wskazano w this comment on an old SignalR issue.

Ponieważ ten wątek jest dla SignalR 2.2.0, zróbmy to dla SignalR Core.

using System; 
using System.Reflection; 
using Microsoft.AspNetCore.SignalR.Infrastructure; 
using Newtonsoft.Json.Serialization; 

    public class SignalRContractResolver : IContractResolver 
    { 
     private readonly Assembly _assembly; 
     private readonly IContractResolver _camelCaseContractResolver; 
     private readonly IContractResolver _defaultContractSerializer; 

     public SignalRContractResolver() 
     { 
      _defaultContractSerializer = new DefaultContractResolver(); 
      _camelCaseContractResolver = new CamelCasePropertyNamesContractResolver(); 
      _assembly = typeof(Connection).GetTypeInfo().Assembly; 
     } 


     public JsonContract ResolveContract(Type type) 
     { 
      if (type.GetTypeInfo().Assembly.Equals(_assembly)) 
       return _defaultContractSerializer.ResolveContract(type); 

      return _camelCaseContractResolver.ResolveContract(type); 
     } 

    } 

Co się dzieje, jest to, że nie można używać zamówieniu case wielbłąd rozpoznawania nazw dla wewnętrznych SignalR, ponieważ byłoby to przerwać komunikację z klientem.

Tak więc za każdym razem, gdy rozwiązujemy umowę w metodzie ResolveContract, musimy sprawdzić złożenie aktualnie rozpatrywanego typu i sprawdzić, czy jest to sygnał wewnętrzny SignalR. Jeśli nie, wówczas możemy rozwiązać umowę za pomocą walizki wielbłądziej.

W tym momencie musimy zarejestrować resolver umowy w ramach.

public void ConfigureServices(IServiceCollection services) 
    { 
     var settings = new JsonSerializerSettings(); 
     settings.ContractResolver = new SignalRContractResolver(); 

     var serializer = JsonSerializer.Create(settings); 

     services.Add(new ServiceDescriptor(typeof(JsonSerializer), 
              provider => serializer, 
              ServiceLifetime.Transient)); 

     // register other services like SignalR, MVC and custom services 
    } 

Powodzenia!

+0

Dokładnie to, czego szukałem i działa świetnie. Dziękuję Ci! – PersonThing

+4

Świetne, dzięki. Sprowadziłem rejestrację do jednej linijki: 'services.AddSingleton (_ => nowy JsonSerializer {ContractResolver = new SignalRContractResolver()});' (i poszedł z singletonem). – Stajs

4

Jako pierwszego ostatecznej wersji alfa signalR rdzenia (alfa1-1.0.0-wersja ostateczna), można uzyskać przypadek wielbłąda jak fragmencie kodu poniżej natywnie:

services.AddSignalR(option => 
{ 
    option.JsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
}); 

W rzeczywistości, można również zatrudniać dowolny niestandardowy przelicznik zamiast CamelCasePropertyNamesContractResolver.

+0

Dzięki za aktualizację, Arash. Dobrze wiedzieć. Używałem SignalR przez jakiś czas, ale po tym, jak Azure zrzucił wsparcie dla project.json, zamiast tego zaimplementowałem prosty .netowy serwer sieci web dla moich potrzeb. Mogę przełączyć się na SignalR, kiedy zostanie wydany oficjalny rdzeń SignalR .net, aby uniknąć konieczności wykonywania niestandardowej implementacji, ale na razie działa dobrze. – PersonThing