As much as I seem to be enjoying my trip with EpiServer there are some little things I don’t seem to appreciate all that much and I’m not quite sure how to work around some of them in an elegant way.

EpiServer has a fairly advanced way of dealing with properties but it also seems to be a bit tough on the developer whenever you try to do something more than just strictly using its API-s. One of the areas I don’t really enjoy is the dealing with the pages that are expired or generally unavailable for the user for various reasons.

In the project that we’ve been implementing recently we needed to store page ids for further reference in numerous places and although this generally works, accessing a page that’s been deleted, expired or not published yet, has proven to be a challenge and I can’t seem to be able to find an elegant solution around it.

For instance, we have a list of bloggers, that are stored in our faceted navigation with links to their pages, our system lists them and the links to their pages, should someone’s page be unpublished yet – we run into problems.

Another good sample of where this is needed is a list of pages (A multi-page property of sorts). There seems to be no implementation of a multi-page property in EpiServer and the only reasonable implementation that I’ve been able to find is available through EpiCode. The following is it deals with the pages going in or out of the system, which leads me to think that the only way of checking whether a page is available for me is to instantiate it with all the consequences of it:

// get the page with error handling for // access denied or deleted page try { PageData page = Global.EPDataFactory.GetPage(pageref); isExternalLink = (page.StaticLinkURL != multipageLinkItem.Url); if (page != null && isExternalLink == false) _selectedPages.Add(page); } catch (PageNotFoundException notFoundEx) { // We should not add the page if it // does not exist } catch (EPiServer.Core.AccessDeniedException accessDeniedEx) { // User is not allowed to see page, skip it } catch (Exception ex) { // The page could not be loaded, for some other // reason. System.Diagnostics.Debug.Write("Page could not be loaded: " + pageref.ToString(), "PropertyMultiPage"); }

What I do not like about this part (of an otherwise remarkable piece) of code is that exceptions are not supposed to be the driving force of the program flow. But in this case they seem to have been forced to do it. It’s like I had to open a file to check its size or whether it even exists.

I can see why the system will not let me visit the page if I’m not allowed to do it as a user, but the fact that the API frowns at me whenever I even try to instantiate it just to check its existence or my rights to it has proven to be quite problematic. After all a user is not supposed to see a login screen in the list of pages, but rather when he/she enters a page that he/she no no rights to. Better yet, give me a way to check whether I even can access it.

Is there one already? Has anyone heard? Did anyone see?

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)

This entry (Permalink) was posted on Thursday, August 30th, 2007 at 7:36 pm and is filed under .Net Framework, ASP.NET, C#, EPiCode, EPiServer, Software Development, Web applications. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.

  • Dariusz Macina

    Why can’t you just use QueryDistinctAccess to check if CurrentUser has enough rights to access the page?

  • I see your point, and I agree that exceptions should not be the driving force of program flow.

    For the PageNotFoundException exception, there really is no other way to do this, as far as I know. We have what we think is a valid PageReference, but it is in fact not. I guess the API could return null for doing a GetPage on a non existing page, but these references are scattered around in markup and code, and the PageNotFoundException is a better error to show than the NullReferenceException on the first line that was actually trying to use the null’ed PageData object you just recieved. :-)

    If you want to check if the user has access to the page, you will need to load it using the GetPage overload in the DataFactory:
    PageData pd = Global.EPDataFactory.GetPage(myRef, AccessControlList.NoAccess);
    This code gets the page, without checking the security (I know, it is a bad enum name, read it as “NoAccessCheck” to remember the difference.)

    Then you can check the access right by looking at the ACL property (and its Query methods.)

    To my defence (I wrote the code above) I did not really care what access rights the user have on that page. If she cannot see it, I’m skipping it. Checking the rights means I have to load it into memory anyway, and the cost of an exception in contrast to that can be ignored.

  • Steve, I am as far as possible from critiquing the code, it’s working within the bounds that are set by Episerver- hence the post title. I have to admit, I was not aware of the possibility of pulling the page with no access, which, although possible still seems to be more of a workaround rather than a solution. After all – I’m not interested in the page content but rather with its metadata. an ideal solution would be to be able to query access AND existence against a page PageReference, which I am able to do with file without opening it.

    Dariusz – if I’m not mistaken, QueryDistinctAccess works only on a page that exist and one that you’ve already Getpage()-ed – and then, the solution for page that has been deleted form the system is outstanding from it. What I’m thinking of would be a simple extension to ACL indeed that could even be static but would accept a page reference in addition to SID and AccessControlList.NoAccess.

    GetPage is really heavy for a way to query a page access – I’m currently evaluating an EpiServer project that nearly failed performacne wise and we-ve just profiled it and the poor performance is mostly attributed to an excessive GetPage() calls that are taking up to 75% of whole CPU time spent within the application.