Возврат JsonResult из web api без его свойств
У меня есть API-интерфейс Web API, и оттуда я возвращаю объект как JSON из действия.
Я делаю это вот так:
public ActionResult GetAllNotificationSettings()
{
var result = new List<ListItems>();
// Filling the list with data here...
// Then I return the list
return new JsonResult { Data = result };
}
Но таким образом объект JsonResult, включая атрибут Data
сериализуется как JSON. Итак, мой последний JSON, возвращающийся действием, выглядит так:
{
"ContentEncoding": null,
"ContentType": null,
"Data": {
"ListItems": [
{
"ListId": 2,
"Name": "John Doe"
},
{
"ListId": 3,
"Name": "Jane Doe"
},
]
},
"JsonRequestBehavior": 1,
"MaxJsonLength": null,
"RecursionLimit": null
}
Я не могу сериализовать эту строку JSON, потому что объект JsonResult
добавил в нее все другие свойства. Меня интересует только ListItems
, больше ничего. Но это автоматически добавляются такие вещи, как: ContentType
, MaxJsonLength
и т.д....
Теперь это не сработает для меня из-за всех других свойств в строке JSON...
var myList = JsonConvert.DeserializeObject<List<ListItems>>(jsonString);
Есть ли способ отправить объект JSON из действия, чтобы он не добавил все свойства, которые мне не нужны?
Ответы
Ответ 1
Как кто-то, кто работал с ASP.NET API около 3 лет, я бы рекомендовал вместо этого вернуть HttpResponseMessage. Не используйте ActionResult или IEnumerable!
ActionResult плохо, потому что, как вы обнаружили.
Возврат IEnumerable <> является плохим, потому что вы можете продлить его позже и добавить некоторые заголовки и т.д.
Использование JsonResult является плохим, потому что вы должны разрешить продление вашей услуги и поддерживать другие форматы ответов, как и в случае в будущем; если вы серьезно хотите ограничить это, вы можете сделать это с помощью Action Attributes, а не в корпусе действия.
public HttpResponseMessage GetAllNotificationSettings()
{
var result = new List<ListItems>();
// Filling the list with data here...
// Then I return the list
return Request.CreateResponse(HttpStatusCode.OK, result);
}
В моих тестах я обычно использую вспомогательный метод ниже для извлечения моих объектов из HttpResponseMessage:
public class ResponseResultExtractor
{
public T Extract<T>(HttpResponseMessage response)
{
return response.Content.ReadAsAsync<T>().Result;
}
}
var actual = ResponseResultExtractor.Extract<List<ListItems>>(response);
Таким образом, вы достигли следующего:
- Ваше действие также может возвращать сообщения об ошибках и коды состояния, такие как 404, которые не найдены, поэтому вы можете с легкостью справиться с этим.
- Ваше действие не ограничивается только JSON, но поддерживает JSON в зависимости от предпочтения запроса клиента и настроек в Formatter.
Посмотрите на это: http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation
Ответ 2
При использовании WebAPI вы должны просто вернуть объект, а не просто возвращать Json, поскольку API либо вернет JSON, либо XML в зависимости от запроса.
Я не уверен, почему ваш WebAPI возвращает ActionResult, но я бы изменил код на что-то вроде:
public IEnumerable<ListItems> GetAllNotificationSettings()
{
var result = new List<ListItems>();
// Filling the list with data here...
// Then I return the list
return result;
}
Это приведет к JSON, если вы вызываете его из какого-либо кода AJAX.
PS WebAPI должен быть RESTful, поэтому ваш контроллер должен быть вызван ListItemController
и ваш метод следует просто называть Get
. Но это на другой день.
Ответ 3
У меня была аналогичная проблема (различия в том, что я хотел вернуть объект, который уже был преобразован в строку json, и мой контроллер получает IHttpActionResult)
Вот как я это решил. Сначала я объявил класс полезности
public class RawJsonActionResult : IHttpActionResult
{
private readonly string _jsonString;
public RawJsonActionResult(string jsonString)
{
_jsonString = jsonString;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var content = new StringContent(_jsonString);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = content };
return Task.FromResult(response);
}
}
Затем этот класс можно использовать в вашем контроллере. Вот простой пример
public IHttpActionResult Get()
{
var jsonString = "{\"id\":1,\"name\":\"a small object\" }";
return new RawJsonActionResult(jsonString);
}
Ответ 4
return JsonConvert.SerializeObject(images.ToList(), Formatting.None, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.None, ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
using Newtonsoft.Json;