Copied to clipboard

Flag this post as spam?

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


  • jonok 258 posts 474 karma points
    Apr 20, 2019 @ 21:22
    jonok
    0

    Surface controller - accessing node content and properties

    I am creating a surface controller that needs to retrieve nodes from a nested content property, but I'm not sure of the correct way to access the property.

    I am trying to do something like this:

    var block = CurrentPage.Value<IEnumerable<IPublishedElement>>("blocks").Where("Visible").Skip(currentCount).Take(1);
    

    I have tried lots of variations but can't find any examples that work - any help would be greatly appreciated. Instead of using 'CurrentPage' I could load the current page node using an ID if that helps, but I'm not sure how to do that in a surface controller either. I have tried this:

    IPublishedContent content = Umbraco.Content(1234);
    

    but then I get the error "The type or namespace name 'IPublishedContent' could not be found".

  • Alex Skrypnyk 5239 posts 19096 karma points MVP 3x admin c-trib
    Apr 21, 2019 @ 08:46
    Alex Skrypnyk
    0

    Hi Jonok

    What Umbraco version are you using? Can you show all the code you have?

    Thanks,

    Alex

  • jonok 258 posts 474 karma points
    Apr 21, 2019 @ 21:05
    jonok
    0

    Hi Alex, I'm using version 8.0.1, here is the surface controller code. I've got lots of 'using' statements as I can't seem to use the 'IPublishedContent' type, and was trying a few things.

        using System;
        using System.Collections.Generic;
        using System.Web;
        using System.Web.Mvc;
        using System.Net;
        using Umbraco;
        using Umbraco.Core;
        using Umbraco.Core.Models;
        using Umbraco.Core.Services;
        using Umbraco.Web;
        using Umbraco.Web.Mvc;
        using Umbraco.Web.Models;
    
        namespace MyNamespace.Controllers
        {
            public class MoreBlocksController : Umbraco.Web.Mvc.SurfaceController
            {
                public ActionResult LoadMoreBlocks(int currentCount,  int moreCount)
                {
    
                    //get nested content property node from current page
                    var block = CurrentPage.Value<IEnumerable<IPublishedContent>>("blocks").Where("Visible").Skip(currentCount).Take(1);
    
                     //or try to get it from content?? doesn't work either
                    IPublishedContent content = Umbraco.Content(1234);
                    block = content.Value<IEnumerable<IPublishedContent>>("blocks").Where("Visible").Skip(currentCount).Take(1);
    
                    return PartialView("Blocks/Image List Block", block, new ViewDataDictionary(this.ViewData) {
                        { "blockCount", moreCount }
                    });
                }
            }
        }
    
  • Thomas Kassos 12 posts 124 karma points
    Apr 21, 2019 @ 23:37
    Thomas Kassos
    0

    Hi jonok, I saw you question and I made an example. I manage to get the property values from textstring in a nested content. I don't know how this will work with media/member/content pickers. Hope you can make a start from that.

    If someone has a better solution would be nice to share.

    using System.Web.Mvc;
    using Umbraco.Web.Mvc;
    
    namespace Umbraco_8_tests.Controllers
    {
        public class TestingController : SurfaceController
        {
            public const string PARTIAL_VIEW_FOLDER = "~/Views/Partials/";
    
        public ActionResult TestSurfaceController()
        {
            return PartialView(PARTIAL_VIEW_FOLDER + "_TestSurfaceController.cshtml");
        }
    
        [HttpPost]
        public ActionResult testingSC()
        {
            dynamic nestedContent = Umbraco.Content(CurrentPage.Id).GetProperty("nc").GetValue();
    
            foreach (var item in nestedContent)
            {
                System.Reflection.PropertyInfo pi = item.GetType().GetProperty("TextNC");
                string itemValue = (string)(pi.GetValue(item, null));
            }
            return View();
        }
    }
    }
    
  • jonok 258 posts 474 karma points
    Apr 22, 2019 @ 01:03
    jonok
    0

    Hi Thomas, Thanks for that, it's definitely helping me understand surface controllers - however I am trying to get an Umbraco node to pass to the PartialView as the model. I'm hoping there is some way to access Umbraco nodes (eg. IPublishedContent) in a surface controller?

  • Alex Skrypnyk 5239 posts 19096 karma points MVP 3x admin c-trib
    Apr 22, 2019 @ 09:32
    Alex Skrypnyk
    1

    Hi Thomas,

    First of all - do not use "dynamic" type. Everything is strongly typed now.

    This line not needed also -

    System.Reflection.PropertyInfo pi = item.GetType().GetProperty("TextNC");
    

    You can always know which type to expect from the property.

    Thanks,

    Alex

  • Thomas Kassos 12 posts 124 karma points
    Apr 22, 2019 @ 10:20
    Thomas Kassos
    0

    Hi Alex, I used dynamic because I had an issue with this

            var nestedContent = Umbraco.Content(CurrentPage.Id).Value<IEnumerable<IPublishedContent>>("nc");
    

    it was always null, any thoughts why?

    Cheers

  • Alex Skrypnyk 5239 posts 19096 karma points MVP 3x admin c-trib
    Apr 22, 2019 @ 11:22
    Alex Skrypnyk
    0

    Use this :

    var nestedContent = Umbraco.Content(Umbraco.AssignedContentItem.Id).Value<IEnumerable<IPublishedContent>>("nc");
    
  • Thomas Kassos 12 posts 124 karma points
    Apr 22, 2019 @ 11:31
    Thomas Kassos
    0

    Didn't work..

    enter image description here

    enter image description here

  • Alex Skrypnyk 5239 posts 19096 karma points MVP 3x admin c-trib
    Apr 22, 2019 @ 11:55
    Alex Skrypnyk
    0

    this one works for me:

        public ActionResult testingSC()
        {
            var nestedContent = Umbraco.Content(CurrentPage.Id).Value<IEnumerable<IPublishedContent>>("nc");
    
            foreach (var item in nestedContent)
            {
                string itemValue = item.Value<string>("TextNC");
            }
    
            return View();
        }
    
  • Thomas Kassos 12 posts 124 karma points
    Apr 22, 2019 @ 12:06
    Thomas Kassos
    0

    Didn't work either

    Its not that I will have an error from this:

      var nestedContent = Umbraco.Content(CurrentPage.Id).Value<IEnumerable<IPublishedContent>>("nc");
    

    or this:

    var nestedContent = Umbraco.Content(Umbraco.AssignedContentItem.Id).Value<IEnumerable<IPublishedContent>>("nc");
    

    the issue is that returns always null

    and those (wrong ways),return the 2 items I want to get. but as an object, no as IPublishedContent

    var nestedContentV2 = Umbraco.Content(CurrentPage.Id).Value("nc");
    
    var nestedContentV3 = Umbraco.Content(CurrentPage.Id).GetProperty("nc").GetValue();
    
  • Thomas Kassos 12 posts 124 karma points
    Apr 22, 2019 @ 02:40
    Thomas Kassos
    1

    If I understand right, you need a form to post to the controller the pageId so you can access any node no matter the page you are.

    Anyway generally speaking you can access the nodes as IPublishedContent on a Surface controller

    All those are working

            var homePage = Umbraco.Content(CurrentPage.Id);
    
            var textString = homePage.Value("text");
    
            var rte = homePage.Value("rte");
    
            var image = homePage.Value<IPublishedContent>("image").Url;
    

    I couldn't get this one to work

            var nestedContent= homePage.Value<IEnumerable<IPublishedContent>>("nestedContent");
    
  • Alex Skrypnyk 5239 posts 19096 karma points MVP 3x admin c-trib
    Apr 22, 2019 @ 21:07
    Alex Skrypnyk
    0

    Hi Thomas

    How many items are created in the nested content property? Are there many or just one?

    If your Nested Content property editor is configured in single item mode, then the value converter will automatically know this and return a single IPublishedElement entity rather than an IEnumerable

    Thanks,

    Alex

  • jonok 258 posts 474 karma points
    Apr 22, 2019 @ 23:51
    jonok
    0

    Hi Thomas, I can't get anything with IPublishedContent to work. I get the following error: "The type or namespace name 'IPublishedContent' could not be found".

    Do I need to declare anything at the top of the controller file to allow me to use IPublishedContent?

  • Thomas Kassos 12 posts 124 karma points
    Apr 22, 2019 @ 23:54
    Thomas Kassos
    101

    Hi Jonok, I had those, give it a try

    using System.Web.Mvc;
    using Umbraco.Web.Mvc;
    using Umbraco.Web;
    using Umbraco.Core.Models.PublishedContent;
    
  • jonok 258 posts 474 karma points
    Apr 23, 2019 @ 00:09
    jonok
    0

    Thanks Thomas - the Umbraco.Core.Models.PublishedContent was the one I was missing. So now when I try the following code:

    var page = Umbraco.Content(1174);
    var block = page.Value<IEnumerable<IPublishedElement>>("blocks").Take(1);
    

    ...I get this error " 'IEnumerable

    I can use this code inline within a view and it works fine, but I'm not sure why the Take(1) isn't possible in the surface controller?

  • Thomas Kassos 12 posts 124 karma points
    Apr 23, 2019 @ 00:15
    Thomas Kassos
    0

    Well probably its U8 issue.

    Your problem should be the same with mine, IEnumerable IPublishedElement doesn't work (take(1) shouldn't be a problem )

    I have use surface controllers in U7 many times and I had no issue.

    You can try George Phillipson solution for now.

  • Thomas Kassos 12 posts 124 karma points
    Apr 23, 2019 @ 00:20
    Thomas Kassos
    0

    Hi Alex, there are two items

    In this comment I made earlier you can see clearly the issue I described to you

    https://our.umbraco.com/forum/umbraco-8/96911-surface-controller-accessing-node-content-and-properties#comment-306308

    Cheers, Thomas

  • jonok 258 posts 474 karma points
    Apr 23, 2019 @ 02:34
    jonok
    1

    Hi Thomas, I can't believe it was this simple but I was missing the 'using System.Linq;' declaration at the top of my surface controller. So to fix my original issue, it turns out all I needed was these 2 lines:

    using Umbraco.Core.Models.PublishedContent;
    using System.Linq;
    

    Thanks for your help.

  • Alex Skrypnyk 5239 posts 19096 karma points MVP 3x admin c-trib
    Apr 23, 2019 @ 16:09
    Alex Skrypnyk
    0

    We are glad that it's solved.

  • George Phillipson 43 posts 147 karma points
    Apr 22, 2019 @ 09:59
    George Phillipson
    1

    I have been testing out V8 and here is an example of how I get the nested content to work.

    1) I'm using modelbuilder so in my view I have:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<Web.Model.Helper.Contact>
    

    2) I'm not sure whether you are posting the page to the SurfaceController or whether it's on pageload, if posting add the following to a hidden field.

    var id = Model.NestedTest.ToList();
    

    3) SufaceController

    public ActionResult NestedContent(IEnumerable<IPublishedElement> id)
            {
    
    var publishedElements = id.ToList();
                var components = publishedElements.ToList();
    
                    foreach (var data in components)
                    {
                        var testOuter = data.Value<HtmlString>("bodyText");
    
                        if (data.ContentType.Alias == "nestedThreeDoctype")
                        {
                            foreach (var item in data.Value<IEnumerable<IPublishedElement>>("nCThree"))
                            {
                                var testInner = item.Value<IHtmlString>("bodyText");
                            }
                        }
                    }
    
    
    
                return null;
            }
    

    enter image description here

    I have attached an image to show my backoffice layout, this is just me messing around with V8 but it should give you an idea of how to do what you want

    enter image description here

Please Sign in or register to post replies

Write your reply to:

Draft