Managing menulist

Vote:
 

Hello fellow developers! :)

I'm trying to mange the Menulist and accessrights. I know that the Menulist by default doesn't return menuitems that the user doesn't have access to, but I want to show it and make it disabled. The purpose is that the customer should be able to see all titles and buy what ever titles that is interesting.

I therefore want to control the menuitem and make it disabled, but at long as the menulist doesn't show items the user have no access to, I have a problem.

Do I use RestrictAccess on Menuitem to control this??

Kind regards,

Jon Haakon

#56450
Jan 20, 2012 16:58
Vote:
 

If I understand you correctly you want to display the items the user does not have access to in a particular way? You can change the access level filtering by setting the RequiredAccess property on the MenuList. After that you need to find out which ones the user does not have access to and add a particular HTML class to that item to style it differently.

Frederik

#56455
Jan 20, 2012 22:40
Vote:
 

Thanks a lot Fredrik. You understood me correct. However there is still a problem regarding submenus.

I'm using nested Menulist to have the functionality of RequiredAccess for submenus as well. But then I get AccessDeniedException.

I wrapped the code behind functionality in a try catch block, but then I got a new exception on Menulist.visable=true;

I've read on your blog http://www.frederikvig.com/2009/08/episerver-web-controls-menulist-and-pagetree/

that it's customary to use the pagetree as submenu, but can't see that Pagetree have RequiredAccess functionality.

#56475
Jan 23, 2012 13:33
Vote:
 

Yep, it has the RequiredAccess property as well :).

 

Frederik

#56477
Jan 23, 2012 13:56
Vote:
 

Thanks! I changed from Menulist to Pagetree, but I still get access denied  when databinding to the top menu.

<EPiServer:PageTree ID="pagetree1" runat="server" Visible="True" RequiredAccess="NoAccess"  EnableViewState="True" EnableVisibleInMenu="True">
    <HeaderTemplate>
        <ul id="nav" class="clearfix">
            <li class="<%#(CurrentPage.PageLink.ID == EPiServer.Core.PageReference.StartPage.ID) ? "active" : "" %>">
                <EPiServer:Property ID="Property3" runat="server" PropertyName="PageLink" PageLink='<%#EPiServer.Core.PageReference.StartPage %>' />
            </li>
    </HeaderTemplate>
    <ItemTemplate>
        <li class="<%#SecurityHelper.HasAccess(Container.CurrentPage) ? "" : "unavailable" %>">
            <EPiServer:Property ID="Property1" runat="server" PropertyName="PageLink" /> 
            <EPiServer:PageTree ID="pagetree2" runat="server" PageLink='<%#Container.CurrentPage.PageLink %>' RequiredAccess="NoAccess">
                <HeaderTemplate>
                    <ul>
                </HeaderTemplate>
                <SelectedItemTemplate>
                    <li class="active">
                        <EPiServer:Property ID="Property3" runat="server" PropertyName="PageLink" />
                    </li>
                </SelectedItemTemplate>
                <ItemTemplate>
                    <li class="<%#SecurityHelper.HasAccess(Container.CurrentPage) ? "" : "unavailable" %>">
                        <EPiServer:Property ID="Property1" runat="server" PropertyName="PageLink" />
                    </li>
                </ItemTemplate>
                <FooterTemplate>
                    </ul></FooterTemplate>
            </EPiServer:PageTree>
        </li>
    </ItemTemplate>
    <SelectedExpandedTopTemplate>
        <li class="active">
            <EPiServer:Property ID="Property3" runat="server" PropertyName="PageLink" />
            <EPiServer:PageTree ID="pagetree3" runat="server" PageLink='<%#Container.CurrentPage.PageLink %>' RequiredAccess="NoAccess">
                <HeaderTemplate>
                    <ul>
                </HeaderTemplate>
                <SelectedItemTemplate>
                    <li class="active">
                        <EPiServer:Property ID="Property3" runat="server" PropertyName="PageLink" />
                    </li>
                </SelectedItemTemplate>
                <ItemTemplate>
                    <li class="<%#SecurityHelper.HasAccess(Container.CurrentPage) ? "" : "unavailable" %>">
                        <EPiServer:Property ID="Property1" runat="server" PropertyName="PageLink" />
                    </li>
                </ItemTemplate>
                <FooterTemplate>
                    </ul></FooterTemplate>
            </EPiServer:PageTree>
        </li>
    </SelectedExpandedTopTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</EPiServer:PageTree>
                    pagetree1.Visible = true;
                    pagetree1.PageLink = EPiServer.Core.PageReference.StartPage;
                    pagetree1.DataBind();

