2009-08-12 6 views
17

При разработке приложения ASP.NET MVC я нахожу несколько мест, где мои действия JsonResult вызывают исключение «Круговая ссылка была обнаружена при сериализации объекта».Как предотвратить сериализацию JSON в ASP.NET MVC?

В настоящее время я удаляю ссылки, о которых идет речь, но в идеале я хотел бы просто пометить свойство таким образом, чтобы сериализатор JSON игнорировал его.

Может ли кто-нибудь предложить, как я могу это сделать?

+0

Какой сериализатор вы используете? –

+0

JsonResult - это мой тип возврата, поэтому я предполагаю, что сериализатор по умолчанию используется в классе контроллера ASP.NET MVC 1.0. – JMP

+0

Какой JavaScriptSerializer. – womp

ответ

28

[ScriptIgnore]должно работать на вас.

+2

Это должно работать, потому что JsonResult использует JavaScriptSerializer внутренне. – womp

+3

Примечание для других: вам может потребоваться добавить ссылку на сборку System.Web.Extensions, чтобы сделать ее доступной, по крайней мере, в .NET 4. – Jacob

+4

System.Web.Script.Serialization.ScriptIgnore –

13

я вообще нашел, что для сложных объектов его лучше просто сериализации, создавая временный «Inbetween» объект:

, например, для свидетельств я следующее. Я действительно делаю это в коде для моей страницы модели ASPX.

Это создает приятный объект JSON. Вы заметите, что я могу даже реорганизовать свою модель, и страница все равно будет работать. Это просто еще один слой абстракции между моделью данных и страницей. Я не думаю, что мой контроллер должен знать о JSON как можно больше, но ASPX «codebehind», безусловно, может.

/// <summary> 
/// Get JSON for testimonials 
/// </summary> 
public string TestimonialsJSON 
{ 
    get 
    { 
     return Model.Testimonials.Select(
      x => new 
      { 
       testimonial = x.TestimonialText, 
       name = x.name 
      } 
      ).ToJSON(); 
    } 
} 

В моей ASPX я просто сделать это в блоке:

var testimonials = <%= TestimonialsJSON %>; 

// oh and ToJSON() is an extension method 
public static class ObjectExtensions 
{ 
    public static string ToJSON(this Object obj) 
    { 
     return new JavaScriptSerializer().Serialize(obj); 
    } 
} 

Я готов к негативной реакции на это предложение ... принести его на ...

Я не получая доступа к данным, просто переформатируя модель для представления. Это логика «модели представления», а не логика «модель контроллера».

+2

+1. Сначала я хотел бы дать некоторую люфт «Я не хочу создавать несколько моделей», но вы упомянули «модель взгляда», которая начинает иметь для меня определенный смысл: вы создаете модели для бизнес-логики, почему бы не создавать модели для просмотра логика? Brilliant! Это не ответ на мою конкретную ситуацию, но вы стоите над головой. – JMP

+0

Я не хочу создавать несколько моделей! это самый простой способ сделать это без необходимости создания другого класса (здесь нет необходимости). модель должна быть данными и только данными, а не тем, как эти данные отображаются, и, хотя это не всегда практично, вы всегда должны сводить к минимуму связь между представлением и моделью, чтобы просматривать изменения в другой технологии или вам нужно предоставить несколько разных видов (ajax/flash/plain html) –

+0

Мне нравится этот подход в случае, когда вам может понадобиться несколько разных сериализаций JSON одной и той же базовой модели. –

2

Я бы посоветовал использовать JSON.NET. Он позволяет сериализовать циклические ссылки и предоставляет гораздо больше возможностей сериализации.

2

Что Саймон сказал. Добавьте немного AutoMapper действие, чтобы держать вес кода под контролем.

1

Самый чистый подход, который я нашел, - использовать комбинацию [DataContract] для класса и [DataMember] для свойств, которые вы хотите сериализовать. Атрибут DataContract указывает различным сериализаторам игнорировать любое свойство, не имеющее атрибут DataMember.

Существует два основных преимущества по сравнению с использованием ScriptIgnoreAttribute. Во-первых, он не имеет отношения к сборке System.Web.Extensions. Во-вторых, он работает с другими типами сериализации, а не только с JSON. Например, если вы используете новый веб-API в MVC 4, подход DataContract/DataMember будет работать с XML-сериализатором.

Рассмотрите сценарий, в котором ваши объекты хранятся в общей библиотеке и повторно используются в разных проектах - вам не нужна зависимость от System.Web.Extensions, и вы хотите свободно описывать правила сериализации - не поведение жесткого кода, характерное для JSON, XML и т. Д.

Смежные вопросы