Возврат 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;