在EpiServer中将整个页面树序列化为JSON

时间:2016-07-14 14:25:20

标签: c# json episerver

我是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大师可以帮助我在这里!

提前致谢:)

2 个答案:

答案 0 :(得分: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
    {
    }
}

答案 1 :(得分:0)

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

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

我希望你觉得它很有用