Copied to clipboard

Flag this post as spam?

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


  • Kris Janssen 210 posts 569 karma points c-trib
    Jun 22, 2014 @ 12:07
    Kris Janssen
    0

    @PartialViewMacropage and page protection status

    Hello all,

    I wanted to make a simple page navigation macro that, instead of only taking into account "Visible" would also look at whether or not a member has access to a page (and leave out unaccessible pages from the nag bar).

    There are lots of examples in this respect:

    1. The now defunct DynamicNode had two methods
    2. There is a lot of confusion online, even on these forums where people seem to think that something like

      foreach (var page in CurrentPage.Children.Where("Visible && HasAccess") would work.

    However, that last bit of code will not work because, during runtime, page will resolve (is that the correct terminology?) to DynamicPublishedContent and Children will be a DynamicPublishedContentList and the string argument of Where() will be converted into a lambda expression by Umbraco.Web.Dynamics.ExpressionParser<T>.Parse(...) and this is the problem:

    DynamicPublishedContent has no definition for something like IsProtected() of HasAccess() so obviously they cannot be resolved by the above Where()...

    One has to resort to Umbraco.MemberHasAccess() and Umbraco.Isprotected() but as far as I know, you cannot use them in the Where() call because it cannot be parsed (or am I wrong?), as far as I can tell because arguments are needed for MemberHasAccess:

    .Where("Visible && Umbraco.MemberHasAccess(id, path)")
    

    Nonetheless, being able to not only filter visible pages but also accessible ones from a Where() would be very, very convenient in my opinion.

    Could anyone comment on this? I would really like to understand why MemberHasAccess was implemented in the way it was and put in UmbracoHelper instead of being an integral part of DynamicPublishedContent.

    Cheers,

    Kris

  • Lennart Stoop 304 posts 842 karma points
    Jun 22, 2014 @ 12:30
    Lennart Stoop
    0

    Hi Kris,

    I actually prefer the current implementation wherein web security is seperated from content. For partial actions you would also be using User.IsInRole() rather than IPublishedContent.HasAccess().

    The option to hide or show content in navigation ("Visible") is unrelated to security imo (and correctly so a property on content).

    And if that means writing an extra IF statement within a FOREACH.. I really don't mind :)

     

    Grtz

    L

  • Lennart Stoop 304 posts 842 karma points
    Jun 22, 2014 @ 13:01
    Lennart Stoop
    2

    PS: you could also use an extension method for filtering secured content

    Here's an example for strongly typed content:

        public static IEnumerable<IPublishedContent> AndHasAccess(this IEnumerable<IPublishedContent> content)
        {
            var helper = new UmbracoHelper(UmbracoContext.Current);
            foreach (var c in content)
            {
                if (helper.IsProtected(c.Id, c.Path) && helper.MemberHasAccess(c.Id, c.Path))
                    yield return c;
            }
        }
    

    Usage:

    CurrentPage.Children.Where("Visible").AndHasAccess()
    

    I'm sure you can do the same for dynamic types.

    Grtz

    L

  • Kris Janssen 210 posts 569 karma points c-trib
    Jun 22, 2014 @ 16:44
    Kris Janssen
    0

    Hi Lennart,

    I hadn' t looked at it in that way and I have to say it seems to make sense.

    Your proposed extension method also seems like an elegant solution...

    One more thing I currently do not fully grasp: would you have any idea why the Where on DynamicPublishedContent does not accept lambdas as arguments instead of strings needing parsing by ExpressionParser? Currently, my understanding of dynamics, lambdas and such does not reach much further than being able to use existing stuff so this might be a stupid question...

  • Lennart Stoop 304 posts 842 karma points
    Jun 22, 2014 @ 21:02
    Lennart Stoop
    0

    Hi Kris,

    That's a tough question. I don't really have much experience with dynamic types as in most of our projects we have full control over model and content and I really prefer strongly typed models because I'm a monkey without intellisense :)

    I do believe much of the confusion is caused by the quick pace at which dynamic types have changed over time (from Razor scripts in Umbraco 4.x to Umbraco 6 and 7) and the documentation still mentions the dynamic query parser has its merits when it comes to complex querying (i.e. lambdas)

    The best advice I can give is to code by example and poke around and to keep reporting issues when you're stuck.

  • Jeavon Leopold 3072 posts 13628 karma points MVP 10x admin c-trib
    Jun 23, 2014 @ 19:35
    Jeavon Leopold
    1

    @Lennart, what a great extension method, I will be adding that one to my collection!

    @Kris, you cannot use Lambda expressions with dynamics, that's why we have the Expression Parser instead. However if you want to do a Lambda you could either use a fully typed .Where or if you really want to you can used typed for your query and get it to return dynamic, here is how:

    @{
        var myCollection = Model.Content.Children.Where(x => x.IsVisible()).Select(x => x.AsDynamic());
        foreach (var page in myCollection)
        {
            <p>dynamic property title: @page.title</p>
        }
    }
    

    Jeavon

Please Sign in or register to post replies

Write your reply to:

Draft