SPListItemVersion.Level is returning "Published" and SPListItem.HasPublishedVersion returning tru on unpublished pages


  • My code in debugger shows weird behaviour. The SPListItem returned into pageItem by pWeb.DefaultPage.Item is the default page for a sub web. I'm building a menu web part that will show the title of the sub web as a link and a summary for the page taken from a summary field on the default page. This is for a public facing website, so will be using anonymous access. But of course I don't want to show a link to a sub web if the default page is not published. This would normally not be a problem the code would run under the anonymouse user access and only return what they can see. But PublishingWeb.DefaultPage returns a 401 Unauthorised error when run as anonymous. It needs to be run with RunWithElevatedPrivileges see here:

    But this causes the problem that when running elevated it can now access all pages wheteher they are published or not. So I thought I'd just check to see if the item has a published version with SPListItem.HasPublishedVersion. But this is where the weird behaviour happens. It is returning true when the page has never been published. For example I create a whole new publishing sub site. A default page gets created as part of this site. But I have never submitted the page for approval to publish it. I may have added a word and then saved the page but never 'published' it. In my code I added the string 'level' to check what the levels are of each version of the page. It is returning 3 versions, 2 which it says are "Published" and one which it says is "Draft". I go to that page in the site and check the page history in the ribbon and then click version history. There are 3 versions of the page 0.1, 0.2 and 0.3. None of which have an approved status.

    So why is SPListItem.HasPublishedVersion returning true and why is SPListItemVersion.Level returning "Published" when the page has NEVER been published?

    pageItem = pWeb.DefaultPage.Item;
     if (pageItem.HasPublishedVersion)
      foreach (SPListItemVersion itemVersion in pageItem.Versions)
       string level = itemVersion["Title"].ToString() + " for " + web.Title + " itemVersion.Level = " + itemVersion.Level.ToString() + " itemVersion.VersionId = " + itemVersion.VersionId;

    16. března 2012 3:09


  • Ok I found the answer. In my RunwithElevatedPrivileges code I am now returning the int for the SPListItem ID instead of the SPListItem. Then in non-elevated code I try to get that page using the int ID. My code to get return the ID:

    int GetDefaultPageID(Guid webId, Guid siteId)
                /* Have to return just the ID int for trying to find the page when anonymous user accessing the site
                 * We don't want to return an SPListItem from elevated priveleges back to someone who shouldn't have access to see it.
                SPListItem pageItem;
                pageItem = null;
                    SPSite elevatedSite = new SPSite(siteId);
                    SPWeb elevatedWeb = elevatedSite.OpenWeb(webId);
                    PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(elevatedWeb);
                    pageItem = pWeb.DefaultPage.Item;
                if (pageItem != null)
                    return pageItem.ID;
                    return 0;

    Then in non-elevated code I use that ID:

    Guid siteId = SPContext.Current.Site.ID;
    Guid webId = SPContext.Current.Web.ID;
    int defPageId;
    defPageId = GetDefaultPageID(webId, siteId);
    SPList pages = web.Lists["Pages"];
    SPListItem defaultPage = null;
     defaultPage = pages.GetItemById(defPageId);
    catch (Exception ex)
    It doesn't explain why the SpListItem.HasPublishedVersion was returning true for unpublished pages but it does give me the functionality I was originally after which is to find the default page for a bunch of subwebs and only show it to the user in the menu if they have access to that page. :)

    • Označen jako odpověď Vertigrator 16. března 2012 5:04
    16. března 2012 5:03