I extend the Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver and apply the new resolver in my WebApi:
public static void Register(HttpConfiguration config)
{
var json = config.Formatters.JsonFormatter.SerializerSettings;
json.ContractResolver = new CustomPropertyNamesContractResolver();
json.Formatting = Formatting.Indented;
config.MapHttpAttributeRoutes();
}
and here is the overridden method of my custom name resolver (CustomPropertyNamesContractResolver class):
protected override string ResolvePropertyName(string propertyName)
{
if (propertyName.Equals("ID"))
return "id";
// return the camelCase
propertyName = base.ResolvePropertyName(propertyName);
if (propertyName.EndsWith("ID"))
propertyName = propertyName.Substring(0, propertyName.Length - 1) + "d";
return propertyName;
}
My issue is that the results are indeed in camel case but properties like "QuestionID", are never converted to "questionId" - what I keep on receiving is "questionID".
Plus, my custom ResolvePropertyName() method is never called (tested it with breakpoints), so it seems that only the ResolvePropertyName() method of my parent class (CamelCasePropertyNamesContractResolver) is called somehow.
Now, when I inherit directly from DefaultContractResolver (which is the parent of CamelCasePropertyNamesContractResolver) my custom ResolvePropertyName() method is called.
Can someone explain me what happens here? Am I missing something?
ResolvePropertyName()
is no longer called by CamelCasePropertyNamesContractResolver
. This is documented in Issue #950: Breaking change in 9.0.1 for custom contract resolvers? which was resolved by JamesNK as follows:
JamesNK commented on Jul 4, 2016
Yes that will now break. That method [ResolvePropertyName] is never called because of changes in how CamelCasePropertyNamesContractResolver works.
What you could do is inherit from CamelCaseNamingStrategy and do something similar, then assign that to DefaultContractResolver. Note that you should cache the contract resolver on a static variable so it isn't recreated all the time.
Following the advice there you should inherit from CamelCaseNamingStrategy
like so:
public class CustomNamingStrategy : CamelCaseNamingStrategy
{
protected override string ResolvePropertyName(string propertyName)
{
if (propertyName.Equals("ID"))
return "id";
// return the camelCase
propertyName = base.ResolvePropertyName(propertyName);
if (propertyName.EndsWith("ID"))
propertyName = propertyName.Substring(0, propertyName.Length - 1) + "d";
return propertyName;
}
}
Then set it on DefaultContractResolver.NamingStrategy
like so:
json.ContractResolver = new DefaultContractResolver { NamingStrategy = new CustomNamingStrategy() };
Or, since I believe ASP.NET Web API uses its own contract resolver JsonContractResolver
, you might want to modify the NamingStrategy
of the existing config.Formatters.JsonFormatter.SerializerSettings.ContractResolver
, assuming a resolver has been allocated already in settings:
var resolver = json.ContractResolver as DefaultContractResolver ?? new DefaultContractResolver();
resolver.NamingStrategy = new CustomNamingStrategy();
json.ContractResolver = resolver;
(Note - I haven't tested using the pre-existing resolver myself.)