This was extremely annoying and caused me a few headaches. Googling came up with a ton of blog posts about setting web.AllowUnsafeUpdates = true was the solution. I did not find this to be the case.
Some other posts brought up the need for a FormDigest control on your page. This led me to the solution that worked for me.
From the MSDN page "To make posts from a Web application that modify the contents of the database, you must include the FormDigest control in the form making the post. The FormDigest control generates a security validation, or message digest, to help prevent the type of attack whereby a user is tricked into posting data to the server without knowing it. The security validation is specific to a user, site, and time period and expires after a configurable amount of time. When the user requests a page, the server returns the page with security validation inserted. When the user then submits the form, the server verifies that the security validation has not changed."
The key piece of information I found in here was the following line: "The security validation is specific to a user, site, and time period and expires after a configurable amount of time."
From my testing, I had a web and list under the following structure:
Now being an application page that gets put in the Layouts folder, I could access this page from any url that uses the _layouts url, like the following:
Here is the fix:
- If your MasterPage does not already have the FormsDigest control, add it to your application page.
You'll need to add the declaration to the top of your page: <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=184.108.40.206, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Next add the control to the Main section of your page:
<SharePoint:FormDigest ID="FormDigest1" runat="server" />
- Now, ensure you only call your page via a URL that includes the web. Again, from the MSDN article: "The security validation is specific to a user, site, and time period and expires after a configurable amount of time." So, after I added the FormDigest control to my page and using the 2 URLs from above, the second continued to fail. This is because the list I was trying to update lived under the Dept1 web. Once I started using the first URL (http://sp2010/sites/dept/dept1/_layouts/MyCustomAppPage/apppage.aspx), the error disappeared.