Вернуть CamelCased JSON из Web API
Я пытаюсь вернуть JSON с верблюдом из контроллера ASP.Net Web API 2. Я создал новое веб-приложение только с битами ASP.Net MVC и Web API. Я захватил ValuesController следующим образом:
public class ValuesController : ApiController
{
public class Thing
{
public int Id { get; set; }
public string FirstName { get; set; }
public string ISBN { get; set; }
public DateTime ReleaseDate { get; set; }
public string[] Tags { get; set; }
}
// GET api/values
public IHttpActionResult Get()
{
var thing = new Thing
{
Id = 123,
FirstName = "Brian",
ISBN = "ABC213",
ReleaseDate = DateTime.Now,
Tags = new string[] { "A", "B", "C", "D"}
};
return Json(thing);
}
}
Запустив это в IE, я получаю следующие результаты:
{"Id":123,"FirstName":"Brian","ISBN":"ABC213","ReleaseDate":"2014-10-20T16:26:33.6810554-04:00","Tags":["A","B","C","D"]}
Следуя K. Скотт Аллен по этому вопросу, я добавил следующее в метод Register в файле WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Однако я все равно получаю то же самое, капиляция в моих результатах. Есть что-то, что мне не хватает? Я пробовал несколько других подходов, но пока ничего не работает.
Ответы
Ответ 1
Похоже, основная проблема заключалась в том, что я использовал метод результата Json() для JsonResult:
public IHttpActionResult Get([FromUri] string domain, [FromUri] string username)
{
var authInfo = BLL.GetAuthenticationInfo(domain, username);
return Json(authInfo);
}
По-видимому, он полностью контролировал форматирование результатов. Если я переключусь на возвращаемый HttpResponseMessage, он будет работать как ожидалось:
public HttpResponseMessage Get([FromUri] string domain, [FromUri] string username)
{
var authInfo = BLL.GetAuthenticationInfo(domain, username);
return Request.CreateResponse(HttpStatusCode.OK, authInfo);
}
В конце концов я использовал блок кода в файле WebApiConfig, как предположил Омар Алани (против более длинного кода, который у меня был в моем OP). Но настоящим виновником был метод JsonResult. Надеюсь, это поможет кому-то другому.
Ответ 2
В вашем WebApiConfig.cs обязательно добавьте эти две строки
// Serialize with camelCase formatter for JSON.
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
убедитесь, что вы установили библиотеку Newtonsoft.
Надеюсь, что это поможет.
Ответ 3
Вам нужно использовать OK()
вместо Json()
в ваших методах действий.
// GET api/values
public IHttpActionResult Get()
{
var thing = new Thing
{
Id = 123,
FirstName = "Brian",
ISBN = "ABC213",
ReleaseDate = DateTime.Now,
Tags = new string[] { "A", "B", "C", "D"}
};
// Use 'Ok()' instead of 'Json()'
return Ok(thing);
}
Ответ 4
Я использовал Owin и DI (AutoFac в моем случае), чтобы выталкивать еще один ключ в работу. Мой Startup.cs содержит:
var apiconfig = new HttpConfiguration
{
DependencyResolver = new AutofacWebApiDependencyResolver(container)
};
WebApiConfig.Register(apiconfig);
Затем в моем WebApiConfig.cs у меня есть:
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
// Setup json.Net for pretty output, easy human reading AND this formatter
// does that ONLY for browsers - best of both worlds: useful AND efficient/performant!
config.Formatters.Clear();
config.Formatters.Add(new BrowserJsonFormatter());
}
public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
// Since most browser defaults do not include an "accept type" specifying json, this provides a work around
// Default to json over XML - any app that wants XML can ask specifically for it ;)
public BrowserJsonFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
SerializerSettings.Formatting = Formatting.Indented;
SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Convert all dates to UTC
SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
}
// Change the return type to json, as most browsers will format correctly with type as text/html
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
Ответ 5
В методе регистрации WebApiConfig добавьте это
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = новый CamelCasePropertyNamesContractResolver();
Полный код 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 }
);
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
}
Убедитесь, что установлена последняя версия Json.Net/Newtonsoft.Json Installed, и ваш метод действий API возвращает данные следующим образом:
[HttpGet]
public HttpResponseMessage List()
{
try
{
var result = /*write code to fetch your result*/;
return Request.CreateResponse(HttpStatusCode.OK, result);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
Ответ 6
Попробуйте также.
[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);
}
}