A Practical Guide to SharePoint 2013

A Practical Guide to SharePoint 2013
A Practical Guide to SharePoint 2013 - Book by Saifullah Shafiq

Sunday, November 25, 2007

Operation is not valid due to the current state of the object

Operation is not valid due to the current state of the object
This is one of the common errors that you see during SharePoint development. There could be many reasons for this error to occur. Here I will discuss one scenario. I have noticed that sometimes calling SPContext throws this error. It seems to be a bug. The code works for the first time but throws an error if you run the same statement again (during the same session). For example, consider the following code:
SPSecurity.RunWithElevatedPrivileges(delegate(){     using (SPSite site = new SPSite(SPContext.Current.Site.ID))     using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
     string ItemID = web.Lists["myList"].Items[0]["ItemID"].ToString();});
Interestingly, sometimes this code works but sometimes it fails after running successfully for the first time. I feel something goes wrong with the session. SPContext returns correct context when accessed for the first time but then throws the following error:
Operation is not valid due to the current state of the object
The error goes away if you remove the SPContext code and hard code the site and web values, for example:
SPSecurity.RunWithElevatedPrivileges(delegate(){      using (SPSite site = new SPSite(http://server/))      using (SPWeb web = site.OpenWeb("myweb"))
      string ItemID = web.Lists["myList"].Items[0]["ItemID"].ToString();
}
);
Obviously, we can not hard code the values in professional level applications. So, what's the solution? How can we get rid of this error? The error can be avoided if we write the same code in a different way. Here is the modified code:
SPWeb  webContext = null; //declare webContext out side the try ... catch and assign "null"
try
{
     webContext = SPContext.Current.Web; // Assign SPContext to the webContext
    SPSecurity.RunWithElevatedPrivileges(    delegate()
   {
        using (SPSite site = new SPSite(webContext.Site.ID))        using (SPWeb web = site.OpenWeb(webContext.ID))
        string ItemID = web.Lists["myList"].Items[0]["ItemID"].ToString();
   }
);
}
catch (Exception ex)
{
}
finally{
    if (webContext != null)
         webContext.Dispose();
}

Now, you won't get any error. Note that we declared the webContext outside the try... catch block and used SPContext only once. You can get "site" by calling webContext.Site.ID and similarly you can get "web" by calling webContext.ID. It's important that you dispose off the object after using it.