Friday, December 16, 2011

The query cannot be run for the following DataObject: GetCommonManager

I got that message when I previewed an InfoPath form (SharePoint Server 2010, InfoPath 2010):

The query cannot be run for the following DataObject: GetCommonManager 
InfoPath cannot run the specified query. 
The SOAP response indicates that an error occurred on the server: 
Server was unable to process request. ---> Object reference not set to an instance of an object.

I knew that new User Profile Service Application had been created and it used to work with old one without issues. The UserProfileService web service was healthy and calls for GetUserProfileByName were proceeded well. It just stuck with GetCommonManager call.

After some investigation I found My Site host was not defined in that brand new User Profile Service Application. When I defined it My Site Settings for the application  GetCommonManager started working again.

Hope that helps save time someone.


Wednesday, April 20, 2011

Title column value in ItemUpdating event for Document Library

I had to add some logic in ItemUpdating event receiver when anything was changed except one particular column. This had to work for both lists and libraries.
There some good posts about differences in properties for lists and libraries, e.g. this one from Randy Williams.

My code was

string[] ignoreFields = new string[] { "myField" };
foreach (SPField field in properties.ListItem.Fields)
{
if (!ignoreFields.Contains(field.InternalName) &&
properties.AfterProperties[field.InternalName] != null &&
(properties.ListItem[field.Id] == null ||
properties.ListItem[field.Id].ToString() != properties.AfterProperties[field.InternalName].ToString()))
{
// do something
}
}


This worked well for lists but I struggled with Title column in libraries.
I found properties.AfterProperties["Title"] is always null for libraries even when Title was changed.

After intensive googling I found that for libraries properties.ListItem.Title is mapped to properties.AfterProperties["vti_title"].

So, I had to add this

if (properties.List is SPDocumentLibrary && properties.ListItem.Title != properties.AfterProperties["vti_title"])
{
// do something
}

Thursday, March 10, 2011

No paging on SharePoint groups page

I don't know exact reason but this was a fact: I have more than 30 SharePoint groups in particular site collection and no paging at all. For other site collections paging is there.

I was very annoying: I had to filter by group name to have access to members list for groups with name started with 'k' and below.

I googled and found this is actually a hidden view of User Information List. Looked like it had 'Limit the total number of items returned to the specified amount' set under 'Items limit' instead of 'Display items in batches of the specified size'. So, the question was How to get access to its View Edit page?

Actual View Edit page is an application page in layouts folder (_layouts/viewedit.aspx) and it accepts two parameters in query string: List and View ids.

What I did:

- went to the groups page (http://spSite/_layouts/groups.aspx)

- opened page source and found list and view guids there. The answer was searching by WebQuerySourceHref= phrase. I found url with this values there.

- went to http://spSite/_layouts/viewedit.aspx?List={630F7EE7-1EA5-45F5-A162-4523647E1564}&View={132D30FA-EAD7-4134-B328-DB873CE82BD0}
(ids are mine :)

- changed the settings under 'Items limit'

Thursday, March 3, 2011

Accessing mixed authentication web app with Client Object Model and Web Serices

I have mixed authentication web app in SharePoint 2010: both Windows (NTLM) and Forms based.
When I tried to access it using Client Object Model with my NTLM credentials I got 401 (Unauthorized) exception. I googled and found this solution

...
clientContext.ExecutingWebRequest += new EventHandler(clientContext_ExecutingWebRequest);
...
}

static void clientContext_ExecutingWebRequest(object sender, WebRequestEventArgs e)
{
e.WebRequestExecutor.WebRequest.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
}


This works well for me.

Then when I tried to access same site using Lists.asmx web service with same NTLM credentials I got exactly same exception.
I added this method to the Web Service wrapper class (it's in Web References > ListWebService > Reference.map > Reference.cs in my case)


protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
System.Net.WebRequest wr = base.GetWebRequest(uri);
wr.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
return wr;
}

That solved the issue as well.

Tuesday, March 1, 2011

How to attach files to list item using Client Object Model

No way. It is just impossible to do that using Client Object Model.

This is my story.

The task was to copy list item with attachments to another location of separate farm. Everything was going fine. There are tons links in Google how to work with SharePoint 2010 Client Object Model. So my code was like that:


foreach (string attachment in sourceItem.Attachments)
{
string fileUrl = SPUtility.ConcatUrls(sourceItem.Attachments.UrlPrefix, attachment);
SPFile file = sourceItem.Web.GetFile(fileUrl);
Stream fs = file.OpenBinaryStream(SPOpenBinaryOptions.SkipVirusScan);

string attachmentPath = string.Format("{0}/{1}/Attachments/{2}/{3}", SPUtility.ConcatUrls(targetContext.Web.ServerRelativeUrl,"Lists"), targetListName,
targetItem.Id, attachment);

Microsoft.SharePoint.Client.File.SaveBinaryDirect(targetContext, attachmentPath, fs, true);
}


Looks good, doesn't it? However when I ran it ... ups ... I got 409(Conflict) error message. After debugging and checking attachmentPath was correct (e.g. /Lists/testList/Attachments/10/testFile.doc) I googled the error and found the most possible reason was the folder not found on the target. Actually it wasn't. Folder for item id (10) in attachmentPath is never exist in this stage by design because targetItem had been just created. But SaveBinaryDirect doesn't create folder. It just save file and expects correct path provided.
I tried to create the folder with ListItemCreationInformation object but without any success. That technique is for creating ordinary folders and doesn't work for creating folders under Attachments folder. Then I found this stack overflow thread. Looks like Microsoft had confirmed it is not possible to achieve that using Client Object Model.

The only one way for now is using Lists.asmx web service.
So, I added web reference to the web service. In VS 2010 I did right click on References, then 'Add Server Reference', then clicked 'Advanced...' button on the bottom and provider web service url (any existing url e.g. http://spdev/_vti_bin/lists.asmx in my case).

This is my final code

ListsWebService.Lists objLists = new ListsWebService.Lists();
objLists.Credentials = targetContext.Credentials;
objLists.Url = SPUtility.ConcatUrls(targetWebUrl, "/_vti_bin/lists.asmx");

foreach (string attachment in sourceItem.Attachments)
{
string fileUrl = SPUtility.ConcatUrls(sourceItem.Attachments.UrlPrefix, attachment);
SPFile file = sourceItem.Web.GetFile(fileUrl);
byte[] fileContent = file.OpenBinary(SPOpenBinaryOptions.SkipVirusScan);
objLists.AddAttachment(targetListName, targetItem.Id.ToString(), file.Name, fileContent);
}


Hope it helps someone make things clear.