My customer has a requirement to track the last login date/time for each SharePoint user so that they can disable accounts that have not had any activity for a time period. I decided to implement this requirement by creating an HttpHandler and tying a jQuery .post call into the custom masterpage. The HttpHandler would then update a property, LastLogin, that has been added to the user profile service application.

The issue I ran into is that SharePoint would constantly complain about not allowing updates via a GET, and that I needed to set the AllowUnsafeUpdates property on the SPWeb object. Sounds simple and straight forward enough, and oddly this was an instance where not only did SharePoint give you a decent error, it even went so far as to propose a solution! Double word score! Unfortunately it took forever to figure out WHICH SPWeb object it was talking about! Check out the following code:

private void UpdateUserLastLogin(HttpContext context)
{
    string siteURL = SPContext.Current.Site.Url;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(SPContext.Current.Site.ID))
        using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
        {
            // this is the important bit
            SPContext.Current.Site.AllowUnsafeUpdates = true;
            SPContext.Current.Web.AllowUnsafeUpdates = true;
            SPServiceContext serviceContext = SPServiceContext.GetContext(site);
            UserProfileManager profileManager = new UserProfileManager(serviceContext);
            UserProfile profile;
            if (!profileManager.UserExists(SPContext.Current.Web.CurrentUser.LoginName))
            {
                profile = profileManager.CreateUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
            }
            else
            {
                profile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
            }
            profile["LastLogin"].Value = DateTime.Now;
            profile.Commit();
            SPContext.Current.Web.AllowUnsafeUpdates = false;
            SPContext.Current.Site.AllowUnsafeUpdates = false;
        }
    });
}

So if you look at the part commented "This is the important bit" you will see AllowUnsafeUpdates getting set. This is what I finally came to which actually worked. Previously I tried the following:

site.AllowUnsafeUpdates = true;
web.AllowUnsafeUpdates = true;

And that did not work at all. So I'm still not completely clear why setting it on the SPContext.Current.Web works, considering that I am spinning up new instances of SPSite and SPWeb and sending them to UserProfileManager, but whatever. I'll take it.

If anyone can explain why this works that would be awesome, in the meantime I'll keep this handy incase I run across this dreaded error in the future.