views:

60

answers:

2

I'm having trouble updating a SharePoint publishingWeb attribute under RunWithElevatedPrivileges. it fails with the exception "The security validation for this page is invalid" at this line : "pubWeb.IncludeInCurrentNavigation = false;". Below is the code i'm trying to run. Normally you can set AllowUnsafeUpdates = true, but publishingWeb's don't have this special property.

My question is what is the proper way to update publishingWeb attributes in an elevated context?

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite siteCollection = new SPSite(parentSiteUrl))
                {
                    //siteCollection.AllowUnsafeUpdates = true;
                    using (SPWeb web = siteCollection.OpenWeb(subSiteUrl))
                    {
                        //web.AllowUnsafeUpdates = true;
                        if (PublishingWeb.IsPublishingWeb(web))
                        {
                            // hide new sub-site from navigation elements.
                            PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
                            pubWeb.IncludeInCurrentNavigation = false;
                            pubWeb.IncludeInGlobalNavigation = false;
                            pubWeb.Update();
                        }
                    }
                }
            });
+1  A: 

If this change occurs on a postback (a POST), you should be calling SPSecurity.ValidateFormDigest() before you make the change. AllowUnsafeUpdates is only used for http GET requests.

If it is a GET request, I would have expected the commented-out line to have worked, but since it's commented I presume it didn't. I would suggest you to use:

pubWeb.Web.AllowUnsafeUpdates = true

as a PublishingWeb is a wrapper for an SPWeb instance, which is accessible via the Web property. It's strange though, I would have expected the supplied SPWeb to have been the same instance (and as such your commented line should have worked.)

x0n
This action is happening on postback. Given that do I need to combine SPSecurity.ValidateFormDigest() with pubWeb.Web.AllowUnsafeUpdates = true for this to work?
James
No. ValidateFormDigest is for POST, AllowUnsafeUpdate is for GET. The point of the form digest is that it keeps the page tamper-free and "safe." A get request is considered unsafe because it's easy to tamper with the querystring that might be used in sensitive method calls. If you find yourself making the same changes in POST and GET, then revisit your design. You should strive for POST only.
x0n
Given that these actions are on postback only, should "SPSecurity.ValidateFormDigest()" go inside of the RunWithElevatedPrivileges block or outside?
James
Inside. But just looking at your code a bit closer - ValidateFormDigest only works for the context web; you are using explicit URLs so I will have to modify my advice - you should be using both pubWeb.Web.AllowUnsafeUpdates AND ValidateFormDigest. The former enables changes on the pubwebs, the latter ensures the current page has not been tampered with. Follow?
x0n
umm, James? any further information? Fixed? If so, mark someone as answer if applicable. thx.
x0n
+1  A: 

Was reading a bit about using this property

pubWeb.Navigation.ExcludeFromNavigation(true, web.ID);

instead of

pubWeb.IncludeInCurrentNavigation = false;

pubWeb.IncludeInGlobalNavigation = false;

Not sure if that is relevant to what your trying to accomplish.

SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite siteCollection = new SPSite(parentSiteUrl))
                    {
                        //siteCollection.AllowUnsafeUpdates = true;
                        using (SPWeb web = siteCollection.OpenWeb(subSiteUrl))
                        {
                            //web.AllowUnsafeUpdates = true;
                            if (PublishingWeb.IsPublishingWeb(web))
                            {
                                // hide new sub-site from navigation elements.
                                PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
                                pubWeb.Navigation.ExcludeFromNavigation(true, web.ID);
                                pubWeb.Update();
                            }
                        }
                    }
                });
Shane