So after Rory's hint I searched some more on the internet and of course, someone else has run into this problem:
SignalR : use camel case
However, the solution isn't working for me :/
Then I found a similar solution, here however you'll always have the default contract resolver except when the object comes from a certain library -the one with your view models-.
https://blogs.msdn.microsoft.com/stuartleeks/2012/09/10/automatic-camel-casing-of-properties-with-signalr-hubs/
Note: This is not the perfect solution, but it is one that worked best for my scenario
So I came up with a new solution all together that ties in nicely with the existing code that is giving me the problem.
The other way to go around this is to let your app use the DefaultContractResolver
. SignalR will now connect, but the rest of your application will break. To mitigate this in the solution I'm working in I used two simple extension methods.
Firstly I extended the HttpConfiguration
class to swap out the formatter for a CamelCasePropertyNamesContractResolver
public static class HttpConfigurationExtensions
{
public static HttpConfiguration ToCamelCaseHttpConfiguration(this HttpConfiguration configuration)
{
var jsonFormatter = configuration.Formatters.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
bool needToAddFormatter = jsonFormatter == null;
if (needToAddFormatter)
{
jsonFormatter = new JsonMediaTypeFormatter();
}
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
if (needToAddFormatter)
{
configuration.Formatters.Add(jsonFormatter);
}
return configuration;
}
}
The existing Web API will always return a HttpResponseMessage
and that's why I could go about it in the way that I did.
Example of an api call
[Route("")]
[HttpPost]
public async Task<HttpResponseMessage> CreateSetting(Setting setting)
{
// the response object is basically the data you want to return
var responseData = await ...
return Request.CreateResponse(responseData.StatusCode, responseData);
}
I noticed every Api call was using the Request.CreateResponse(...)
method. What I didn't see immediately is that Microsoft actually has foreseen all necessary overloads, this meant I couldn't just make my own Request.CreateResponse(...)
implementation.
That's why it's called MakeResponse
public static class HttpRequestMessageExtensions
{
public static HttpResponseMessage MakeResponse<T>(this HttpRequestMessage request, T response) where T : Response
{
return request.CreateResponse(response.StatusCode, response,
request.GetConfiguration().ToCamelCaseHttpConfiguration());
}
}
The Response
classes are the data structures that you want your api to return. In our api they all got wrapped into one of these structures. This results into an api with responses similar to the ones on the Slack API.
So now the controllers all use Request.MakeResponse(responseData)