SharePoint get ContentType Name - c#

I am trying to get All Folders and Files from a SharePoint library, executing a single Request.
CamlQuery query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll' />";
var libraryName = "Specific Documents";
ListItemCollection itemsRaw = clientContext.Web.Lists.GetByTitle(libraryName).GetItems(query);
clientContext.Load(itemsRaw);
clientContext.ExecuteQuery();
This code works well, and as result I have a list of All Folders and Files within the specified library.
It seems that the files details are loaded in a lazy manner. Only the first level from details hierarchy. But I don't know how, the FieldValues collection is filled with Data.
I see that the ListItem ContentType.Name is not initialized.
Is it possible somehow to update the query in a manner which will load the data for ContentType in this single call.
Or the only possibility is to iterate through all files and do a load of ContentType for the specific file?
I did this in the following way:
foreach(var listItem in listItemCollection)
{
context.Load(listItem, k => k.ContentType);
context.ExecuteQuery();
var contentTypeName = listItem.ContentType.Name;
}
But I am going to get this information in a single call, If it is possible, without iterating in the collection and starting multiple calls to ClientContext.
P.S.: I am new to SharePoint programming. I just want to fix a bug.
Thanks!

As you correctly noticed in SharePoint Client Side Object Model (CSOM) ClientRuntimeContext.Load Method does not retrieve all the properties for client object.
ClientRuntimeContext.Load Method has the following syntax:
public void Load<T>(
T clientObject,
params Expression<Func<T, Object>>[] retrievals
)
where T : ClientObject
where retrievals parameter is intended for specifying properties that have to be retrieved.
Secondly, since SharePoint CSOM supports Request Batching, your example could be modified to this one:
foreach (var item in items)
{
ctx.Load(item, i => i.ContentType);
}
ctx.ExecuteQuery();
Note: request is submitted to the server only once in this example
But still the provided example requires two requests to the server:
retrieve list items
retrieve content type for list items
and it could be improved from performance perspective by reducing requests to the server till one.
Final example
The example demonstrates how to retrieve list items and specify explicitly which properties to retrieve:
var listTitle = "Documents";
var query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll' />";
var items = ctx.Web.Lists.GetByTitle(listTitle).GetItems(query);
ctx.Load(items,icol => icol.Include(
i => i.ContentType,
i => i.FieldValues));
ctx.ExecuteQuery();

The final example does not work (in SP2010).
There is an exception "The query expression is not supported"
If you explicitly states all required fields then the solution below works.
var listTitle = "Documents";
var query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll' />";
var items = ctx.Web.Lists.GetByTitle(listTitle).GetItems(query);
string[] fieldsToMigrate = new string[] { "Title", "FieldA", "FieldB" };
ctx.Load(items, a => a.Include(b => b.ContentType, b => b["FileRef"]));
foreach (var f in fieldsToLoad) {
ctx.Load(items, includes => includes.Include(a => a[f]));
}
ctx.ExecuteQuery();

Related

Read And Write Data to SharePoint Site Pages

I am new to Sharepoint and currently I want to write a function where I can read and write data to Sharepoint pages. This is the structure of the URL I want to connect to read and write data: https://mycompany.sharepoint.com/sites/SubSite/SubSite1/SitePages/Home.aspx
Then, I open the connection to it by using:
ClientContext clientContext = new ClientContext("https://mycompany.sharepoint.com/sites/SubSite/SubSite1/");
clientContext.Credentials = new SharePointOnlineCredentials("user#mycompany.com", password);
I use SecureString for the password
Then, I load site pages in to a list and read each field to examine:
List colList = clientContext.Web.Lists.GetByTitle("Site Pages");
FieldCollection colfield = colList.Fields;
IEnumerable<Microsoft.SharePoint.Client.List> resultCollection = clientContext.LoadQuery(
clientContext.Web.Lists.Include(
list => list.Title,
list => list.Id));
clientContext.Load(colList);
clientContext.Load(colfield);
clientContext.ExecuteQuery();
Then I loop through every field to examine
for(int i = 1; i <= 4; i++){
ListItem lst = colList.GetItemById(i);
foreach (Field field in colfield){
clientContext.Load(field);
clientContext.ExecuteQuery();
var val = lst[field.Title];
}
}
I figured out that there are some fields in colList, such as: DataSource, etc. containing this exception:
The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested
My question is how can I properly connect to Sharepoint site pages to read and write data in them?
You are iterating through all the fields of colList but including only Id & Title fields in
clientContext.Web.Lists.Include(
list => list.Title,
list => list.Id));
That's why you are getting above exception.
You have to Include all the fields you want to retrieve OR just load the list clientContext.Load(colList); and don't Include anything if you want to retrieve all the fields.

