Copied to clipboard

Flag this post as spam?

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


  • Hefin Jones 39 posts 161 karma points
    Jul 23, 2014 @ 13:51
    Hefin Jones
    1

    How do I use - TypedContentAtXpath / ContentAtXpath?

    Hello guys!

    I'm trying to use "ContentAtXpath" or "TypedContentAtXpath" to find the Homepage document type from the current page.  The site I have has two languages which is why I need to traverse up the tree to find the correct homepage for the current page / site.  However, I cannot get anywhere with these methods.  The only way I can get them to work is if I use:

    Umbraco.TypedContentAtXPath("//Homepage")

    But this obviously just gets the first "Homepage" it comes across from the "root", which is correct for one site, but not for the other language.  I have tried variations of:

    Umbraco.TypedContentAtXPath("ancestor-or-self::Homepage")
    Umbraco.TypedContentAtXPath("./ancestor-or-self::Homepage")
    Umbraco.TypedContentAtXPath("/ancestor-or-self::Homepage")

    None of which seem to work, so I guess my question is what is the correct syntax to achieve what I'm looking for?  Any help would be greatly appreciated!

    Cheers Guys :)

  • Sebastiaan Janssen 5053 posts 15507 karma points MVP admin hq
    Jul 23, 2014 @ 14:21
    Sebastiaan Janssen
    0

    To get the result you want, the easiest way would probably be: Model.Content.AncestorOrSelf(1).

    This will give you the typed content at level 1 of your current site (which I assume is where your homepage is).

  • Hefin Jones 39 posts 161 karma points
    Jul 23, 2014 @ 14:32
    Hefin Jones
    0

    Thanks for your reply Sebastiaan, 

    Probably should have explained a bit better that I'm trying to do this in a custom class, such as this:

    public static string ForgotYourPasswordPage
    {
    get
    {
    string url = "";
    var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);

    url = umbracoHelper.TypedContentAtXPath("//AccountForgottenPassword").FirstOrDefault().Url;

    return url;
    }
    }

    So in this instance I've got a document type of "AccountForgottenPassword" within the current site which I'm trying to find using "TypedContentAtXPath" - but need to traverse to the "Homepage" document type and then find "AccountForgottenPassword" document type - so that I end up with the correct language version of "AccountForgottenPassword" page.  

    So in this instance I assume using 

    Model.Content.AncestorOrSelf(1)

    isn't feasible, which is why I'm trying to utilise the UmbracoHelper .... However, feel free to correct me if I'm wrong!

    Hope this makes sense?

  • Lee 1130 posts 3088 karma points
    Jul 23, 2014 @ 14:34
    Lee
    0

    You can get ALL HomePage doctypes using this code

    var allHomeNodes = UmbracoContext.Current.ContentCache.GetByXPath("//HomePage");
    
  • Hefin Jones 39 posts 161 karma points
    Jul 23, 2014 @ 14:45
    Hefin Jones
    0

    Hi Lee, thanks for the reply - however I'm looking to find the "Homepage" of the current page / site, which is why I'm trying to use ancestor-or-self to go up the tree until I find a document type of "Homepage" - but can't get anywhere with it.  Site structure is as follows:

    -- Root
    ----  Homepage (en)
    ------  Page 1
    ------  Page 2
    ------  Page 3
    ------  Page 4
    ----  Homepage (cy) 
    ------  Page 1
    ------  Page 2
    ------  Page 3
    ------  Page 4

    So esentially what I'm trying to do for example: if I am viewing "Page 4" on either site, I need some Xpath to find the "Homepage" of that particular site.  But I can't get ContentAtXPath syntax correct to do it? 

  • Sebastiaan Janssen 5053 posts 15507 karma points MVP admin hq
    Jul 23, 2014 @ 14:53
    Sebastiaan Janssen
    0

    Your custom class has no idea though where it currently "lives" in the content tree. Are you in a SurfaceController?

    If so then something like this should work:

    var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
    var currentPage = umbracoHelper.TypedContent(UmbracoContext.Current.PageId.Value);
    var home = currentPage.AncestorOrSelf(1);
    

    I think this also works if you are in webforms and inherit from UmbracoUserControl instead of UserControl.

    If all else fails, try to send in the current page's id into your method and get TypedContent that way.

  • Hefin Jones 39 posts 161 karma points
    Jul 23, 2014 @ 14:59
    Hefin Jones
    0

    I appreciate what you're saying, and you are probably correct about the context.  

    However I have tried using TypedContentAtXPath and ContentAtXPath directly in my view, but I still can't get it to work correctly.

    So I guess, although I can find other methods of acheiving what I need, I'm still curious about what the actual XPath syntax "should" be if I was using TypedContentAtXPath or ContentAtXPath as all I can get to work is "//Homepage" - does ancestor-or-self work at all?

  • Sebastiaan Janssen 5053 posts 15507 karma points MVP admin hq
    Jul 23, 2014 @ 15:17
    Sebastiaan Janssen
    1

    Forget about XPath already :-) Also: I have NO idea how it works.

    Have you tried the above code? This works in your view, but please seperate your code from your view. :)

    var currentPage = Umbraco.TypedContent(UmbracoContext.Current.PageId.Value);
    var home = currentPage.AncestorOrSelf(1);
    
  • Sebastiaan Janssen 5053 posts 15507 karma points MVP admin hq
    Jul 23, 2014 @ 15:20
    Sebastiaan Janssen
    0

    Also, I'm trying to help you get things done in the context of where you're doing them. If your external class has NO idea what the current page is, then the TypedContentAtXPath methods will also have no idea, so any attempts to get to the homepage that way will be futile.

    So: If the code above works in your custom class THEN you can try to replace AncestorOrSelf(1) with TypedContentAtXPath and experiment if you must. But I honestly don't know the XPath syntax to use there.

  • Sebastiaan Janssen 5053 posts 15507 karma points MVP admin hq
    Jul 23, 2014 @ 15:36
    Sebastiaan Janssen
    0

    Okay, so this was bugging me:

    I've looked into the TypedContentAtXPath method and it has no concept of "currentPage", so it will never work the way you want it to work. You will only be able to query the complete content cache (umbraco.config basically) with that method.

  • Hefin Jones 39 posts 161 karma points
    Jul 23, 2014 @ 15:38
    Hefin Jones
    0

    Ha ha ha! Ok .... My custom class is basically a helper class where I can retrieve URL's for various pages across the site, so for insntace to get the URL for my "Forgotten Password" page I've written this:

    /// <summary>
    /// URL for the Forgot your password page
    /// </summary>
    public static string ForgotYourPasswordPage
    {
    get
    {
    string url = "#";
    var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
    var currentPage = umbracoHelper.TypedContent(Umbraco.Web.UmbracoContext.Current.PageId);

    if (currentPage != null)
    {
    url = currentPage.AncestorOrSelf("Homepage").Descendant("AccountForgottenPassword") != null ? currentPage.AncestorOrSelf("Homepage").Descendant("AccountForgottenPassword").Url : "#";
    }

    return url;
    }
    }

    So in my view I have something like this:

    <a href="@URLHelper.PageURLs.ForgotYourPasswordPage" class="btn btn-default">Forgotten Your Password?</a>

    Seems to work ok for me :)

  • Sebastiaan Janssen 5053 posts 15507 karma points MVP admin hq
    Jul 23, 2014 @ 15:51
    Sebastiaan Janssen
    1

    Looks good. A word of warning: you're querying the content twice there, I would refactor to:

    var url = "#";
    var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
    var currentPage = umbracoHelper.TypedContent(Umbraco.Web.UmbracoContext.Current.PageId);
    
    if (currentPage != null)
    {
        var forgottenPasswordPage = currentPage.AncestorOrSelf(1).Children(x => x.DocumentTypeAlias == "AccountForgottenPassword").FirstOrDefault();
    
        if(forgottenPasswordPage != null)
            url = forgottenPasswordPage.Url;
    }
    
    return url;
    

    Another reason why I insist on using 1 to indicate the level is that you can then at some point change the homepage document type alias with no fear. I'm also no fan of hardcoding the doctype of the page you're looking for but.. oh well.

    I would only look in Children (if you plan to have this page directly under your homepage) in order to make the query faster, only use Descendants if you have no other choice.

    And finally, I use a Linq query for readability of the code. If anybody else picks up this code they can at least see at a glance that your looking for a doctype alias.

    Anyway, do with this as you please, just a few tips.

  • Hefin Jones 39 posts 161 karma points
    Jul 23, 2014 @ 15:59
    Hefin Jones
    0

    Awesome, thanks for your help .... very much appreciated and thanks for the tips too :)

Please Sign in or register to post replies

Write your reply to:

Draft