Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Support CamelCasePropertyNamesContractResolver when serialize #500

Closed
scott-xu opened this Issue · 31 comments
@scott-xu

For issue 138:
#138

Can we use JsonProperty in the build-in objects to serialize to {"Url":"/signalr","ClientId":"194d19cf-219b-405e-9ed2-d5309d098022"} so that we can choose using CamelCasePropertyNamesContractResolver or not.

@davidfowl
Owner

No. You can add it to your own objects though.

@scott-xu

Come on. It makes sense if give the end user free to use CamelCasePropertyNamesContractResolver or not.
What if we can't modify the entities, or just want the entity project has no dependencies

@davidfowl
Owner

Write a custom resolver that checks if the type is in the SignalR assembly, seems simple enough. The problem is the client hardcodes a particular case, so you'll break the javascript (and possibly other clients) if you change it.

@scott-xu

Your solution above seems to be another hardcodes. How about make your connection object dynamicly generated as well?

@scott-xu

or use camelCase by default so that it works no matter use CamelCasePropertyNamesContractResolver or not

@davidfowl
Owner

Thanks for the suggestion, we'll think about it.

@worldspawn

Thanks for the suggestion to roll my own resolver and check the assembly. Fixed my problem.

using System;
using System.Reflection;
using Newtonsoft.Json.Serialization;
using SignalR;

namespace Loveboat.Configuration
{
    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;
        }

        #region IContractResolver Members

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

            return _camelCaseContractResolver.ResolveContract(type);
        }

        #endregion
    }
}
var settings = new JsonSerializerSettings();
            settings.ContractResolver = new SignalRContractResolver();
            var serializer = new JsonNetSerializer(settings);
            GlobalHost.DependencyResolver.Register(typeof (IJsonSerializer), () => serializer);
@bytenik

+1 for adding native support to this. In the meantime this code snip was awesome.

@chrisdostert

+1 for native support and thanks for the code snip; worked like a charm.

@RooSoft

+1 here for native support...

@Jaben

A different solution that special-cases the response output:

https://gist.github.com/Jaben/6550139

@bytenik

This code snip doesn't work for 2.0. Any suggestions?

@davidfowl
Owner
var settings = new JsonSerializerSettings();
settings.ContractResolver = new SignalRContractResolver();
var serializer = JsonSerializer.Create(settings);
GlobalHost.DependencyResolver.Register(typeof (JsonSerializer), () => serializer);
@tomsquires

The new code doesn't work for me. I'm using the same contract resolver as I used in v1 successfully. I'm registering it as above. I have tried it both in the Startup.cs and Global.asax. Nothing breaks, no exceptions however the ContractResolver never seems to be hit and the Json comes out in the wrong case.

@tomsquires

I had a look through the code and I think I found why its using default serializer even if you override it #2621

@davidfowl
Owner

That's only for incoming though right? It shouldn't matter for what makes it to javascript (FYI that bug has always been there).

@tomsquires

Actually now you mention it yes i think it is for both. Ill have a bit more of a look and see if i can find the root cause.

@IharKrasnik

These code samples are not working. I use SignalRContractResolver and it's resolver's setting (code written above), but SignalRContractResolver.ResolveContract is never called, so default Contract Resolver is used.
It's seems that registration of JsonSerializer don't work, because the same code on old versions, using resolving of IJsonSerializer works fine.
What can be a problem? ( SignalR v. 2.0)

@AndersMalmgren

Same here, cant upgrade to 2.0 before this is fixed

@AndersMalmgren

Looks like the problem is that we cant overwrite already register types in the DependecyResolver

@AndersMalmgren

Found the problem, maybe it can help you guys.

I use Ninject as dependency resolver, I use code found on the net to hook up Ninject with SignalR

When GetService is called the code is doing

return kernel.TryGet(serviceType) ?? base.GetService(serviceType);

This worked before because we used a interface instead of concrete type, with a concrete type Ninject will instance a default JsonSerializer and not call base.GetService(serviceType)

@davidfowl
Owner

Ahhh, that's a good one. We'll look into this.

@AndersMalmgren

If you flip the two it works :D

edit: But that will break if you override types in the Ninject kernel. bummer

I guess only way is to do kernel.GetBindings and check that a binding is actually registered for the type

@DamianEdwards DamianEdwards added the v3 label
@DamianEdwards

Well move this to the new repo as a candidate for v3 or beyond

@scott-xu
@stajs

+1 for native support, and confirming that the code snip doesn't work for me on 2.0.3

@MartinDevillers

+1 for native support and I fully support scott-xu motivation. Our domain objects are automatically generated from a canonical data model so we can't easily change these. Moreover, it seems more sensible to make the few fields in the SignalR library "case-proof", than expect all your users all over the world to litter their models with JSON-attributes.

@jnm2

+1 for native support.

@pisqko

+1 for native support

@jpierson

When i try going the same route of creating a manual resolver it's not working me with latest version of SignalR and JSON.NET. The type JsonNetSerializer cannot be found amongst other things, have these types moved namespaces, assemblies, or been renamed?

@ryanwischkaemper

Using SignalR v2.2.0 and Autofac 3.5.2, if I use the code snippets above and register a binding with Autofac like this

var settings = new JsonSerializerSettings {ContractResolver = new SignalRContractResolver()};
var serializer = JsonSerializer.Create(settings);
builder.Register(c => serializer).As<JsonSerializer>();

then the camel case resolver is being used.

@larrifax larrifax referenced this issue in aspnet/SignalR-Server
Open

Customized JsonSerializer breaks SignalR #115

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.