UPDATE
Merci pour toutes les réponses. Je suis sur un nouveau projet et on dirait que j'ai enfin compris: il semble que le code suivant soit en fait à blâmer:
public static HttpResponseMessage GetHttpSuccessResponse(object response, HttpStatusCode code = HttpStatusCode.OK)
{
return new HttpResponseMessage()
{
StatusCode = code,
Content = response != null ? new JsonContent(response) : null
};
}
autre part...
public JsonContent(object obj)
{
var encoded = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore } );
_value = JObject.Parse(encoded);
Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
J'avais négligé l'innocent JsonContent en supposant que c'était WebAPI, mais non.
Ceci est utilisé partout ... Puis-je juste être le premier à dire, wtf? Ou peut-être que cela devrait être "Pourquoi font-ils cela?"
la question initiale suit
On aurait pu penser que ce serait un simple paramètre de configuration, mais cela m’échappe depuis trop longtemps.
J'ai examiné diverses solutions et réponses:
https://Gist.github.com/rdingwall/2012642
ne semble pas s'appliquer à la dernière version de WebAPI ...
Ce qui suit ne semble pas fonctionner - les noms de propriété sont toujours PascalCased.
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.UseDataContractJsonSerializer = true;
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
La réponse de Mayank ici: sous-objets CamelCase JSON WebAPI (objets imbriqués, objets enfants) semblait être une réponse peu satisfaisante mais pratique jusqu'à ce que je sache que ces attributs devraient être ajoutés au code généré car nous utilisons linq2sql. ..
Tout moyen de le faire automatiquement? Ce "méchant" me tourmente depuis longtemps maintenant.
En réunissant tout cela, vous obtenez ...
protected void Application_Start()
{
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
}
C'est ce qui a fonctionné pour moi:
internal static class ViewHelpers
{
public static JsonSerializerSettings CamelCase
{
get
{
return new JsonSerializerSettings {
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
}
}
}
Puis:
[HttpGet]
[Route("api/campaign/list")]
public IHttpActionResult ListExistingCampaigns()
{
var domainResults = _campaignService.ListExistingCampaigns();
return Json(domainResults, ViewHelpers.CamelCase);
}
La classe CamelCasePropertyNamesContractResolver
provient de la bibliothèque Newtonsoft.Json.dll
in Json.NET .
Il se trouve que
return Json(result);
était à l'origine du processus de sérialisation et ignorait le paramètre camelcase. Et cela
return Request.CreateResponse(HttpStatusCode.OK, result, Request.GetConfiguration());
était le droïde que je cherchais.
Aussi
json.UseDataContractJsonSerializer = true;
Était en train de mettre une clé dans les travaux et s'est avéré être pas le droïde que je cherchais.
Toutes les réponses ci-dessus n'ont pas fonctionné pour moi avec Owin Hosting et Ninject. Voici ce qui a fonctionné pour moi:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
// Get the ninject kernel from our IoC.
var kernel = IoC.GetKernel();
var config = new HttpConfiguration();
// More config settings and OWIN middleware goes here.
// Configure camel case json results.
ConfigureCamelCase(config);
// Use ninject middleware.
app.UseNinjectMiddleware(() => kernel);
// Use ninject web api.
app.UseNinjectWebApi(config);
}
/// <summary>
/// Configure all JSON responses to have camel case property names.
/// </summary>
private void ConfigureCamelCase(HttpConfiguration config)
{
var jsonFormatter = config.Formatters.JsonFormatter;
// This next line is not required for it to work, but here for completeness - ignore data contracts.
jsonFormatter.UseDataContractJsonSerializer = false;
var settings = jsonFormatter.SerializerSettings;
#if DEBUG
// Pretty json for developers.
settings.Formatting = Formatting.Indented;
#else
settings.Formatting = Formatting.None;
#endif
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
}
La principale différence est la suivante: new HttpConfiguration () plutôt que GlobalConfiguration.Configuration.
Code de WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//This line sets json serializer's ContractResolver to CamelCasePropertyNamesContractResolver,
// so API will return json using camel case
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
}
Assurez-vous que votre méthode d’action API renvoie les données de la manière suivante et que vous avez installé la dernière version de Json.Net/Newtonsoft.Json. Installé:
[HttpGet]
public HttpResponseMessage List()
{
try
{
var result = /*write code to fetch your result*/;
return Request.CreateResponse(HttpStatusCode.OK, cruises);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
Dans votre startup Owin, ajoutez cette ligne ...
public class Startup
{
public void Configuration(IAppBuilder app)
{
var webApiConfiguration = ConfigureWebApi();
app.UseWebApi(webApiConfiguration);
}
private HttpConfiguration ConfigureWebApi()
{
var config = new HttpConfiguration();
// ADD THIS LINE HERE AND DONE
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.MapHttpAttributeRoutes();
return config;
}
}
En voici une obscure: lorsque la valeur de l'attribut route ne correspond pas à celle de l'URL GET mais que celle-ci correspond au nom de la méthode, la directive relative à la casse des chameaux de jsonserializer est ignorée, par exemple.
//uppercase fail cakes
[HttpGet]
[Route("countries")]
public async Task<GeoData> GeoData()
{
return await geoService.GetGeoData();
}
//lowercase nomnomnom cakes
[HttpGet]
[Route("geodata")]
public async Task<GeoData> GeoData()
{
return await geoService.GetGeoData();
}
Je l'ai résolu de la manière suivante.
[AllowAnonymous]
[HttpGet()]
public HttpResponseMessage GetAllItems(int moduleId)
{
HttpConfiguration config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
try
{
List<ItemInfo> itemList = GetItemsFromDatabase(moduleId);
return Request.CreateResponse(HttpStatusCode.OK, itemList, config);
}
catch (System.Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
J'utilise WebAPI avec Breeze et je courais le même problème lorsque vous essayez d'exécuter une action non-brise dans un contrôleur de jeu d'enfant. J'ai essayé d'utiliser le Request Request.GetConfiguration apprach mais le même résultat. Donc, quand j'accéder à l'objet retourné par Request.GetConfiguration Je me rends compte que le sérialiseur utilisé par demande est celle que l'utilisation brise-serveur pour le faire est magique. Quoi qu'il en soit, j'ai résolu mon problème en créant une configuration HttpConfiguration différente:
public static HttpConfiguration BreezeControllerCamelCase
{
get
{
var config = new HttpConfiguration();
var jsonSerializerSettings = config.Formatters.JsonFormatter.SerializerSettings;
jsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
return config;
}
}
et en le passant comme paramètre à Request.CreateResponse comme suit:
return this.Request.CreateResponse(HttpStatusCode.OK, result, WebApiHelper.BreezeControllerCamelCase);