33

I have LoginModel:

public class LoginModel : IData
{
    public string Email { get; set; }
    public string Password { get; set; }
}

and I have the Web api method

public IHttpActionResult Login([FromBody] LoginModel model)
{
    return this.Ok(model);
}

And it's return 200 and body:

{
    Email: "dfdf",
    Password: "dsfsdf"
}

But I want to get with lower first letter in property like

{
    email: "dfdf",
    password: "dsfsdf"
}

And I have Json contract resolver for correcting

public class FirstLowerContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        if (string.IsNullOrWhiteSpace(propertyName))
            return string.Empty;

        return $"{char.ToLower(propertyName[0])}{propertyName.Substring(1)}";
    }
}

How I can apply this?

ekad
  • 14,436
  • 26
  • 44
  • 46
MihailPw
  • 509
  • 2
  • 9
  • 16

4 Answers4

40

If your are using Newtonsoft.Json, you can add JsonProperties to your view model :

public class LoginModel : IData
{
     [JsonProperty(PropertyName = "email")]
     public string Email {get;set;}

     [JsonProperty(PropertyName = "password")]
     public string Password {get;set;}
}
AdrienTorris
  • 9,111
  • 9
  • 34
  • 52
21

To force all json data returned from api to camel case it's easier to use Newtonsoft Json with the default camel case contract resolver.

Create a class like this one:

using Newtonsoft.Json.Serialization;

internal class JsonContentNegotiator : IContentNegotiator
{
    private readonly JsonMediaTypeFormatter _jsonFormatter;

    public JsonContentNegotiator(JsonMediaTypeFormatter formatter)
    {
        _jsonFormatter = formatter;          
        _jsonFormatter.SerializerSettings.ContractResolver =
            new CamelCasePropertyNamesContractResolver();
    }

    public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
    {
        return new ContentNegotiationResult(_jsonFormatter, new MediaTypeHeaderValue("application/json"));
    }
}

and set this during api configuration (at startup):

var jsonFormatter = new JsonMediaTypeFormatter();
httpConfiguration.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
Luca Ghersi
  • 3,261
  • 18
  • 32
  • This works very well even with Entity Framework in a WebAPI project. Just place the startup code provided here in the `WebApiConfig` class (replace `httpConfiguration` with `config`). – SiZiOUS Apr 25 '18 at 13:00
  • 1
    There is only one issue, all the json fields, also the ones not related to the viewmodel, are going to be lower cased. The other issue is that it does not work with nested properties/objects ie: myTopKey.MySubKey --should be---> myTopKey.mySubKey – Carlo Luther Sep 06 '18 at 16:07
13

You can add the two following statement in the configuration of the web API or to the startup file

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;

But it is very important to use the return Ok() method instead of return Json() otherwise; this will not work.

if you have to use Json method (and have no other choice) then see this answer https://stackoverflow.com/a/28960505/4390133

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
6

If you need it only in some certain place and not throughout whole application, then you can do following:

var objectToSerialize = new {Property1 = "value1", SubOjbect = new { SubObjectId = 1 }};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(data, new JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() });

It should result in {"property1":"value1","subOjbect":{"subObjectId":1}} (note that nested properties also start from lowercase)

Grengas
  • 836
  • 12
  • 16