Пропустить [ScriptIgnore] только один раз

Среда для этой ситуации:

  • asp.net mvc 3
  • C#
  • Entity Framework 4.3.1
  • JavaScriptSerializer

    Я сталкивался с ситуацией, в которой было бы неплохо включить поле, помеченное как [ScriptIgnore], Поле, если оставить его без атрибута, будет представлять собой круговую ссылку и вызовет исключение. Причина в чем-то похожем на это:

    public class Foo
    {
     public int FooId { get; set; }
    
     [ScriptIgnore]
     public virtual Collection<Bar> Bars { get; set; }
    }
    
    public class Bar
    {
     public int BarId { get; set; }
     public int FooId { get; set; }
     public virtual Foo Foo { get; set; }
    }
    

    Таким образом, вы можете увидеть здесь, Foo может иметь много связанных Bars, И Bar имеет связанный Foo,

    Вернемся к ситуации. Я загружаю эту ассоциацию в контроллер, используя оператор включения:

    .Include( foo => foo.Bars );
    

    Там нет ошибок, потому что включить не влияет [ScriptIgnore] аннотаций. После отладки ассоциация правильно создается при проверке. Есть список foos и каждый foo имеет связанный список Bars,

    Теперь я хочу сериализовать этот построенный список. У меня есть модель представления, которая заполняется данными, это выглядит так:

    public class FooView
    {
     public List<Foo> Foos { get; set; }
    
     public string AsJson()
     {
      var serializer = new JavaScriptSerializer();
      return serializer.Serialize(this);
     }
    }
    

    Поэтому я передаю эту view model в представление и сериализую его:

    @model FooView
    <script type="text/javascript">
     var fooViewModel = @( Html.Raw( Model.AsJson() ) );
    </script>
    

    Никаких исключений не выдается, однако, сериализация правильно пропускает поле (Bars) отмечен [ScriptIgnore], на consol.log(fooViewModel) осмотр ясно, что существует массив Foo Однако нет связанного массива Bar в любом из Foos,

    Есть ли способ, которым я могу пропустить это [ScriptIgnore] пометить только один раз? Я понимаю, что если он пропускается каждый раз, то сериализатор будет сериализовать Foo, посмотреть и увидеть коллекцию типа Bar, сериализовать каждый Bar, заметить, что Bar имеет связанный Foo, сериализовать Foo, заметить, что Foo имеет коллекцию типа Bar...так далее. Я только хочу захватить коллекцию Bar первый раз. Есть ли способ сделать это? Я понимаю, что он будет пытаться сериализовать Foo из бара, но он будет пустым. Все это делается с энергичной загрузкой, и весь граф объектов уже построен.

  • 1 ответ

    Когда я столкнулся с этим, в итоге я заменил сериализатор на сериализатор Json.NET, который имеет настройки, в частности

    _jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    

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

    Информация для настроек: http://james.newtonking.com/projects/json/help/index.html?topic=html/SerializingJSON.htm и я использовал http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx для замены сериализатора, а затем я добавляю его по умолчанию в global.asax.cs.

    configuration.Formatters.Insert(0, new JsonNetFormatter(serializerSettings));
    

    Я понимаю, что это обходной путь (на самом деле не имеет отношения к scriptignore), однако у меня было так много циклических ссылок из предоставленной базы данных, что это казалось лучшим решением в то время.

    Другие вопросы по тегам