Copied to clipboard

Flag this post as spam?

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


  • Thomas Beckert 193 posts 469 karma points
    Dec 22, 2020 @ 13:47
    Thomas Beckert
    1

    UmbracoAuthorizedApiController and return IPublishedContent

    Hi,

    I just write a very simple AuthorizedApiController - i simply wanted to return a node, but this seems to be a very hard challenge.

    Here is my code (concerning the second function "GetNewsletterAdminNode", the first function works fine!):

    using System;
    using System.Web.Http;
    using System.Web.Mvc;
    using Umbraco.Core.Models.PublishedContent;
    using Umbraco.Web;
    using Umbraco.Web.Mvc;
    using Umbraco.Web.WebApi;
    
    namespace umbGastroON.Controllers.RESTApi.Authorized
    {    
        [PluginController("GastroOn")]
        public class NodeNavigationController : UmbracoAuthorizedApiController
        {           
            [System.Web.Http.HttpGet]
            public int GetContentNodeByType(string contentType = "", int idCurrentNode = -1)
            {
                contentType = (contentType == "") ? System.Web.HttpContext.Current.Request.QueryString["contentType"] : contentType;
                idCurrentNode = (idCurrentNode == -1) ? Convert.ToInt32(System.Web.HttpContext.Current.Request.QueryString["idCurrentNode"]) : idCurrentNode;
    
                //var IStartNode = getKundeStartknoten(Convert.ToInt32(idCurrentNode));
                //var startNode = Umbraco.Content(IStartNode.Id);            
    
                IPublishedContent webpageNode = Helpers.Structure.GetHP4MeWebpageNode(Umbraco.Content(idCurrentNode));
                //UmbracoContext.Current.ContentCache.GetById
                var node = webpageNode.DescendantOfType(contentType);
    
                return node.Id;
            }
    
            [System.Web.Http.HttpGet]
            public IPublishedContent GetNewsletterAdminNode(int idCurrentNode)
            {                
                IPublishedContent nlNode = Helpers.Structure.GetHP4MeNewsletterNode(Umbraco.Content(idCurrentNode));
                return nlNode;
                //return Json(nlNode, JsonRequestBehavior.AllowGet);     
            }
        }
    }
    

    I already tried to change the return value to JSONResult. But then. I get an error in the line:

    return Json(nlNode, JsonRequestBehavior.AllowGet);
    

    AllowGet could not be cast to some Newtonsoft.Json Property.

    Any idea what's going an here?

    Umbraco version is the newest one.

    The error when I call the Controller is:

        <Error>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.</ExceptionMessage>
    <ExceptionType>System.InvalidOperationException</ExceptionType>
    <StackTrace/>
    <InnerException>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>Type 'Umbraco.Web.PublishedModels.NewsletterAdministration' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.</ExceptionMessage>
    <ExceptionType>System.Runtime.Serialization.InvalidDataContractException</ExceptionType>
    <StackTrace> at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContractSerializer.GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__22.MoveNext()</StackTrace>
    </InnerException>
    </Error>
    
  • Huw Reddick 1929 posts 6677 karma points MVP 2x c-trib
    Dec 22, 2020 @ 16:29
    Huw Reddick
    0

    what happens if you just return the node? i.e. return nlNode;

  • Thomas Beckert 193 posts 469 karma points
    Dec 22, 2020 @ 16:37
    Thomas Beckert
    0

    Exactly the same.

  • Malthe Petersen 68 posts 383 karma points c-trib
    Dec 23, 2020 @ 07:39
    Malthe Petersen
    100

    Hi Thomas.

    I don’t think you can serialize the IPublishedContent, it will throw you an exception due to recursiveness. Not sure why and not sure how to fix. Personally what I have done is to map the properties that I would need into a new model and then return that in my API controllers.

    So if I were you, I would do:

    1. Create a new class
    2. Create the properties you need: node Id, node name, seoTitle (document type property), etc. etc.
    3. In your controller, fetch the IPublishedContent as you do.
    4. New up a new instance of your new class
    5. Set the properties you need
    6. Return that class.

    Hope that can help you solve your problem.

    Regards

  • Huw Reddick 1929 posts 6677 karma points MVP 2x c-trib
    Dec 23, 2020 @ 06:48
    Huw Reddick
    0

    Must be related to your model, it works ok for me with a simple published content object

  • Thomas Beckert 193 posts 469 karma points
    Dec 23, 2020 @ 09:47
    Thomas Beckert
    0

    Hi, Malthe,

    I feared that this will be the only way. I hoped it would be just that simple to return an existing object. So I have to write some more code.

    Anyway, thank you for your time and ideas anyone.

Please Sign in or register to post replies

Write your reply to:

Draft