Как предотвратить сериализацию JSON в ASP.NET MVC?

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

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

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

Ответ 1

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

Ответ 2

Я обычно обнаружил, что для сложных объектов лучше всего сериализовать, создав временный объект 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);
    }
}

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

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