Finding changesets associated with the work item or having specific comment TFS Api

I'm trying to find all changesets associated with the work item using Microsoft.TeamFoundation.WorkItemTracking.Client. Using query I was able to get the information about the work items in question, however I cannot find any changeset information on the object I'm getting back. In addition to that there are some changesets that are not linked to specific work item but easy identifiable by the comment. Is there a quick way to find these using tfs api?
Edit: this is not a duplicate of How to get work items associated with a changeset id using tfs api? b/c in that question person has a changeset and would like to find associated work items. In my case I have a work items and I would like to find all changesets associated with the specific work items. In addition to that I need to find all changesets that have specific string in the comment.
After more googling on the subject and exploring tfs API here is what I ended up with:
If all you changesets are linked to the work items (not really my case but this is what I originally was asking about):
// based on https://etoptanci.wordpress.com/2011/05/04/seeing-all-code-changes-for-a-work-item/
private static void GetChangesForWorkItem()
{
var configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(new Uri(#"http://myserver:8080/tfs"));
var tpcService = configurationServer.GetService<ITeamProjectCollectionService>();
var collectionNodes = configurationServer.CatalogNode.QueryChildren(
new[] { CatalogResourceTypes.ProjectCollection },
false, CatalogQueryOptions.None);
var collectionNode = collectionNodes.First(x => x.Resource.DisplayName == "<collection name>");
// Use the InstanceId property to get the team project collection
Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
TfsTeamProjectCollection collection = configurationServer.GetTeamProjectCollection(collectionId);
var vcs = collection.GetService<VersionControlServer>();
var store = new WorkItemStore(collection);
var workItems = new List<WorkItem>()
{
store.GetWorkItem(1123),
store.GetWorkItem(1145),
};
var associatedChangesets = new List<Changeset>();
foreach (var workItem in workItems)
{
foreach (var link in workItem.Links)
{
if((link==null) || !(link is ExternalLink))
continue;
string externalLink = ((ExternalLink)link).LinkedArtifactUri;
var artifact =LinkingUtilities.DecodeUri(externalLink);
if (artifact.ArtifactType == "Changeset")
associatedChangesets.Add(vcs.ArtifactProvider.GetChangeset(new Uri(externalLink)));
}
}
Console.WriteLine(associatedChangesets.Select(x=>x.ChangesetId).OrderBy(x => x));
}
If you need to get by comment as well then you gate all changesets for the daterange and then filter out by Changeset.Comment which is a string.
Check the REST API:
GET https://{instance}/defaultcollection/_apis/tfvc/changesets/{id}?api-version={version}[&includedetails={boolean}&includeworkitems={boolean}&includesourcerenames={boolean}&maxchangecount={int}&maxcommentlength={int}]
You can also use RestAPI (as stated in the first answer)
https://www.visualstudio.com/en-us/docs/integrate/api/wit/work-items#with-links-and-attachments
You need to filter out "relations" array with rel == "ArtifactLink"

To fetch a specific SharePoint Office 365 list item using CAML query?

I am creating a sample program to check ListItem existence at Sharepoint list.
My SharePoint list has one of column (field) named 'Title' or it can be any other name with text type.
I Know that when we create a list at SharePoint for each item in the list a "ID" field is assigned by SharePoint list item itself.
I am creating my sample application in C# using Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime dlls.
PROBLEM: I want to get a specific item in the list on the basis of the value of 'Title' column using CAML query.
My List may contains thousands of items,
Using CAML Query :
"<View><Query><Where><Leq>" +
"<FieldRef Name='ID'/><Value Type='Number'>100</Value>" +
"</Leq></Where></Query><RowLimit>7000</RowLimit></View>"
I am successfully retrieving ListItemCollection and throw that I can get ListItem. But its very time consuming and inefficient way, to traverse whole list to get particular item.
Although it is possible to get a specific item in list through the ID field using CAML query, but as i don't know what is the ID of the Item, therefore i want to fetch it through my "Title" field,
for this i tried the following CAML Query
`
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><eq>" +
"<FieldRef Name='TITLE'/><Value Type='TEXT'>2</Value>" +
"</eq></Where></Query></View>";`
but I get the following exceptions when I run the code
1. Value does not fall within the expected range. this exception is generated when I try to fetch Item through the 'Title' instead of 'ID' field, in the FieldRef Name parameter.
2. One or more field types are not installed properly when i created a coloumn manually in the list, and passed it in the FieldRef Name parameter
My code snippet is as follows
class sharepoint1
{
ClientContext context = null;
string OBJECTMETATADTA_ID = "Title";
private class Configuration
{
public static string ServiceSiteUrl = "";
public static string ServiceUserName = "";
public static string ServicePassword = "";
}
private ListItemCollection getListItemCollectionFromSP(String listName)
{
Web oWebsite = context.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle(listName);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><eq>" +
"<FieldRef Name='Title'/><Value Type='Text'>abc</Value>" +
"</eq></Where></Query></View>";
ListItemCollection collListItem = oList.GetItems(camlQuery);
context.Load(collListItem,
items => items.IncludeWithDefaultProperties(
item => item.DisplayName));
context.ExecuteQuery();
return collListItem;
}
ListItem checkItem(string listname, string fileName)
{
ListItem result = null;
ListItemCollection collListItem =
getListItemCollectionFromSP(listname);
string itemName = fileName.Substring(0, 3);
foreach (ListItem oListItem in collListItem)
{
if (oListItem[OBJECTMETATADTA_ID].Equals(itemName))
{
{
// my business logic;
}
}
}
context.Dispose();
return result;
}
}
It would be great if I get some help on this Issue from any person who knowns about this.
Did you try with 'Eq' instead of 'eq' in your query? CAML query is case sensitive

How to extract Url elements from list item in C# windows form app

Here is the concept my C# list items contains
List<string> myList1 = new List<string>();
Urls some are:
http://www.google.com
http://www.google.com/maps
http://www.google.com/?parm=vlue
/www.google.com/
they are currently residing in a list variable myList1
Is there a way to identify each of the url elements like
Scheme:http
host:www.google.com
path:/maps
query:?parm=value
and set those elements as bool so if it is true do something if it is false do something else I don't even know where to start tried regex but not having any luck
Make the list into URI instances:
var uris = myList1.Select(u => new Uri(u));
http://msdn.microsoft.com/en-us/library/system.uri.aspx
Which will then give you access to the various properties, such as Scheme and Host.
Say I have this in my list (among other things):
http://www.google.co.uk/search.php?searchterm=a
I could get this into a Uri first:
var uris = myList1.Select(u => new Uri(u));
Now I want only those that are going to google.com and have a scheme of https...
var googleUris = uris.Where(u => u.Host.Contains("google") && u.Scheme.Equals("http"));
So I've now only got URIs that are going to Google and accessing it over https, great, but it's also in a URI object now, so what if I just want it back as a full URI path?
var fullURIsOfGoogleUris = googleUris.Select(u => u.AbsoluteUri);
This final list would now be, just strings (the full URIs you gave it in the first place).
You mentioned you want it as a "bool" value...well you can use Any() for this. Using my above example this would turn into one line of:
bool hasGoogleUris = myList1.Select(u => new Uri(u)).Any(u => u.Host.Contains("google") && u.Scheme.Equals("http"));
The above would give you a true or false value depending on whether that list contained a URI that contained google in it's host and accessing it over http.
Edited:
Sample code based on Arran's suggestion:
List<string> myList1 = new List<string>() { "http://www.google.com/?parm=vlue"};
var uris = myList1.Select(u => new Uri(u));
foreach (var uri in uris)
{
//"http"
var schema = uri.Scheme;
//www.google.com
var host = uri.Host;
//"?parm=vlue"
var query = uri.Query;
}
Adding some more info. Could be useful
Uri.IsWellFormedUriString(myURL, UriKind.RelativeOrAbsolute)
In your example:
IList<string> wellFormalteUriStrings = myList1.FindAll(url => Uri.IsWellFormedUriString(url, UriKind.Absolute));
List wellFormalteUriStrings would contain only the valid URL stings from myList1
Ref: MSDN

Lucene search not working

I have a function which searches some articles in the Sitecore content items and give me the value. So far I have build up my indexes and it is showing in my IndexViewer. But the return of the function is 0. I looked up this link: http://sitecoregadgets.blogspot.com/2009/11/working-with-lucene-search-index-in_25.html for more information.
protected IEnumerable<Item> ShowHomePageNews(int numOfArticles, string stringofCountries)
{
List<Item> items = new List<Item>();
Sitecore.Search.Index indx = SearchManager.GetIndex("newsArticles");
using (IndexSearchContext searchContext = indx.CreateSearchContext())
{
var db = Sitecore.Context.Database;
CombinedQuery query = new CombinedQuery();
QueryBase catQuery = new FieldQuery("countries", stringofCountries); //FieldName, FieldValue.
SearchHits results = searchContext.Search(catQuery); //Searching the content items by fields.
SearchResultCollection result = results.FetchResults(0, numOfArticles);
foreach (SearchResult i in result)
{
items = result
.Where(r => !r.Title.StartsWith("*"))
.Select(r => db.GetItem(new Sitecore.Data.ItemUri(r.Url).ToDataUri()))
.ToList();
//Lucene.Net.Documents.Field url = i.Document.GetField("_url");
//Sitecore.Data.ItemUri itemUri = new Sitecore.Data.ItemUri(url.StringValue());
//Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(itemUri.ToDataUri());
//items.Add(item);
}
}
return items;
}
Over here the result is 0. What I am doing wrond here?
This is the snapshot of what I am seeing in my IndexViewer:
EDIT:
I am passing a "NZ" in the 'catQuery' and I am getting the result back. Because in my index viewer I am seeing the Field Name = _name, which contains NZ in it. I got this part. However, I want my every field to be indexed. I am seeing only 3 fields in my IndexViewer: _url, _group & _name.
So your countries should be tokenized by the indexer. As a multilist, they will be tokenized by GUID. Searching for a single country by GUID with your code above should work. However, if you want to search for multiple countries, where any of the passed in countries can trigger a match, you need to structure your query differently.
CombinedQuery query = new CombinedQuery();
//apply other filters here to query if need be
//and country filter by creating a new clause (combinedquery) and "ORing" within it (QueryOccurance.Should)
CombinedQuery query3 = new CombinedQuery();
//here you would actually iterate over your country list
query3.Add(new FieldQuery("countries", country1GUID), QueryOccurance.Should);
query3.Add(new FieldQuery("countries", country2GUID), QueryOccurance.Should);
query.Add(query3, QueryOccurance.Must);

Categories

Resources