views:

698

answers:

2

I get the famous error "The security validation for this page is invalid. Click Back..." while creating SharePoint sites using the object model...

This is my code in the web part to create share point sites.

using (SPSite objSite = new SPSite(SPContext.Current.Site.ID))
{
    objSite.AllowUnsafeUpdates = true;
    using (SPWeb objWeb = objSite.OpenWeb(SPContext.Current.Web.ID))
    {
        objWeb.AllowUnsafeUpdates = true;
        SPWeb NewWeb3 = null;
        try
        {
            NewWeb3 = objSite.AllWebs.Add(RelativeITTURL, projectCode, SiteDescription, LocaleID, ITTSiteDefinitionTemplate, false, false);
            NewWeb3.AllowUnsafeUpdates = true;

            NewWeb3.Navigation.UseShared = true;
            NewWeb3.BreakRoleInheritance(true);
            NewWeb3.AllowUnsafeUpdates = true;
            ITTSiteID = new Guid(NewWeb3.ID.ToString());
            NewWeb3.Update();

            NewWeb3.AllowUnsafeUpdates = false;
        }
        catch (Exception ex3)
        {
            StringBuilder Message = new StringBuilder();
            Message.Append(string.Format("Error while creating the site for the 3rd time. '{0}/{1}'\n", _siteCollection, projectCode));
            Message.Append(string.Format("Project Code: {0}\n", projectCode));
            Message.Append(string.Format("ITT Site URL: {0}\n", FullITTSiteURL));
            Message.Append(string.Format("Web Template: {0}\n", _webTemplate));
            Message.Append(string.Format("Web Template To String: {0}\n", ITTSiteDefinitionTemplate.ToString()));
            Message.Append(string.Format("Locale ID: {0}\n", LocaleID.ToString()));
            //Message.Append(string.Format("Form digest validated: {0}\n", ValidateFormDigect.ToString()));

            NFER.ErrorManagement.ErrorLog.LogErrorToEventLog(ex3, Message.ToString());

            lblProvisionStatus.Text = "An error occurred while creating the site. Please close your browser and try again.";
            return;
        }
        finally
        {
            //Since an error can occur
            if (NewWeb3 != null)
                NewWeb3.Dispose();
        }
    }
}

I get an error at this line

CurrentSite.AllWebs.Add...

I can create sites successfully with the system account but with a limited test account it fails. The funny thing is it was working at one point in time but now it is not.

This is the call stack

Error Message: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again. 
Error Source: Microsoft.SharePoint 
Stack Trace:    at Microsoft.SharePoint.Library.SPRequest.CreateWeb(String bstrUrl, String bstrTitle, String bstrDescription, UInt32 nLCID, String bstrWebTemplate, Boolean bCreateUniqueWeb, Boolean bConvertIfThere, Guid& pgWebId, Guid& pgRootFolderId, Boolean bCreateSystemCatalogs)
   at Microsoft.SharePoint.SPSite.CreateWeb(String strUrl, String strTitle, String strDescription, UInt32 nLCID, String strWebTemplate, Boolean bCreateUniqueSubweb, Boolean bConvertIfThere, Guid webId, Guid rootFolderId, Boolean createSystemCatalogs)
   at Microsoft.SharePoint.SPSite.SPWebCollectionProvider.CreateWeb(String strWebUrl, String strTitle, String strDescription, UInt32 nLCID, String strWebTemplate, Boolean bCreateUniqueSubweb, Boolean bConvertIfThere)
   at Microsoft.SharePoint.SPWebCollection.Add(String strWebUrl, String strTitle, String strDescription, UInt32 nLCID, String strWebTemplate, Boolean useUniquePermissions, Boolean bConvertIfThere)
   at Microsoft.SharePoint.SPWebCollection.Add(String strWebUrl, String strTitle, String strDescription, UInt32 nLCID, SPWebTemplate WebTemplate, Boolean useUniquePermissions, Boolean bConvertIfThere)
   at ProjectManWebParts.ITTStage2DataCapture.<>c__DisplayClass3.<BtnProvisionITT_Click>b__0() 
Target Site: Void CreateWeb(System.String, System.String, System.String, UInt32, System.String, Boolean, Boolean, System.Guid ByRef, System.Guid ByRef, Boolean) 
Data Begin Information 

Data End Information 

Error Message: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again. 
Error Source:  
Stack Trace:    at Microsoft.SharePoint.Library.SPRequestInternalClass.CreateWeb(String bstrUrl, String bstrTitle, String bstrDescription, UInt32 nLCID, String bstrWebTemplate, Boolean bCreateUniqueWeb, Boolean bConvertIfThere, Guid& pgWebId, Guid& pgRootFolderId, Boolean bCreateSystemCatalogs)
   at Microsoft.SharePoint.Library.SPRequest.CreateWeb(String bstrUrl, String bstrTitle, String bstrDescription, UInt32 nLCID, String bstrWebTemplate, Boolean bCreateUniqueWeb, Boolean bConvertIfThere, Guid& pgWebId, Guid& pgRootFolderId, Boolean bCreateSystemCatalogs) 
Target Site: Void CreateWeb(System.String, System.String, System.String, UInt32, System.String, Boolean, Boolean, System.Guid ByRef, System.Guid ByRef, Boolean) 
Data Begin Information 

Data End Information 


 Custom Error Message: Error while creating the site for the 3rd time. 




For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

Please any help is truly appreciated.

+1  A: 

What you are doing, is preventing the "GET parameters are having side effects" exceptions from being SharePoint's object model.

However the exception "The security validation for this page is invalid" actually comes from Form Digest component that lives in every form page in your web app. The idea is to generate a unique ID for each form and to VALIDATE it at the server when the form gets submitted.

Sometimes, to work around this problem, it's worth hacking into HTTPContext.Current and setting the "FormDigestValidated" field to true. Like this: HttpContext.Current.Items["FormDigestValidated"]=true;

EDIT Some people say that calling SPUtility.ValidateFormDigest() does the same thing (see http://stephenkaye.blogspot.com/2008/03/form-digest-and-spsecurityrunwithelevat.html). This sounds a bit less "hackish" than setting the field in HttpContext

I found also an explanatory article about security validation etc: http://hristopavlov.wordpress.com/2008/05/21/what-you-need-to-know-about-allowunsafeupdates-part-2/

naivists
Would I call "SPContext.ValidateFormDigest()" method in Page load?
iHeartDucks
Read the article, got it thanks... let's see how it works
iHeartDucks
Calling this "SPUtility.ValidateFormDigest()" method at the top of the button click solved the issue.
iHeartDucks
A: 

Please, try this:

Guid webId = Guid.Empty;
SPSecurity.RunWithElevatedPrivileges(delegate() // it's required?
{
    using (SPSite site = new SPSite(SPContext.Current.Site.ID))
    {
        try
        {
            site.AllowUnsafeUpdates = true;
            using(SPWeb web = site.AllWebs.Add(RelativeITTURL, projectCode, 
                SiteDescription, LocaleID, siteDefinitionTemplate, false, false))
            {
                web.AllowUnsafeUpdates = true;
                web.Navigation.UseShared = true;
                web.BreakRoleInheritance(true);
                web.AllowUnsafeUpdates = true;
                web.Update();
                webId = new Guid(NewWeb3.ID.ToString());
            }
        }
        catch (Exception ex3)
        {
            // error handler
        }
    }
 });

Please let me know if this doesn't works (I'm without WSS here)

Rubens Farias
One of my mistake was that I was adding the new site to the site.AllWebs collection. I should have added it to the objWeb.Webs collection.
iHeartDucks