SignalR and camelCase data contracts

I really like SignalR for its capability to do push notifications from the server to the client. But there are a few thing in SignalR I am not quite happy with. Fortunately SignalR is really pluggable and you can change it to suit your needs. :-)

 

PascalCase versus camelCase

One thing I am not really happy about is the fact that all data is send over the wire with a request as is. And with SignalR the server tends to be C# where the convention is to have methods and properties in PascalCase. The client side however is JavaScript where the usual convention is to have methods and properties in camelCase.

 

With functions defined on a SignalR Hub this is no problem. SignalR does the right thing and converts them from the server side PascalCase to the client side camelCase so everyone is happy.

 

However with the data passed as arguments this is not the case and they are passed as is. It turns out SignalR is using JSON.NET which is a really powerful JSON serializer that can do just that. All you need to do is start using the CamelCasePropertyNamesContractResolver and Bob is your uncle. Or is he?

 

Unfortunately things aren’t that simple. It turns out just using CamelCasePropertyNamesContractResolver will break the internal SignalR data contracts and that is not a good thing. But with a bit of help we can still get this to work.

 

The SignalRContractResolver that makes things work

The solution is the SignalRContractResolver found here.

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


    }


 


    public JsonContract ResolveContract(Type type)


    {


        if (type.Assembly.Equals(_assembly))


        {


            return _defaultContractSerializer.ResolveContract(type);


        }


 


        return _camelCaseContractResolver.ResolveContract(type);


    }


}

With this contract resolver the SignalR types are send as is and all your custom types are send using the camelCase properties the JavaScript client code is used to. Sweet right :-)

 

With the SignalRContractResolver in place all we need to do is register it with SignalR. Below is the code I use to do that.

public static void RegisterHubs()


{


    var serializerSettings = new JsonSerializerSettings


    {


        ContractResolver = new SignalRContractResolver()


    };


    var jsonNetSerializer = new JsonNetSerializer(serializerSettings);


    GlobalHost.DependencyResolver.Register(typeof (IJsonSerializer), () => jsonNetSerializer);


 


    RouteTable.Routes.MapHubs();


}



 



Enjoy!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>