首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在EpiServer中将整个页面树序列化为JSON

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

Stack Overflow用户
提问于 2016-07-14 22:25:20
回答 2查看 635关注 0票数 0

我对EpiServer完全陌生,这让我苦恼了好几天:

我正在寻找一种简单的方法来转换一个页面和它的所有后代到一个JSON树。

我已经做到了这一点:

代码语言:javascript
运行
复制
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;
    }
}

问题是,通过将页面结构转换为字典,我的页面中的JsonProperty PropertyName注释会丢失:

代码语言:javascript
运行
复制
[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:

代码语言:javascript
运行
复制
{
    "MyPage": {
        "MySubPage": {
            "prop1": "...",
            "prop2": "..."
        }
    }
}

而不是这样:

代码语言:javascript
运行
复制
{
    "MyPage": {
        "MySubPage": {
            "value-1": "...",
            "value-2": "..."
        }
    }
}

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

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

我真的希望一位友好的EpiServer专家能帮我解决这个问题!

提前感谢:)

EN

回答 2

Stack Overflow用户

发布于 2016-07-30 15:49:31

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

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2016-07-29 06:59:53

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

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

我希望它对你有用

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38376842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档