Я использую веб-API MVC 4 и веб-формы asp.net 4.0 для создания остальных API. Работает отлично:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = somethings });
return httpResponseMessage;
}
Теперь мне нужно предотвратить сериализацию некоторых свойств. Я знаю, что могу использовать некоторые LINQ над списком и получать только нужные мне свойства, и в целом это хороший подход, но в данном сценарии something
объект слишком сложен, и мне нужен другой набор свойств в разных методах, поэтому проще отметить во время выполнения каждое свойство, которое следует игнорировать.
Есть ли способ сделать это?
c#
asp.net
asp.net-mvc
asp.net-web-api
user1330271
источник
источник
Ответы:
ASP.NET Web API использует
Json.Net
форматировщик по умолчанию, поэтому, если ваше приложение использует только JSON в качестве формата данных, вы можете[JsonIgnore]
игнорировать свойство для сериализации:Но этот способ не поддерживает формат XML. Таким образом, в случае, если ваше приложение должно поддерживать формат XML больше (или только поддерживать XML), вместо использования
Json.Net
вы должны использовать тот,[DataContract]
который поддерживает JSON и XML:Для большего понимания вы можете прочитать официальную статью .
источник
Согласно странице документации Web API JSON и XML Serialization в ASP.NET Web API, чтобы явно предотвратить сериализацию для свойства, которое можно использовать
[JsonIgnore]
для сериализатора Json или[IgnoreDataMember]
для сериализатора XML по умолчанию.Однако в тестировании я заметил, что это
[IgnoreDataMember]
предотвращает сериализацию для запросов XML и Json, поэтому я бы рекомендовал использовать это, а не украшать свойство с несколькими атрибутами.источник
[IgnoreDataMember]
, похоже, не работает с лени-загруженными объектами прокси EF 6 (виртуальные свойства).[DataContract]
и[DataMember]
сделать, однако.Вместо того, чтобы все по умолчанию сериализовать, вы можете воспользоваться подходом «opt-in». В этом случае сериализуются только те свойства, которые вы указали. Это делается с помощью
DataContractAttribute
иDataMemberAttribute
, найденного в пространстве имен System.Runtime.Serialization .DataContactAttribute
Применяются к классу, иDataMemberAttribute
применяются к каждому члену вы хотите сериализовать:Смею сказать, что это лучший подход, потому что он заставляет вас принимать четкие решения о том, что будет или не будет сделано через сериализацию. Это также позволяет вашим модельным классам жить в проекте самостоятельно, без зависимости от JSON.net, просто потому, что где-то еще вы сериализуете их с JSON.net.
источник
Это сработало для меня: создайте пользовательский обработчик контрактов, который имеет открытое свойство AllowList типа строкового массива. В своем действии измените это свойство в зависимости от того, что нужно вернуть.
1. создать пользовательский обработчик контракта:
2. использовать пользовательский обработчик контракта в действии
Этот подход позволил мне разрешить / запретить для конкретного запроса вместо изменения определения класса. И если вам не нужна сериализация XML, не забудьте отключить ее в вашем
App_Start\WebApiConfig.cs
или ваш API вернет заблокированные свойства, если клиент запрашивает xml вместо json.источник
Я покажу вам 2 способа достичь желаемого:
Первый способ: Украсьте свое поле атрибутом JsonProperty, чтобы пропустить сериализацию этого поля, если оно пустое.
Второй способ: если вы ведете переговоры с некоторыми сложными сценариями, вы можете использовать соглашение Web Api ("ShouldSerialize"), чтобы пропустить сериализацию этого поля в зависимости от некоторой конкретной логики.
WebApi использует JSON.Net и использует отражение для сериализации, поэтому при обнаружении (например) метода ShouldSerializeFieldX () поле с именем FieldX не будет сериализовано.
источник
Я опаздываю к игре, но анонимные объекты справятся с задачей:
источник
Попробуйте использовать
IgnoreDataMember
свойствоисточник
Почти так же, как ответ greatbear302, но я создаю ContractResolver для каждого запроса.
1) Создайте пользовательский ContractResolver
2) Использовать пользовательский обработчик контракта в действии
Редактировать:
Это не сработало, как ожидалось (изолят распознавателя для каждого запроса). Я буду использовать анонимные объекты.
источник
Возможно, вы сможете использовать AutoMapper и использовать
.Ignore()
сопоставление, а затем отправить сопоставленный объектисточник
Работает нормально, просто добавив: [IgnoreDataMember]
Поверх свойства p, например:
Это работает с ApiController. Код:
источник
По какой-то причине
[IgnoreDataMember]
у меня не всегда получается, а я иногда получаюStackOverflowException
(или подобное). Поэтому вместо этого (или в дополнение) я начал использовать шаблон, похожий на этот, когдаPOST
входил вObjects
мой API:Так что в основном я прохожу в
JObject
и преобразовываю его после того, как он был получен, к проблемам aviod, вызванным встроенным сериализатором, которые иногда вызывают бесконечный цикл при анализе объектов.Если кто-то знает причину того, что это в любом случае плохая идея, пожалуйста, дайте мне знать.
Возможно, стоит отметить, что это следующий код для свойства класса EntityFramework, которое вызывает проблему (если два класса ссылаются друг на друга):
источник