简体   繁体   中英

Connection response properties are camel case

I have no idea why this is happening. I'm connecting my angular 4 app to a signalR hub from the hosting server and it works like a charm (version 2.2.2)

I'm now having to add a second signalR connection to another project and for some unknown reason the properties of the response are all camelCase in stead of PascalCase. The jquery.signalr-2.2.2.js file however expects them to be PascalCase and throws an error that the server version is "undefined".

"Undefined" is logical since he's looking for res.ProtocolVersion and that property does not exist on my deserialized response. I do however have a res.protocolVersion and that one holds the exact value that he needs.

I've been losing a lot of time on this, any help is seriously appreciated!

调试jquery.signalR-2.2.2.js

Edit: @rory-mccrossan 在此处输入图片说明 I thought as much and that's why I commented out the server side json serializer/formatter code, but to no avail.

I'm taking any suggestion where to look next

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM