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 1932 posts 6722 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 1932 posts 6722 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.

  • 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