Inconvenient SPWeb.GetListItem (Exception from HRESULT: 0x80070001)
SPWeb ships with the GetListItem method which allows you to retrieve a list item using a URL. While in general you would use the SPContext.Current.ListItem property to get the current list item, there are situations when the GetListItem method becomes really useful, like for example getting the current list item with elevated privileges. There is however one confusing thing about the GetListItem method and if you’re not focused enough, you will spend hours trying to figure out what is wrong.
What’s the inconvenience?
The GetListItem method is being called in the context of a site (SPWeb):
string listItemUrl = SPContext.Current.ListItem.Url; SPListItem listItem = web.GetListItem(listItemUrl);
Without reading the WSS SDK you would expect the above to work. Because the GetListItem method is being called in the context of a web, you would expect it to accept site-relative URL’s. Unfortunately the above doesn’t work and results in the following error:
Incorrect function. (Exception from HRESULT: 0x80070001) Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Runtime.InteropServices.COMException: Incorrect function. (Exception from HRESULT: 0x80070001)
To make things work you should use the server-relative URL of list item. The problem is that the SPListItem class doesn’t provide a server-relative URL. If you need one you can use one of the two approaches. First of all you can combine the site-relative URL of the list item with the server-relative URL of the site:
string serverRelativeListItemUrl = SPUrlUtility.CombineUrl( SPContext.Current.Web.ServerRelativeUrl, SPContext.Current.ListItem.Url );
The nice thing is that the WSS team has foreseen such scenario and has provided the server-relative list item URL within the SPContext class:
string serverRelativeListItemUrl = SPContext.Current.ListItemServerRelativeUrl;
So if you need a server-relative URL of a list item in a Publishing Page scenario (when you actually * are *on the Page (list item)), the second approach is the way to go. It is faster than the first one because you don’t need to access the SPWeb object and combine both URL’s.
Later on, while reading carefully the WSS SDK, I’ve found out that the SDK says that the GetListItem method requires a server-relative instead a site-relative URL. Yet I find it rather inconvenient of SharePoint to expect a server-relative URL while calling a method on an instance of site. That’s why SPWeb.GetListItem has made it to my Inconvenient SharePoint gallery.