Reputation: 13194
I am trying to achieve the following using the Sharepoint Client Object Model (CSOM) on a Sharepoint Online Instance:
SharepointResultTable
returned by the queryIn pseudo code:
var results = Sharepoint.GetSearchResults("Keyword");
var specificItem = results[2];
var itemId = sepcificItem.UniqueId;
Store(itemId);
And later:
var itemId = LoadItemId();
var item = Sharepoint.GetItem(itemId);
The querying part is working fine, I get a search result table offering lots of field values for each result, such as different URLs and also unique identifiers, titles, etc.
var clientContext = new ClientContext(SharepointUri);
clientContext.Credentials = new SharePointOnlineCredentials(SharepointUserName, GetSecureString(SharepointPassword));
var keywordQuery = new KeywordQuery(clientContext);
keywordQuery.QueryText = keyword;
var searchExecutor = new SearchExecutor(clientContext);
var sharepointResultTable = searchExecutor.ExecuteQuery(keywordQuery);
clientContext.ExecuteQuery();
foreach (var resultRow in sharepointResultTable.Value[0].ResultRows)
{
var path = (string) resultRow["ServerRedirectedURL"];
var id = Guid.Parse((string) resultRow["UniqueId"]);
}
The part I am missing now is: Which value(s) should I store for a result row and how can I perform an efficient query based on this data to get the item later? (Of course I could just perform a query with the same keyword again, but as I know the id or whatever I've stored, there must be more efficient ways. Also, the item might not be a result of the former keyword anymore because it might have changed).
I've tried this, using the id in the result table column 'UniqueId':
var clientContext = new ClientContext(SharepointUri);
clientContext.Credentials = new SharePointOnlineCredentials(SharepointUserName, GetSecureString(SharepointPassword));
var file = clientContext.Web.GetFileById(location);
clientContext.ExecuteQuery();
Console.WriteLine(file.Name);
return true;
It doesn't work, though:
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: The property or field 'Name' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
and honestly, I don't know what I'm doing here, because it's really hard to tell for me what the various Id's mean (DocId, WorkId, UniqueId, just to mention three...).
Can anybody with a little more Sharepoint experience tell me the way here?
Upvotes: 3
Views: 12261
Reputation: 59358
The error:
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: The property or field 'Name' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
tells that client object (File
) has not been requested. In order to request client object, ClientRuntimeContext.Load and ClientRuntimeContext.LoadQuery methods are intended.
Examples
//1. Retrieve File
var file = ctx.Web.GetFileById(id);
ctx.Load(file);
ctx.ExecuteQuery();
//2.Explicitly specify what properties (e.g. `Name`) to retrieve
var file = ctx.Web.GetFileById(id);
ctx.Load(file, f=>f.Name);
ctx.ExecuteQuery();
From another hand, since SharePoint Search Query API returns results across site collections, you need to consider to specify the proper url for ClientContext
in order to retrieve File
, for example:
using (var ctx = GetContext(webUri, userName, password))
{
var keywordQuery = new KeywordQuery(ctx) {QueryText = queryText};
var searchExecutor = new SearchExecutor(ctx);
var resultTables = searchExecutor.ExecuteQuery(keywordQuery);
ctx.ExecuteQuery();
foreach (var resultRow in resultTables.Value[0].ResultRows)
{
var itemWebUri = new Uri((string)resultRow["SPWebUrl"]); //<- get web url of item
var itemId = Guid.Parse((string)resultRow["UniqueId"]);
using (var curCtx = GetContext(itemWebUri, userName, password))
{
var file = curCtx.Web.GetFileById(itemId);
curCtx.Load(file, f => f.Name);
curCtx.ExecuteQuery();
Console.WriteLine(file.Name);
}
}
}
where
public static ClientContext GetContext(Uri webUri, string userName, string password)
{
var securePassword = new SecureString();
foreach (var ch in password) securePassword.AppendChar(ch);
return new ClientContext(webUri) { Credentials = new SharePointOnlineCredentials(userName, securePassword) };
}
Upvotes: 3