Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Rasmus Fjord 657 posts 1542 karma points c-trib
    Jul 30, 2019 @ 19:58
    Rasmus Fjord
    2

    Serializing an PublishedContentModel(modelsbuilder model) in V8

    Hello there :)

    Hoping to make a thread that a lot of people will get something out of, the overall goal of the thread is to be able to take a modelsbuilder model(underlying being a PublishedContentModel) and get it out as JSON. This was possible in V7 with some tinkering, but lets try and see how far we can get shall we?

    So I have an object which comes from a modelsbuilder Model, so it inherits from PublishedContentModel, lets call it obj. Normally we could just put a model in to JSON.net and say give me JSON like:

    @JsonConvert.SerializeObject(obj)
    

    But both in V7 and V8 this gives you something like :

    Self referencing loop detected for property....
    

    But in V7 we could build a JSON.NET ContractResolver, where we could filter out the params it shouldn't serialize, and in this way make it into a serilizable model.

    This class could look like this:

         public class PublishedContentContractResolver : DefaultContractResolver
       {
           public new static readonly PublishedContentContractResolver Instance = new PublishedContentContractResolver();
            protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
            {
                JsonProperty property = base.CreateProperty(member, memberSerialization);
    
                property.ShouldSerialize = instance =>
                {
    
                    if (property.PropertyName == "CompositionAliases") return false;
                    if (property.PropertyName == "ContentSet") return false;
                    if (property.PropertyName == "PropertyTypes") return false;
                    if (property.PropertyName == "ObjectContent") return false;
                    if (property.PropertyName == "Properties") return false;
                    if (property.PropertyName == "Parent") return false;
                    if (property.PropertyName == "Children") return false;
                    if (property.PropertyName == "DocumentTypeId") return false;
                    if (property.PropertyName == "WriterName") return false;
                    if (property.PropertyName == "CreatorName") return false;
                    if (property.PropertyName == "WriterId") return false;
                    if (property.PropertyName == "CreatorId") return false;
                    if (property.PropertyName == "CreateDate") return false;
                    if (property.PropertyName == "UpdateDate") return false;
                    if (property.PropertyName == "Version") return false;
                    if (property.PropertyName == "SortOrder") return false;
                    if (property.PropertyName == "TemplateId") return false;
                    if (property.PropertyName == "IsDraft") return false;
                    if (property.PropertyName == "ItemType") return false;
                    if (property.PropertyName == "ContentType") return false;
                    if (property.PropertyName == "Url") return false;
                    if (property.PropertyName == "ContentSet") return false;
    
    //making people on the other end of my api happy 
                    property.PropertyName = StringUtils.ToCamelCase(property.PropertyName);
    
                    return true;
                };
    
                return property;
            }
            protected override JsonContract CreateContract(Type objectType)
            {
                JsonContract contract = base.CreateContract(objectType);
    
                return contract;
            }
        }
    

    Now we could go do something like this to use our brand new ContractResolver:

        @{
      PublishedContentContractResolver contractResolver = new PublishedContentContractResolver();
        var settings = new JsonSerializerSettings();
        settings.ContractResolver = contractResolver;
    
    
    }
    <pre>
    @JsonConvert.SerializeObject(l, Formatting.Indented, settings)
    </pre>
    

    This would work in V7, job done, but in V8 something new is brewing, we get another YSOD, this time it saying the following:

        panic: invalid item type
    [Exception: panic: invalid item type]
       Umbraco.Web.PublishedCache.NuCache.PublishedContent.GetGetterById() in d:\a\1\s\src\Umbraco.Web\PublishedCache\NuCache\PublishedContent.cs:122
       Umbraco.Web.PublishedCache.NuCache.<get_ChildrenForAllCultures>d__57.MoveNext() +55
       Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs:677
       Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs:469
       Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs:469
       Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs:95
       Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) in /_/Src/Newtonsoft.Json/JsonSerializer.cs:1151
       Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer) in /_/Src/Newtonsoft.Json/JsonConvert.cs:664
       Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings) in /_/Src/Newtonsoft.Json/JsonConvert.cs:629
       ASP._Page_Views_Testarea_cshtml.Execute() in Web\Views\Testarea.cshtml:21
       System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +252
       System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +148
       System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +107
       Umbraco.Web.Mvc.ProfilingView.Render(ViewContext viewContext, TextWriter writer) in d:\a\1\s\src\Umbraco.Web\Mvc\ProfilingView.cs:25
       System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +378
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +91
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +793
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +793
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +793
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +81
       System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__1(IAsyncResult asyncResult) +188
       System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
       System.Web.Mvc.<>c.<BeginExecuteCore>b__152_1(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
       System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +73
       System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52
       System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +39
       System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
       System.Web.Mvc.<>c.<BeginProcessRequest>b__20_1(IAsyncResult asyncResult, ProcessRequestState innerState) +43
       System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +73
       System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
       System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +651
       System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +220
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +134
    

    So any people who have got a work around, an idea why or just a pointer? it says something about NuCache so don't know if Stephan has an idea or any other?

  • Marc Goodson 1285 posts 8696 karma points MVP 5x c-trib
    Jul 30, 2019 @ 22:56
    Marc Goodson
    102

    I may be misunderstanding the question but isn't there a new ChildrenForAllCultures property on IPublishedContent? and are you excluding that from serialization?

    https://github.com/umbraco/Umbraco-CMS/blob/3bfd9b71e290354744d677440983ecd06c5c0788/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs#L164

  • Rasmus Fjord 657 posts 1542 karma points c-trib
    Jul 31, 2019 @ 07:43
    Rasmus Fjord
    3

    Hey Marc!

    Thx for helping, ive just added it to the exclution and now it works!

    THANK YOU :)

    So for everyone needing a JSON serilization solution use thg following ContractResolver and go through the steps in my first post!

    public class PublishedContentContractResolver : DefaultContractResolver
    

    { public new static readonly PublishedContentContractResolver Instance = new PublishedContentContractResolver(); protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization);

            property.ShouldSerialize = instance =>
            {
    
                if (property.PropertyName == "CompositionAliases") return false;
                if (property.PropertyName == "ContentSet") return false;
                 if (property.PropertyName == "PropertyTypes") return false;
                if (property.PropertyName == "ObjectContent") return false;
                if (property.PropertyName == "Properties") return false;
                if (property.PropertyName == "Parent") return false;
                if (property.PropertyName == "Children") return false;
                if (property.PropertyName == "ChildrenForAllCultures") return false;
                if (property.PropertyName == "DocumentTypeId") return false;
                if (property.PropertyName == "WriterName") return false;
                if (property.PropertyName == "CreatorName") return false;
                if (property.PropertyName == "WriterId") return false;
                if (property.PropertyName == "CreatorId") return false;
                if (property.PropertyName == "CreateDate") return false;
                if (property.PropertyName == "UpdateDate") return false;
                if (property.PropertyName == "Version") return false;
                if (property.PropertyName == "SortOrder") return false;
                if (property.PropertyName == "TemplateId") return false;
                if (property.PropertyName == "IsDraft") return false;
                if (property.PropertyName == "ItemType") return false;
                if (property.PropertyName == "ContentType") return false;
                if (property.PropertyName == "Url") return false;
                if (property.PropertyName == "ContentSet") return false;
    
    
    
                //making people on the other end of my api happy 
                property.PropertyName = StringUtils.ToCamelCase(property.PropertyName);
    
                return true;
            };
    
            return property;
        }
        protected override JsonContract CreateContract(Type objectType)
        {
            JsonContract contract = base.CreateContract(objectType);
    
            return contract;
        }
    }
    
  • vcd 3 posts 72 karma points
    Feb 15, 2020 @ 23:19
    vcd
    0

    Hi, I tried this first on Umbraco 7, and it worked perfectly (with the additional handling of the rich text editor, as described here https://our.umbraco.com/forum/using-umbraco-and-getting-started/100395-how-do-i-convert-rich-text-editor-doctype-properties-to-json-in-umbraco-8), but on Umbraco 8.2.2 - no properties are being serialized, I only get the key, Name, Id, level, path etc. properties. Did anyone else encounter this?

  • vcd 3 posts 72 karma points
    Feb 27, 2020 @ 23:50
    vcd
    0

    Just to close this, the problem wasn't with the serialization at all, but an umbraco error due to some types defined incorrectly ('element type' doc types had a non element type parent), which prevented umbraco from creating any models. The presence (if all's well, it shouldn't be there) and content of the file models.err in the App_Data\Models folder was the clue...

Please Sign in or register to post replies

Write your reply to:

Draft