tisdag 10 juni 2008
Linq for SharePoint
måndag 2 juni 2008
Basic SPQuery problems
Basic query with SPQuery
List<SPListItem> cases = new List<SPListItem>();
SPSite site = Helper.GetDefaultSite();
SPWeb web = site.OpenWeb();
SPList list = web.Lists["myCaseList"];
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name='ProblemType'/><Value Type='Text'>6</Value></Eq></Where>";
SPListItemCollection foundItems = list.GetItems(query);
if (foundItems.Count > 0)
foreach (SPListItem item in foundItems)
cases.Add(item);
caseList.Cases = cases;
Annoying WSS errors
Value does not fall within the expected range
This means the same as "index outside of range" or "the key is not present in the dictionary". Or make it simple, you have referenced something in a dictionary where the key isn't present. Like Trying to get a list from the SPWeb-object that doesn't exists. This troubled me for quite some time.
Cannot complete this action
Is most commonly due to user rights, or, the lack of. WSS need you to impersonate before doing certain kinds of tasks. Read this post. Another fantastic description of the problem. Not vague at all.
One or more field types are not installed properly. Go to the list settings page to delete these fields.
When you get this error, it probably is due to a reference to a field with special character in it's name. For instance, if you have a field namned "Problem type" it has to be referenced as "ProblemType" (WSS 3.0). To avoid this, and you really should, never name a field with a non-alphanumeric character. Use only numbers and letters.
Exception occurred. (Exception from HRESULT: 0x80020009 (Part 1)(DISP_E_EXCEPTION))
From what I've seen, this can come up on alot of different instances. This guy, David, has a solution for it in his blog.
To sum up his post:
stsadm.exe -o export -url http://yourweb/ -filename c:\yourweb.cab
stsadm.exe -o deletesite -url http://yourweb/
stsadm.exe -o import -url http://yourweb/ -filename c:\yourweb.cab
Worked fine for me, and resolved a problem with cached list templates that refused to take on new fields even though i retracted and deleted the solution where they originated from.
Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)) (Part 2)
The problem resurfaced when I tried to use a SPQuery to search for a SPUser. All other searches works fine. Another blog suggested that it could be due to a disposed SPSite. I notices that I had typed "type" instead of "Type" in the <Value>-tag. I changed it to a capital T and everything worked fine.
Exception from HRESULT: 0x81070215
Go to your schema.xml for the list you are trying to create and change the Name attribute of the
Creating webparts outside of SharePoint
That's when I evolved a simple Helper-class for get default sites and such so I could test the webpart outside of WSS and just put it in when needed.
Now i just use Helper.GetDefaultSite() and specifying an application setting ("CM.Debug") with a value of true if I'm of the bars of WSS. Just remeber not to dispose the SPSite or SPWeb if you're within WSS context.
The thing is, when you try to do some actions, such as updating an SPListItem, you will get an error unless you impersonate as yourself. Inside of the GetDefaultSite() I've included a call to GetUserToken() which gets the SPUserToken for you. If you havn't impersonated as yourself, you will get the wonderful error message "Cannot complete this action". Thank you SharePoint for being so precise in your error messages =). Feels like all of their is wrapped inside a try-catch and always return something like that, hehe.
Helper class
public static class Helper
{
public static bool Debug
{
get { return bool.Parse(GetSetting("CM.Debug")); }
}
public static string DebugUrl
{
get { return GetSetting("CM.DebugUrl"); } //http://WSS/sites/yoursite
}
public static SPUserToken GetUserToken()
{
SPSite site = new SPSite(debugUrl);
SPWeb web = site.OpenWeb();
SPUserToken token = null;
if (Debug)
token = web.AllUsers[WindowsIdentity.GetCurrent().Name].UserToken;
else
token = web.CurrentUser.UserToken;
web.Dispose();
site.Dispose();
return token;
}
public static SPSite GetDefaultSite()
{
if (Debug)
return new SPSite(debugUrl, GetUserToken());
else
return SPSite(SPContext.Current.Site.ID);
}
public static string GetSetting(string setting)
{
return System.Web.Configuration.WebConfigurationManager.AppSettings[setting];
}
Example code using Helper
public static Case Load(int id)
{
SPSite site = Helper.GetDefaultSite();
SPWeb web = site.OpenWeb();
SPList list = web.Lists["myCaseList"];
Case loadedCase = new Case();
loadedCase.Loaded = true;
if (list == null)
return null;
foreach (SPListItem item in list.Items)
{
... some code
}
if (Helper.Debug)
{
web.Dispose();
site.Dispose();
}
return loadedCase;
}
Another way to impersonate
System.Security.Principal.WindowsImpersonationContext wic = null;
wic = System.Security.Principal.WindowsIdentity.GetCurrent().Impersonate();
SPSite site = new SPSite(...);
SPWeb web = site.OpenWeb(...);
....
wic.Undo();