Copied to clipboard

Flag this post as spam?

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


  • Morten Peter Hagh Jensen 25 posts 85 karma points
    May 24, 2021 @ 07:00
    Morten Peter Hagh Jensen
    0

    Return nested content items as JSON with controller

    I am trying to learn controllers and have searched a ton without finding a solution to my problem.

    I have some meeting dates and times created as nested content in nested content.

    The meeting dates being a nested content and the meeting times being nested content inside meeting dates giving a structure like this

    > date (24-05-2021) 
    >> 10:30
    >> 12:30
    >> 13:30
    
    > date (25-05-2021) 
    >> 11:30
    >> 14:30
    >> 15:30
    

    What I am trying to achieve is to create an endpoint with a Umbraco controller to get the times for a specific date chosen on a calendar on the front end.

    So if I f.x. select 25-05-2021 in the calendar, the click event should make a call to /umbraco/api/meetingdates/getdates/ with the date 25-05-2021 as the ID to select the content in Umbraco, like ?date=25-05-2021

    and return something like

    {
        date: "25-05-2021",
        times: [{
            "11:30",
            "14:30",
            "15:30"
        }]
    }
    

    The date item has the alias MeetingDateItemDay and the time item has meetingdateTimeItem with the overall property containing the items aliased meetingDatesAvailable

  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    May 24, 2021 @ 07:21
    Huw Reddick
    0

    Hi,

    Don't know if this will help at all, but this is something I wrote to export the metadata from pages.

    public JsonResult ExportMetaData()
    {
        int count = 0;
        List<string> pages = new List<string>();
        IPublishedContent homePage = Umbraco.Content(Guid.Parse("a53c075a-61a2-456e-a73d-e65e52efea92"));
        var pageNotes = homePage.Children;
        CountNodes(homePage.Children,ref pages, ref count);
    
        JsonResult ret = Json("{\"Synchronised\":[" + string.Join(",", pages.ToArray()) + "]}");
    
        return ret;
    }
    
    private void CountNodes(IEnumerable<IPublishedContent> children, ref List<string> pages, ref int count)
    {
        count += children.Count();
        foreach (IPublishedContent item in children)
        {
            if(item.Children != null)
            {
                var test = (PublishedContentModel)item;
                if (test.GetProperty("metaName") != null)
                {
                    pages.Add("{\"Id\":\"" + test.Id + "\",\"Name\":\"" + test.Name + "\",\"metaName\":\"" + test.GetProperty("metaName").GetValue().ToString() + "\",\"Description\":\"" + test.GetProperty("metaDescription").GetValue().ToString() +"\"}");
                }
    
                CountNodes(item.Children, ref pages, ref count);
            }
        }
    }
    
  • Morten Peter Hagh Jensen 25 posts 85 karma points
    May 24, 2021 @ 07:45
    Morten Peter Hagh Jensen
    0

    Just making a 1:1 copy of your code, which I would try to edit gives me

    cannot implicitly convert type system.web.http.results.jsonresult to system.web.mvc.jsonresult
    
  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    May 24, 2021 @ 08:17
    Huw Reddick
    0

    Change the signature of the method from jsonresult to actionresult, that should mix it :)

  • Morten Peter Hagh Jensen 25 posts 85 karma points
    May 24, 2021 @ 08:28
    Morten Peter Hagh Jensen
    0

    That unfortunately didn't do the trick :-(

    I have pasted my code here

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Umbraco.Web.WebApi;
    using System.Web.Http;
    using HttpGet = System.Web.Http.HttpGetAttribute;
    using Umbraco.Web;
    using System.Web.Http.Results;
    using Umbraco.Core.Models.PublishedContent;
    
    namespace test_inspection_website.umbraco.Controllers
    {
        public class MeetingDatesController : UmbracoApiController
        {
            // GET: MeetingDates
            public ActionResult ExportMetaData()
            {
                int count = 0;
                List<string> pages = new List<string>();
                IPublishedContent homePage = Umbraco.Content(Guid.Parse("a53c075a-61a2-456e-a73d-e65e52efea92"));
                var pageNotes = homePage.Children;
                CountNodes(homePage.Children, ref pages, ref count);
    
                JsonResult ret = Json("{\"Synchronised\":[" + string.Join(",", pages.ToArray()) + "]}");
    
                return ret;
            }
    
            private void CountNodes(IEnumerable<IPublishedContent> children, ref List<string> pages, ref int count)
            {
                count += children.Count();
                foreach (IPublishedContent item in children)
                {
                    if (item.Children != null)
                    {
                        var test = (PublishedContentModel)item;
                        if (test.GetProperty("metaName") != null)
                        {
                            pages.Add("{\"Id\":\"" + test.Id + "\",\"Name\":\"" + test.Name + "\",\"metaName\":\"" + test.GetProperty("metaName").GetValue().ToString() + "\",\"Description\":\"" + test.GetProperty("metaDescription").GetValue().ToString() + "\"}");
                        }
    
                        CountNodes(item.Children, ref pages, ref count);
                    }
                }
            }
        }   
    }
    
  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    May 24, 2021 @ 08:32
    Huw Reddick
    0

    Does that give the same error?

  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    May 24, 2021 @ 08:33
    Huw Reddick
    0

    Ah, I see you are using an API controller, mine is in a surface controller so that explains the arror :)

  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    May 24, 2021 @ 10:12
    Huw Reddick
    100

    With an Api controller, you should just return a normal c# object or list, it will get returned either as xml or json depending on the request, so you can do something similar to below

    private List<Markers> GetLocations()
    {
        List<Markers> locations = new List<Markers>();
        var filePath = HostingEnvironment.MapPath("~/App_Data");
        using (var streamReader = new StreamReader(Path.Combine(filePath, "MapMarkers.csv")))
        using (var reader = new CsvReader(streamReader))
        {
            // the CSV file has a header record, so we read that first
            reader.ReadHeaderRecord();
    
            while (reader.HasMoreRecords)
            {
                var dataRecord = reader.ReadDataRecord();
    
                var loc = new Markers()
                {
                    Name = dataRecord["title"],
                    Id = new Guid(dataRecord["id"]), //Convert.ToInt32(dataRecord["id"]),
                    Description = dataRecord["description"],
                    Address = dataRecord["address"],
                    Link = dataRecord["link"],
                    Categories = dataRecord["category"].Split(','),
                    Geolocation = new Geolocation() { Latitude = Convert.ToDouble(dataRecord["lat"]), Longitude = Convert.ToDouble(dataRecord["lng"]) }
                };
                locations.Add(loc);
            }
        }
    
        return locations;
    }
    

    Obviously this isn't reading umbraco data, but the List is returned as a json array of marker objects

  • Morten Peter Hagh Jensen 25 posts 85 karma points
    May 24, 2021 @ 13:46
    Morten Peter Hagh Jensen
    0

    Thanks a lot, @Huw Reddick - Your answer pointed me in the right direction.

    I have created this

    public class MeetingDatesController : UmbracoApiController
        {
            // GET: MeetingDates
            [HttpGet]
            public Object MeetingDates(String theDate)
            {
                IPublishedContent content = Umbraco.Content(Guid.Parse("ff3e93f6-b34f-4664-a08b-d2eae2a0adbd"));
                var meettypes = content.Value<IEnumerable<IPublishedElement>>("meetingDatesAvailable");
    
                var items = new List<object>();
    
                foreach(var item in meettypes)
                {
                    if (item.Value("meetingItemDay").ToString().Substring(0, 8) == theDate) {
                        var times = item.Value<IEnumerable<IPublishedElement>>("meetingItemDayTimes");
    
                        foreach (var time in times)
                        {
                            items.Add(time.Value("meetingdateTimeItem").ToString());
                        }
                    }
                }
    
                return new { dateChosen = theDate, meetingTimes = items };           
            }
        }
    }
    

    Which actually works.

    Calling it with /umbraco/api/meetingdates/MeetingDates/?theDate=26-05-20ยด give me a response with

    {
        "dateChosen": "26-05-20",
        "meetingTimes": [
            "12:30",
            "15:30",
            "10:30"
        ]
    }
    

    which is what I wanted. Calling a date without any times gives an empty meetingTimes: []

    The code above can without a doubt be better! Any suggestions are greatly appreciated!

  • 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