简体   繁体   English

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

[英]Serialise entire Page tree to JSON in EpiServer

I am completely new to EpiServer and this has been killing me for days :( 我对EpiServer完全陌生,这已经使我丧命了几天:(

I am looking for a simple way to convert a page and all it's descendents to a JSON tree. 我正在寻找一种简单的方法来将页面及其所有后代转换为JSON树。

I have got this far: 我已经做到了这一点:

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;
    }
}

The problem is, by converting the page structure to Dictionaries, the JsonProperty PropertyName annotations in my pages are lost: 问题是,通过将页面结构转换为Dictionary,我页面中的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; }
}

This means I get JSON like this: 这意味着我得到这样的JSON:

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

Instead of this: 代替这个:

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

I know about using custom ContractResolvers for the JSON serialisation, but that will not help me because I need JSON property names that cannot be inferred from the C# property name. 我知道使用自定义ContractResolvers进行JSON序列化,但这对我无济于事,因为我需要无法从C#属性名推断出的JSON属性名。

I would also like to be able to set custom JSON property names for the pages themselves. 我还希望能够为页面本身设置自定义JSON属性名称。

I really hope that a friendly EpiServer guru can help me out here! 我真的希望友好的EpiServer专家可以在这里为我提供帮助!

Thanks in advance :) 提前致谢 :)

One of the C# dev's on my project rolled his own solution for this in the end. 最后,我项目中的一位C#开发人员为此推出了自己的解决方案。 He used reflection to examine the page tree and built the JSON up from that. 他使用反射来检查页面树,并以此为基础构建JSON。 Here it is. 这里是。 Hopefully it will help someone else as much as it did me! 希望它能像我一样帮助别人!

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
    {
    }
}

Hi I'm looking for the same thing, and until now I find this page and component. 嗨,我正在寻找相同的东西,直到现在,我仍然找到此页面和组件。 https://josefottosson.se/episerver-contentdata-to-json/ https://josefottosson.se/episerver-contentdata-to-json/

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

I hope you find it useful 希望对你有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM