SignalR .NET Core camelCase JSON Contract Resolver

Based on this issue from the SignalR Core repository, there is no native way of doing this as of right now, but you can create a custom contract resolver as indicated in this comment on an old SignalR issue.

Since that thread is for SignalR 2.2.0, let's make it work for 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);
        }

    }

What happens here is that you cannot use the camel case contract resolver for the SignalR internals, because it would break the communication with the client.

So every time we resolve a contract in the ResolveContract method we have to check the assembly of the type currently resolved and check wether it is SignalR internal. If not, then we can resolve the contract using camel case.

At this point, we need to register this contract resolver in the framework.

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
     }

Best of luck!


Let me quote the answer of anurse on GitHub:

Since the protocols are pluggable, the options were moved to a different location because you may choose not to use JSON at all. Now you set them in the .AddJsonProtocol extension method in ConfigureServices, like this:

services.AddSignalR()
.AddJsonProtocol(options => {
    // Edit or replace 'options.PayloadSerializerSettings' here!
});

As of the first final alpha release of signalR core (1.0.0-alpha1-final), you can get camel case like the code snippet below natively:

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

In fact, you can also employ any customized resolver instead of CamelCasePropertyNamesContractResolver.