【问题标题】:Serialise entire Page tree to JSON in EpiServer在 EpiServer 中将整个页面树序列化为 JSON
【发布时间】:2016-07-14 14:25:19
【问题描述】:

我对 EpiServer 完全陌生,这已经让我死了好几天:(

我正在寻找一种将页面及其所有后代转换为 JSON 树的简单方法。

我已经走到这一步了:

public class MyPageController : PageController<MyPage>
{
    public string Index(MyPage currentPage)
    {
        var output = new ExpandoObject();
        var outputDict = output as IDictionary<string, object>;

        var pageRouteHelper = ServiceLocator.Current.GetInstance<EPiServer.Web.Routing.PageRouteHelper>();
        var pageReference = pageRouteHelper.PageLink;

        var children = DataFactory.Instance.GetChildren(pageReference);
        var toOutput = new { };
        foreach (PageData page in children)
        {
            outputDict[page.PageName] = GetAllContentProperties(page, new Dictionary<string, object>());
        }
        return outputDict.ToJson();
    }

    public Dictionary<string, object> GetAllContentProperties(IContentData content, Dictionary<string, object> result)
    {
        foreach (var prop in content.Property)
        {
            if (prop.IsMetaData) continue;

            if (prop.GetType().IsGenericType &&
                prop.GetType().GetGenericTypeDefinition() == typeof(PropertyBlock<>))
            {
                var newStruct = new Dictionary<string, object>();
                result.Add(prop.Name, newStruct);
                GetAllContentProperties((IContentData)prop, newStruct);
                continue;
            }
            if (prop.Value != null)
                result.Add(prop.Name, prop.Value.ToString());
        }

        return result;
    }
}

问题是,通过将页面结构转换为Dictionaries,我的页面中的JsonProperty PropertyName注解丢失了:

[ContentType(DisplayName = "MySubPage", GroupName = "MNRB", GUID = "dfa8fae6-c35d-4d42-b170-cae3489b9096", Description = "A sub page.")]
public class MySubPage : PageData
{
    [Display(Order = 1, Name = "Prop 1")]
    [CultureSpecific]
    [JsonProperty(PropertyName = "value-1")]
    public virtual string Prop1 { get; set; }

    [Display(Order = 2, Name = "Prop 2")]
    [CultureSpecific]
    [JsonProperty(PropertyName = "value-2")]
    public virtual string Prop2 { get; set; }
}

这意味着我得到这样的 JSON:

{
    "MyPage": {
        "MySubPage": {
            "prop1": "...",
            "prop2": "..."
        }
    }
}

而不是这个:

{
    "MyPage": {
        "MySubPage": {
            "value-1": "...",
            "value-2": "..."
        }
    }
}

我知道使用自定义 ContractResolvers 进行 JSON 序列化,但这对我没有帮助,因为我需要无法从 C# 属性名称推断的 JSON 属性名称。

我还希望能够为页面本身设置自定义 JSON 属性名称。

我真的希望友好的 EpiServer 大师可以在这里帮助我!

提前致谢:)

【问题讨论】:

  • 您能否更新您的问题以包括 ToJson 实现,我提出的一个建议是将 Dictionary&lt;string, object&gt; 更改为 Dictionary&lt;string, MySubPage&gt;
  • 我只是在 Index 方法的末尾使用outputDict.ToJson();。关于您的建议,我想我可以这样做:var newStruct = new Dictionary&lt;string, prop.GetType()&gt;(); 我不确定这会有所帮助吗?
  • 更新:我现在正在试用 JOS.Content.Json。希望这会有所帮助。如果是这样,我将发布我的解决方案。 github.com/joseftw/JOS.ContentJson

标签: c# json episerver


【解决方案1】:

我项目中的一位 C# 开发人员最终为此推出了自己的解决方案。他使用反射来检查页面树并从中构建 JSON。这里是。希望它能像对我一样帮助别人!

using EPiServer;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.ServiceLocation;
using EPiServer.Web.Mvc;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;
using System;
using System.Runtime.Caching;
using System.Linq;
using Newtonsoft.Json.Linq;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;

