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 675 posts 1566 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 2157 posts 14434 karma points MVP 9x 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 675 posts 1566 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...

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies