.NET WebAPI Serialization k_BackingField Гадость

86

Когда я сериализую следующее:

[Serializable]
public class Error
{

    public string Status { get; set; }
    public string Message { get; set; }
    public string ErrorReferenceCode { get; set; }
    public List<FriendlyError> Errors { get; set; }
}

Получаю этот отвратительный беспорядок:

<ErrorRootOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance"   xmlns="http://schemas.datacontract.org/2004/07/Printmee.Api">
<_x003C_Errors_x003E_k__BackingField>
An exception has occurred. Please contact printmee support
</_x003C_Errors_x003E_k__BackingField>
<_x003C_LookupCode_x003E_k__BackingField>988232ec-6bc9-48f3-8116-7ff7c71302dd</_x003C_LookupCode_x003E_k__BackingField>
</ErrorRootOfstring>

Что дает? Как мне сделать это красивым? Ответы JSON также содержат k_BackingField

Мика
источник
Это помогло мне: stackoverflow.com/questions/15388452/…
granadaCoder

Ответы:

126

По умолчанию вам не нужно использовать ни , [Serializable]ни [DataContract]для работы с Web API.

Просто оставьте свою модель как есть, и веб-API сериализует все общедоступные свойства за вас.

Только если вы хотите иметь больший контроль над тем, что включено, вы затем украшаете свой класс [DataContract]и свойства, которые будут включены [DataMember](потому что и DCS, и JSON.NET соответствуют этим атрибутам).

Если по какой-то причине вам нужен [Serializable]ваш класс (например, вы по какой-то причине сериализуете его в поток памяти, выполняете глубокие копии и т. Д.), Тогда вы должны использовать оба атрибута вместе, чтобы предотвратить имена полей поддержки:

[Serializable]
[DataContract]
public class Error
{
    [DataMember]
    public string Status { get; set; }
    [DataMember]
    public string Message { get; set; }
    [DataMember]
    public string ErrorReferenceCode { get; set; }
    [DataMember]
    public List<FriendlyError> Errors { get; set; }
}
Филип В
источник
6
Вот и все - мне просто нужно было удалить [Serializable]. Спасибо.
Micah
Спасибо, Филип, атрибуты должны быть сохранены из-за кеширования ... Кстати, я заядлый фанат твоего блога ... продолжай!
Стивен Паттен
20
Это просто ужасно. Почему Microsoft НИКОГДА не может сделать ничего правильного, когда дело касается сериализации?
Крис Марисич
Существует более общее решение, как я показываю в моем собственном ответе ниже.
JotaBe
Возможно, проблема с сериализацией заключается в определении «правильного», данные нужны каждому по-своему.
Луис Фелипе,
94

Существует более общее решение: вы можете настроить сериализатор Json для игнорирования [Serializable]атрибута, чтобы вам не приходилось изменять атрибуты в своих классах.

Вы должны внести это изменение конфигурации при запуске приложения, то есть в Application_Startсобытии Global.asax :

var serializerSettings =
  GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver =
  (DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;

Вы также можете внести другие изменения в сериализацию Json, например указать форматы для сериализации дат и многое другое.

Это будет применяться только к сериализации JSON веб-API. Этот параметр не повлияет на другие сериализации в приложении (XML-сериализация веб-API, MVC JsonResult ...).

JotaBe
источник
4
Мне это решение нравится больше, чем добавление атрибутов [DataContract] и [DataMember] повсюду. Спасибо!!
Mark Good
1
Не то, что вы должны использовать все время, но это отличный трюк. Что-то вроде лома, который помогает обойти запутанные ситуации, когда у вас нет роскоши изменять модели или глубоко реорганизовывать кодовую базу.
uygar.raf 09
Вы правы, что это не лучший способ сделать это. Однако в некоторых случаях рефакторинг - это не только роскошь, но и вообще невыполнимая задача. Например, если кодовая база использует WCF или сериализацию XML, ей действительно требуются атрибуты контракта данных или сериализации XML. Вы не можете этого изменить. К счастью, JSON.NET очень мощный инструмент: он поддерживает контракт данных, сериализацию XML и свои собственные атрибуты, и вы можете контролировать, как он использует их для сериализации, или даже полностью игнорировать их. И вы даже можете добавить свою реализацию. Конечно, я предпочитаю вести чистые классы без атрибутов.
JotaBe
Так оно и должно работать по умолчанию! Почему мы не видим бессмыслицу в нашем сериализованном потоке?
Байрон Уитлок
1
Если вы используете веб-API и ориентируетесь на версию 4 инфраструктуры .net, вам необходимо обновить пакет Netwonsoft.Json, чтобы это работало, т Update-Package Newtonsoft.Json. Е.
pblack 01
0

Атрибуты [DataContract] у меня не работали, так что это не вариант.

XmlSerializer игнорирует [XmlAttribute] в WebApi

Приведенное выше решение решило эту проблему для меня.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
источник