namespace NUON.Models.MyCorp
{
    public class MyCorpPageController : PageController<MyCorpPage>
    {
        public string Index(MyCorpPage currentPage)
        {
            Response.ContentType = "text/json";

            // check if the JSON is cached - if so, return it
            ObjectCache cache = MemoryCache.Default;
            string cachedJSON = cache["myCorpPageJson"] as string;
            if (cachedJSON != null)
            {
                return cachedJSON;
            }

            var output = new ExpandoObject();
            var outputDict = output as IDictionary<string, object>;

            var pageRouteHelper = ServiceLocator.Current.GetInstance<EPiServer.Web.Routing.PageRouteHelper>();
            var pageReference = pageRouteHelper.PageLink;

            var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
            var children = contentLoader.GetChildren<PageData>(currentPage.PageLink).OfType<PageData>();
            var toOutput = new { };

            var jsonResultObject = new JObject();

            foreach (PageData page in children)
            {
                // Name = e.g. BbpbannerProxy . So remove "Proxy" and add the namespace
                var classType = Type.GetType("NUON.Models.MyCorp." + page.GetType().Name.Replace("Proxy", string.Empty));
                // Only keep the properties from this class, not the inherited properties
                jsonResultObject.Add(page.PageName, GetJsonObjectFromType(classType, page));
            }

            // add to cache
            CacheItemPolicy policy = new CacheItemPolicy();
            // expire the cache daily although it will be cleared whenever content changes.
            policy.AbsoluteExpiration = DateTimeOffset.Now.AddDays(1.0);
            cache.Set("myCorpPageJson", jsonResultObject.ToString(), policy);

            return jsonResultObject.ToString();
        }

        [InitializableModule]
        [ModuleDependency(typeof(EPiServer.Web.InitializationModule),
                  typeof(EPiServer.Web.InitializationModule))]
        public class EventsInitialization : IInitializableModule
        {
            public void Initialize(InitializationEngine context)
            {
                var events = ServiceLocator.Current.GetInstance<IContentEvents>();
                events.PublishedContent += PublishedContent;
            }

            public void Preload(string[] parameters)
            {
            }

            public void Uninitialize(InitializationEngine context)
            {
            }

            private void PublishedContent(object sender, ContentEventArgs e)
            {
                // Clear the cache because some content has been updated
                ObjectCache cache = MemoryCache.Default;
                cache.Remove("myCorpPageJson");
            }
        }

        private static JObject GetJsonObjectFromType(Type classType, object obj)
        {
            var jsonObject = new JObject();
            var properties = classType.GetProperties(BindingFlags.Public
                | BindingFlags.Instance
                | BindingFlags.DeclaredOnly);

            foreach (var property in properties)
            {
                var jsonAttribute = property.GetCustomAttributes(true).FirstOrDefault(a => a is JsonPropertyAttribute);
                var propertyName = jsonAttribute == null ? property.Name : ((JsonPropertyAttribute)jsonAttribute).PropertyName;

                if (property.PropertyType.BaseType == typeof(BlockData))
                    jsonObject.Add(propertyName, GetJsonObjectFromType(property.PropertyType, property.GetValue(obj)));
                else
                {
                    var propertyValue = property.PropertyType == typeof(XhtmlString) ? property.GetValue(obj)?.ToString() : property.GetValue(obj);
                    if (property.PropertyType == typeof(string))
                    {
                        propertyValue = propertyValue ?? String.Empty;
                    }
                    jsonObject.Add(new JProperty(propertyName, propertyValue));
                }
            }
            return jsonObject;
        }
    }

    [ContentType(DisplayName = "MyCorpPage", GroupName = "MyCorp", GUID = "bc91ed7f-d0bf-4281-922d-1c5246cab137", Description = "The main MyCorp page")]
    public class MyCorpPage : PageData
    {
    }
}

【讨论】:

    【解决方案2】:

    您好,我正在寻找同样的东西,直到现在我才找到这个页面和组件。 https://josefottosson.se/episerver-contentdata-to-json/

    https://github.com/joseftw/JOS.ContentJson

    希望对你有用

    【讨论】:

    • 谢谢,但正如上面的 cmets 中提到的,我已经尝试过了。最后,我们的一个 C# 开发人员推出了一个使用反射构建一个可以很好地序列化的对象的本土解决方案。我会在下面发布。
    猜你喜欢
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 2020-11-01
    • 1970-01-01
    • 2011-08-14
    相关资源
    最近更新 更多