Можно ли вернуть SiteMap как JsonResult?

У меня на контроллере очень простое действие, которое пытается вернуть мой XmlSiteMap в виде JsonResult:

public ActionResult Index()
{
    var nodes = SiteMap.Provider.RootNode;
    return new JsonResult() 
        { Data = nodes, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}

Однако, когда я вызываю Action, создается исключение InvalidOperationException:

"A circular reference was detected while serializing an object of 
   type 'System.Web.SiteMapNode'."

Есть ли способ, чтобы Json сериализовал SiteMap, или действительно любой объект, у которого есть потомки того же типа?

3 ответа

Вот как это можно сделать с помощью Json.NET ( http://json.codeplex.com/). Обратите внимание на использование ReferenceLoopHandling.Ignore установка.

using Newtonsoft.Json;

public ActionResult Index() {
  JsonSerializerSettings jsSettings = new JsonSerializerSettings();
  jsSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

  var nodes = SiteMap.Provider.RootNode;
  return Content(JsonConvert.SerializeObject(
    new { Data = nodes }, Formatting.None, jsSettings));
}

Одна хитрость, которую вы можете использовать, когда сталкиваетесь с проблемой сериализации сложного класса в JsonResult, - это использовать LINQ и Select() проецировать значения в перечисление по анонимному типу, содержащему только те свойства, которые вам нужны из исходного сложного класса.

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

Также возможно реализовать свой собственный сериализатор json для этого случая и явно обрабатывать циклическую ссылку, но это, вероятно, не лучшее решение.

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