.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


Ответы:


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 ...).


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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.