1

i want to change the incoming requests deserializing format just for one of my controllers. so i added this in to my Global.asax and it works just fine:

HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } }; 

but it apply the changes to all of the controllers. i just want apply it for one of my controllers. i also found this answer and i wrote this code according to that:

public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) { var formatter = controllerSettings.Formatters.OfType<JsonMediaTypeFormatter>().Single(); controllerSettings.Formatters.Remove(formatter); formatter = new JsonMediaTypeFormatter { SerializerSettings = { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } } }; controllerSettings.Formatters.Add(formatter); } 

but unfortunately it works just for serializing the outputs. is there a way to define it for deserializing inputs?

1 Answer 1

4

You can do what you need with a tricky media type formatter. Usually custom formatter overrides methods CanReadType() / CanWriteType() and ReadFromStreamAsync() / WriteToStreamAsync(). CanWriteType() in your case should always return false since you are not intersted in customizing serialization. As regards deserialization you could use standard JsonMediaTypeFormatter (through inheritance or aggregation) and set its SerializerSettings to use SnakeCaseNamingStrategy:

public class SnakeCaseJsonFormatter : JsonMediaTypeFormatter { public SnakeCaseJsonFormatter() { SerializerSettings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } }; } public override bool CanWriteType(Type type) { return false; } public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) { throw new NotImplementedException(); } } 

Remaining part is applying of such custom formatter on controller level. You could do this with a custom attribute implementing IControllerConfiguration interface. In Initialize() method set your custom formatter at first position so that it takes precedence over standard JsonMediaTypeFormatter. You should not remove standard JsonMediaTypeFormatter because it will handle data serializing:

public sealed class SnakeCaseNamingAttribute : Attribute, IControllerConfiguration { public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) { controllerSettings.Formatters.Insert(0, new SnakeCaseJsonFormatter()); } } 

Now just apply this attribute on controller you want and voila:

[SnakeCaseNaming] public class ValuesController : ApiController 
Sign up to request clarification or add additional context in comments.

11 Comments

Thank you so much dear @CodeFuller. i did exactly what you posted but it didn't worked!! did you test the code? i guess we miss something.
Yes, I've checked and it works for me. What exactly does not work now? Have you removed customization of SerializerSettings in other places you tried?
SnakeCaseNamingStrategy doesn't apply to my inputs. i didn't remove ant thing. i just created a two classes (SnakeCaseJsonFormatter and SnakeCaseNamingAttribute) and apply the attribute on my controller. i can post my code but i guess its so obvious.
when i add SnakeCaseNamingStrategy in my global class it changes the properties name to snake case. for example FirstName become first-name. but when i add your attribute on controller. it didn't change anything.
Try setting breakpoints in SnakeCaseNamingAttribute.Initialize() and SnakeCaseJsonFormatter constructor. Are they called?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.