#56478
Jan 23, 2012 14:15
Vote:
 

I changed the top level control to Pagetree as well, but that didn't help either.

SDK says that the top level should be Menulist and subnodes should be Pagetree which is current status on my pagetype

#56479
Jan 23, 2012 14:26
Vote:
 

I guess the clue is how to get around the exception in the function below, but how!?

        /// <summary>
        /// Retrieves a PageData object based on supplied <see cref="EPiServer.Core.PageReference"/> 
        /// argument (from <see cref="EPiServer.Core.IPageSource"/>).
        /// </summary>
        /// <param name="pageLink"></param>
        /// <returns>Returns the PageData object for the specified EPiServer.Core.PageReference argument.</returns>
        /// <example>
        /// The following code example demonstrates the usage of <b>GetPage</b> to retrieve the <b>PageData</b> 
        /// object for the current page.
        /// <code>EPiServer PageData tmpPageData = GetPage( CurrentPageLink );</code>
        /// The following code example demonstrates the usage of <b>GetPage</b> and <b>CurrentPage</b> 
        /// to retrieve <b>PageData</b> information for the page specified in the <b>EventsContainer</b> attribute.
        /// <code source="../CodeSamples/EPiServer/PageBaseSamples.cs" region="GetPage" lang="cs" />
        /// </example>
        public virtual PageData GetPage(PageReference pageLink)
        {
            if (IsDesignMode)
            {
                return new PageData();
            }

            PageData page = DataFactory.Instance.GetPage(pageLink);

            // Check if the user has access to the page
            AccessLevel requiredAccess = (pageLink.ID == CurrentPageLink.ID) ? RequiredAccess() : AccessLevel.Read;
            if (!page.GetSecurityDescriptor().HasAccess(PrincipalInfo.CurrentPrincipal, requiredAccess))
            {
                // If the user is already logged in, throw exception
                if (PrincipalInfo.CurrentPrincipal.Identity.IsAuthenticated)
                {
                    throw new AccessDeniedException();
                }

                // If not logged in, make sure they get a graceful login screen
                AccessDenied();
            }

            return page;
        }

    

#56480
Edited, Jan 23, 2012 14:29
Vote:
 

If you use a Repeater instead inside your ItemTemplate it should work. The access exception is thrown when the inner PageTree is databound for parent pages that the user does not have access to (this is for MenuList and PageTree, if you call DataFactory.Instance.GetChildren directly it works fine since it won't filter out non-published and noaccess pages).

The only thing we're missing in the Repeater is a SelectedTemplate. In the Extensions for EPiServer CMS library I have an extension method that does this for me (see The SelectedTemplate and duplicate code).

<ItemTemplate>
        <li class="<%#SecurityHelper.HasAccess(Container.CurrentPage) ? "" : "unavailable" %>">
            <EPiServer:Property ID="Property1" runat="server" PropertyName="PageLink" /> 
            <asp:Repeater runat="server" DataSource="<%# EPiServer.DataFactory.Instance.GetChildren(Container.CurrentPage.PageLink) %>">
                <HeaderTemplate>
                    <ul>
                </HeaderTemplate>
                <ItemTemplate>
                    <li class="<%#SecurityHelper.HasAccess((PageData)Container.DataItem) ? "" : "unavailable" %> <%# IsSelected((PageData)Container.DataItem) %>">
                        <EPiServer:Property ID="Property1" runat="server" PropertyName="PageLink" />
                    </li>
                </ItemTemplate>
                <FooterTemplate>
                    </ul></FooterTemplate>
            </asp:Repeater>
        </li>
    </ItemTemplate>

    

Frederik

#56522
Jan 24, 2012 21:27
Vote:
 

Thank you for great explanation, Fredrik! I appreciate very much!

#56524
Jan 25, 2012 8:43
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.