SharePoint 2010: Count ListItem Attachments using Client Object Model - sharepoint

Does anyone know how to read the number of attachments, and the names etc for a ListItem using the Client .Net Object model in SharePoint?
Thanks

// For getting the list item field information
public void LoadPropertyInfo()
{
using (context = new ClientContext(siteCollectionUrl))
{
spWeb = context.Web;
propertiesList = spWeb.Lists.GetByTitle(listName);
FieldCollection fields = propertiesList.Fields;
context.Load(fields);
SP.CamlQuery query = new SP.CamlQuery();
query.ViewXml = string.Format("<View><Query><Where><Eq><FieldRef Name=\"{0}\" /><Value Type=\"Text\">{1}</Value></Eq></Where></Query></View>", propertyID, PropertyIDValue);
listItems = propertiesList.GetItems(query);
context.Load(listItems);
context.ExecuteQueryAsync(GetRequestSucceeded, RequestFailed);
}
}
// Pass the item id here for getting the attachments
private void GetAttchmentCollection(string id)
{
string RedirectHost = string.Empty;
string Host = string.Empty;
context = SP.ClientContext.Current;
RedirectHost = serviceUrl + "_vti_bin/Lists.asmx";
BasicHttpBinding binding = new BasicHttpBinding();
if (System.Windows.Browser.HtmlPage.Document.DocumentUri.Scheme.StartsWith("https"))
{
binding.Security.Mode = BasicHttpSecurityMode.Transport;
}
binding.MaxReceivedMessageSize = int.MaxValue;
EndpointAddress endpoint = new EndpointAddress(RedirectHost);
ServiceReference1.ListsSoapClient oClient = new ServiceReference1.ListsSoapClient(binding, endpoint);
oClient.GetAttachmentCollectionCompleted += new EventHandler<ServiceReference1.GetAttachmentCollectionCompletedEventArgs>(oClient_GetAttachmentCollectionCompleted);
oClient.GetAttachmentCollectionAsync(listName, id);
}
Your can try this link too.
http://helpmetocode.blogspot.com/2011/11/managed-client-object-models-in.html

Related

Update/Change custom TaxonomyFieldValue in document library list in sharepoint using C# CSOM

list of documents thats contains custom taxonomy field column named subject.
Need to update subject of thousands records/documents.
Please any idea to update the taxonomy field such subject programtically using C# CSOM
Please try to use this method:
public void UpdateTaxonomyField(ClientContext ctx, List list,ListItem listItem,string fieldName,string fieldValue)
{
Field field = list.Fields.GetByInternalNameOrTitle(fieldName);
TaxonomyField txField = clientContext.CastTo<TaxonomyField>(field);
TaxonomyFieldValue termValue = new TaxonomyFieldValue();
string[] term = fieldValue.Split('|');
termValue.Label = term[0];
termValue.TermGuid = term[1];
termValue.WssId = -1;
txField.SetFieldValueByValue(listItem, termValue);
listItem.Update();
ctx.Load(listItem);
ctx.ExecuteQuery();
}
public static void UpdateListofLibraryHavingTaxonomyField()
{
string siteUrl = "http://abc:55555/sites/xyz/";
string libName = "Knowledge Repos";
string strTermGuid = "Your new/update term guid";
try
{
Dictionary<string, string> dictIdsSubjectsChange = ReadFromExcel();//Here to read all records (approx 2000 records) that we want to change
ClientContext clientContext = new ClientContext(siteUrl);
List list = clientContext.Web.Lists.GetByTitle(libName);
FieldCollection fields = list.Fields;
Field field = fields.GetByInternalNameOrTitle("Subject1");
ListItemCollection listItems = list.GetItems(CamlQuery.CreateAllItemsQuery());
clientContext.Load(listItems, items => items.Include(i => i["Subject1"], i => i["ID"]));
clientContext.Load(fields);
clientContext.Load(field);
clientContext.ExecuteQuery();
TaxonomyField txField = clientContext.CastTo<TaxonomyField>(field);
TaxonomyFieldValue termValue = null;
if (dictIdsSubjectsChange != null)
{
foreach (ListItem listItem in listItems)//Loop through all items of the document library
{
string strCurrentID = "0";
try
{
strCurrentID = listItem["ID"].ToString();
}
catch (Exception) { }
if (dictIdsSubjectsChange.ContainsKey(strCurrentID))//Checking to change ot not
{
termValue = new TaxonomyFieldValue();
termValue.Label = "Special Knowledge";
termValue.TermGuid = strTermGuid;
termValue.WssId = 246;
txField.SetFieldValueByValue(listItem, termValue);
listItem.Update();
clientContext.Load(listItem);
}
}
clientContext.ExecuteQuery();
}
}
catch (Exception ex) { }
}
}

Executing a site workflow in sharepoint from a console application

I am trying to execute a site workflow from a console application.When the code to execute the workflow runs, it thows an error
An unhandled exception of type 'Microsoft.SharePoint.Client.ServerException' occurred in Microsoft.SharePoint.Client.Runtime.dll
Additional information:
Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. "GetWorkflowInteropService new Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager()"
string userName = "username";
string password = "password";
string siteUrl = "https://share.example.com/sites/workflowsite";
string workflowName = "MyWorkflow";
using (ClientContext clientContext = new ClientContext(siteUrl))
{
SecureString securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);
clientContext.Credentials = new NetworkCredential(userName, securePassword);
Web web = clientContext.Web;
WorkflowAssociationCollection wfAssociations = web.WorkflowAssociations;
WorkflowAssociation wfAssociation = wfAssociations.GetByName(workflowName);
clientContext.Load(wfAssociation);
clientContext.ExecuteQuery();
WorkflowServicesManager manager = new WorkflowServicesManager(clientContext, web);
InteropService workflowInteropService = manager.GetWorkflowInteropService();
clientContext.Load(workflowInteropService);
clientContext.ExecuteQuery();
workflowInteropService.StartWorkflow(wfAssociation.Name, new Guid(), Guid.Empty, Guid.Empty, null);
clientContext.ExecuteQuery(
}
The code below for your reference:
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WorkflowServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
namespace CSOMStartWorkflow {
class Program {
static void Main(string[] args) {
Console.WriteLine("Enter the Office 365 Login Name");
string loginId = Console.ReadLine();
string pwd = GetInput("Password", true);
Console.WriteLine("Web Url:");
string webUrl = Console.ReadLine();
Console.WriteLine("List Name:");
string listName = Console.ReadLine();
Console.WriteLine("Workflow Name");
string workflowName = Console.ReadLine();
var passWord = new SecureString();
foreach (char c in pwd.ToCharArray()) passWord.AppendChar(c);
using (var ctx = new ClientContext(webUrl)) {
ctx.Credentials = new SharePointOnlineCredentials(loginId, passWord);
var workflowServicesManager = new WorkflowServicesManager(ctx, ctx.Web);
var workflowInteropService = workflowServicesManager.GetWorkflowInteropService();
var workflowSubscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
var workflowDeploymentService = workflowServicesManager.GetWorkflowDeploymentService();
var workflowInstanceService = workflowServicesManager.GetWorkflowInstanceService();
var publishedWorkflowDefinitions = workflowDeploymentService.EnumerateDefinitions(true);
ctx.Load(publishedWorkflowDefinitions);
ctx.ExecuteQuery();
var def = from defs in publishedWorkflowDefinitions
where defs.DisplayName == workflowName
select defs;
WorkflowDefinition workflow = def.FirstOrDefault();
if(workflow != null) {
// get all workflow associations
var workflowAssociations = workflowSubscriptionService.EnumerateSubscriptionsByDefinition(workflow.Id);
ctx.Load(workflowAssociations);
ctx.ExecuteQuery();
// find the first association
var firstWorkflowAssociation = workflowAssociations.First();
// start the workflow
var startParameters = new Dictionary<string, object>();
if (ctx.Web.ListExists(listName)) {
List list = ctx.Web.GetListByTitle(listName);
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection items = list.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
ctx.Load(items);
ctx.ExecuteQuery();
foreach (ListItem listItem in items) {
Console.WriteLine("Starting workflow for item: " + listItem.Id);
workflowInstanceService.StartWorkflowOnListItem(firstWorkflowAssociation, listItem.Id, startParameters);
ctx.ExecuteQuery();
}
}
}
}
Console.WriteLine("Press any key to close....");
Console.ReadKey();
}
private static string GetInput(string label, bool isPassword) {
Console.ForegroundColor = ConsoleColor.White;
Console.Write("{0} : ", label);
Console.ForegroundColor = ConsoleColor.Gray;
string strPwd = "";
for (ConsoleKeyInfo keyInfo = Console.ReadKey(true); keyInfo.Key != ConsoleKey.Enter; keyInfo = Console.ReadKey(true)) {
if (keyInfo.Key == ConsoleKey.Backspace) {
if (strPwd.Length > 0) {
strPwd = strPwd.Remove(strPwd.Length - 1);
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
Console.Write(" ");
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
}
} else if (keyInfo.Key != ConsoleKey.Enter) {
if (isPassword) {
Console.Write("*");
} else {
Console.Write(keyInfo.KeyChar);
}
strPwd += keyInfo.KeyChar;
}
}
Console.WriteLine("");
return strPwd;
}
}
}
Reference: Starting a SharePoint Online Workflow with the Client Side Object Model (CSOM)

Sharepoint: How to upload files with metadata including Taxonomy fields through web services

Being very new to SharePoint coding I have been assigned the task to create a prototype code to upload a file and setting the field values for that file that will show up when opening the sharepoint page with the file.
This has to be done from a remote machine and not the Sharepoint server itself so using the .Net objects for Sharepoint is out the question.
I quickly found out how to upload a file through the Sharepoint Web Service Copy.asmx:
void UploadTestFile() {
var file = #"C:\Temp\TestFile.doc";
string destinationUrl = "http://mysharepointserver/Documents/"
+ Path.GetFileName(file);
string[] destinationUrls = { destinationUrl };
var CopyWS = new Copy.Copy();
CopyWS.UseDefaultCredentials = true;
CopyWS.Url = "http://mysharepointserver/_vti_bin/copy.asmx";
CopyResult[] result;
byte[] data = File.ReadAllBytes(file);
FieldInformation mf1 = new FieldInformation {
DisplayName = "title",
InternalName = "title",
Type = FieldType.Text,
Value = "Dummy text"
};
FieldInformation mf2 = new FieldInformation {
DisplayName = "MyTermSet",
InternalName = "MyTermSet",
Type = FieldType.Note,
Value = "Test; Unit;"
};
CopyWS.CopyIntoItems(
"+",
destinationUrls,
new FieldInformation[] { mf1, mf2 },
data,
out result);
}
This code easily uploads any file to the target site but only fills the "title" field with info. The field MyTermSet in which I have added 3 terms allready - Test, Unit and Page - will not update with the values "Test;" and "Unit;".
Being very new to Sharepoint and me not grasping all the basics googling has told me that updating "File", "Computed" or "Lookup" fields does not work with the CopyIntoItems method, and MyTermSet being a Taxonomy field is - if I am correct - a Lookup field.
So how do I get MyTermSet updated with the values "Test;" and "Unit;" ?
I would really prefer If someone has a sample code on this. I have followed several hint-links but I am none the wiser. I have found no sample-code on this at all.
Have anyone made one single method that wraps it all? Or another method that takes in the destinationUrl from the file upload and updates the Term Set/Taxonomy field.
Puzzling together what I have found so far, I am now able to do as I wanted. But I would really like to be able to get the Taxonomy field GUIDs dynamically and NOT having to explicitly set them myself:
void UploadTestFile(string FileName, string DocLib, Dictionary<string, string> Fields = null) {
//Upload the file to the target Sharepoint doc lib
string destinationUrl = DocLib + Path.GetFileName(FileName);
string[] destinationUrls = { destinationUrl };
var CopyWS = new Copy.Copy();
CopyWS.UseDefaultCredentials = true;
CopyWS.Url = new Uri(new Uri(DocLib), "/_vti_bin/copy.asmx").ToString();
CopyResult[] result;
var data = File.ReadAllBytes(FileName);
CopyWS.CopyIntoItems(
"+",
destinationUrls,
new FieldInformation[0],
data,
out result);
if (Fields == null) return; //Done uploading
//Get the ID and metadata information of the fields
var list = new ListsWS.Lists();
list.UseDefaultCredentials = true;
var localpath = new Uri(DocLib).LocalPath.TrimEnd('/');
var site = localpath.Substring(0, localpath.LastIndexOf("/")); //Get the site of the URL
list.Url = new Uri(new Uri(DocLib), site + "/_vti_bin/lists.asmx").ToString(); //Lists on the right site
FieldInformation[] fiOut;
byte[] filedata;
var get = CopyWS.GetItem(destinationUrl, out fiOut, out filedata);
if (data.Length != filedata.Length) throw new Exception("Failed on uploading the document.");
//Dictionary on name and display name
var fieldInfos = fiOut.ToDictionary(x => x.InternalName, x => x);
var fieldInfosByName = new Dictionary<string, FieldInformation>();
foreach (var item in fiOut) {
if (!fieldInfosByName.ContainsKey(item.DisplayName)) {
fieldInfosByName.Add(item.DisplayName, item);
}
}
//Update the document with fielddata - this one can be extended for more than Text and Note fields.
if (!fieldInfos.ContainsKey("ID")) throw new Exception("Could not get the ID of the upload.");
var ID = fieldInfos["ID"].Value; //The ID of the document we just uploaded
XDocument doc = new XDocument(); //Creating XML with updates we need
doc.Add(XElement.Parse("<Batch OnError='Continue' ListVersion='1' ViewName=''/>"));
doc.Element("Batch").Add(XElement.Parse("<Method ID='1' Cmd='Update'/>"));
var methNode = doc.Element("Batch").Element("Method");
//Add ID
var fNode = new XElement("Field");
fNode.SetAttributeValue("Name", "ID");
fNode.Value = ID;
methNode.Add(fNode);
//Loop each field and add each Field
foreach (var field in Fields) {
//Get the field object from name or display name
FieldInformation fi = null;
if (fieldInfos.ContainsKey(field.Key)) {
fi = fieldInfos[field.Key];
}
else if (fieldInfosByName.ContainsKey(field.Key)) {
fi = fieldInfosByName[field.Key];
}
if (fi != null) {
//Fix for taxonomy fields - find the correct field to update
if (fi.Type == FieldType.Invalid && fieldInfos.ContainsKey(field.Key + "TaxHTField0")) {
fi = fieldInfos[field.Key + "TaxHTField0"];
}
else if (fi.Type == FieldType.Invalid && fieldInfosByName.ContainsKey(field.Key + "_0")) {
fi = fieldInfosByName[field.Key + "_0"];
}
fNode = new XElement("Field");
fNode.SetAttributeValue("Name", fi.InternalName);
switch (fi.Type) {
case FieldType.Lookup:
fNode.Value = "-1;#" + field.Value;
break;
case FieldType.Choice:
case FieldType.Text:
fNode.Value = field.Value;
break;
case FieldType.Note: //TermSet's
var termsetval = "";
var terms = field.Value.Split(';');
foreach (var term in terms) {
termsetval += "-1;#" + term + ";";
}
fNode.Value = termsetval.TrimEnd(';');
break;
default:
//..Unhandled type. Implement if needed.
break;
}
methNode.Add(fNode); //Adds the field to the XML
}
else {
//Field does not exist. No use in uploading.
}
}
//Gets the listname (not sure if it is the full path or just the folder name)
var listname = new Uri(DocLib).LocalPath;
var listcol = list.GetListCollection(); //Get the lists of the site
listname = (from XmlNode x
in listcol.ChildNodes
where x.Attributes["DefaultViewUrl"].InnerText.StartsWith(listname, StringComparison.InvariantCultureIgnoreCase)
select x.Attributes["ID"].InnerText).DefaultIfEmpty(listname).First();
//Convert the XML to XmlNode and upload the data
var xmldoc = new XmlDocument();
xmldoc.LoadXml(doc.ToString());
list.UpdateListItems(listname, xmldoc.DocumentElement);
}
Then I call it like this:
var fields = new Dictionary<string, string>();
fields.Add("Test", "Dummy Text");
fields.Add("MrTermSet", "Page|a4ba29c1-3ed5-47e9-b43f-36bc59c0ea5c;Unit|4237dfbe-22a2-4d90-bd08-09f4a8dd0ada");
UploadTestFile(#"C:\Temp\TestFile2.doc", #"http://mysharepointserver/Documents/", fields);
I would however prefer to call it like this:
var fields = new Dictionary<string, string>();
fields.Add("Test", "Dummy Text");
fields.Add("MrTermSet", "Page;Unit");
UploadTestFile(#"C:\Temp\TestFile2.doc", #"http://mysharepointserver/Documents/", fields);

SPQuery search doesn't work with "BeginsWith"

So, my problem is that my knowledge of CAML and Sharepoint is very poor.
Question: I need SPQuery for building query search, search text I have from textbox. I expect that my query returns me item(s) (for example, I type in textbox "Jo" and query returns me all items with surname "Johnson", or name "John", etc)
1)TextChanged works ok. I've check it, there is ok
2) SPGridView views items ok. Items from SPList I add to gridView - there are viewd by gridview.
3) But my query doesn't work. Please, help with links/advises
public class VisualWebPart1 : WebPart
{
SPSite site;
SPWeb web;
SPGridView gridView;
SPDataSource dataSource;
TextBox searchTextBox;
UpdatePanel panel;
SPList list;
SPList resultList;
string currentList;
// Visual Studio might automatically update this path when you change the Visual Web Part project item.
private const string _ascxPath = #"~/_CONTROLTEMPLATES/CRMSearchWebPart/VisualWebPart1/VisualWebPart1UserControl.ascx";
protected override void CreateChildControls()
{
gridView = new SPGridView();
searchTextBox = new TextBox();
panel = new UpdatePanel();
searchTextBox.AutoPostBack = true;
searchTextBox.Visible = true;
searchTextBox.Enabled = true;
searchTextBox.TextChanged += new EventHandler(searchTextBox_TextChanged);
gridView.Visible = true;
gridView.Enabled = true;
gridView.AutoGenerateColumns = false;
AddColumnToSPGridView("Surname", "Surname");
panel.UpdateMode = UpdatePanelUpdateMode.Conditional;
panel.ContentTemplateContainer.Controls.Add(searchTextBox);
panel.ContentTemplateContainer.Controls.Add(gridView);
Control control = Page.LoadControl(_ascxPath);
Controls.Add(control);
Controls.Add(panel);
}
protected override void Render(HtmlTextWriter writer)
{
panel.RenderControl(writer);
}
//Open WebSite with List "listName"
private void OpenWebSite(string listName)
{
site = SPContext.Current.Site;
web = site.OpenWeb();
list = web.Lists[listName];
}
//Add Column to gridView
private void AddColumnToSPGridView(string HeaderText, string Datafield)
{
SPBoundField boundField = new SPBoundField();
boundField.HeaderText = HeaderText;
boundField.DataField = Datafield;
gridView.Columns.Add(boundField);
}
//Build query for search; fieldName - Name of column of current List, searchQuery - our query
private string BuildQuery(string fieldRefName, string searchQuery)
{
string query = "";
switch (fieldRefName)
{
case "Surname":
query = "<Where><BeginsWith><FieldRef Name='Surname'/>" +
"<Value Type=Text>"+searchQuery+"</Value></BeginsWith></Where>";
break;
case "Name":
query = query = "<Where><BeginsWith><FieldRef Name='Name'/>" +
"<Value Type=Text>"+searchQuery+"</Value></BeginsWith></Where>";
break;
case "PassportNumber":
query = "<Where><BeginsWith><FieldRef Name='PassportNumber'/>" +
"<Value Type=Text>"+searchQuery+"</Value></BeginsWith></Where>";
break;
default: break;
}
return query;
}
// search in List for selected items and returns SPGridView
private void searchTextBox_TextChanged(object sender, EventArgs e)
{
dataSource = new SPDataSource();
string querySearch = searchTextBox.Text;
OpenWebSite("Surnames");
string query = BuildQuery("Surname", querySearch);
SPQuery spQuery = new SPQuery();
spQuery.ViewFields = "<FieldRef Name = 'Title'/><FieldRef Name = 'Surname'/><FieldRef Name = 'Name'/>";
spQuery.Query = query;
SPListItemCollection items = list.GetItems(query);
foreach (SPListItem item in items)
{
searchTextBox.Text += item["Surname"] + " ";
}
//resultList = web.Lists["TempSurnames"];
//resultList = AddItemsToSPList(resultList, items);
BindDataSource(dataSource, resultList);
//resultList = AddSPList("Result2", "Result list");
//resultList = AddItemsToSPList(resultList, items);
list = AddItemsToSPList(list, items);
//BindDataSource(dataSource, resultList);
BindDataSource(dataSource, list);
BindGridView(gridView, dataSource);
//var item = list.Items[3];
//var item = resultList.Items[1];
//searchTextBox.Text = item["Surname"].ToString();
//resultList.Delete();
}
//Binds datasource of existing gridView with SPDataSource
private void BindGridView(SPGridView gridview, SPDataSource datasource)
{
gridview.DataSource = datasource;
gridview.DataBind();
}
//Add SPListItem items to SPList
private SPList AddItemsToSPList(SPList spList, SPListItemCollection collection)
{
foreach (SPListItem item in collection)
{
var listItem = spList.AddItem();
listItem = item;
}
return spList;
}
//Binds existing SPDataSource to SPList
private void BindDataSource(SPDataSource spDataSource, SPList spList)
{
spDataSource.List = spList;
}
private SPList AddSPList(string listName, string listDescription)
{
OpenWebSite("Surnames");
SPListCollection collection = web.Lists;
collection.Add(listName, listDescription, SPListTemplateType.CustomGrid);
resultList = web.Lists[listName];
return resultList;
}
Update:
This part gives me an error:
SPListItemCollection items = list.GetItems(query);
foreach (SPListItem item in items)
{
searchTextBox.Text += item["Surname"] + " ";
}
System.ArgumentException: Value does not fall within the expected
range
You have to include the field Surname into the view fields of the query:
SPQuery query = // ...
query.ViewFields = "<FieldRef Name='Surname' />";
// ...
You can understand the view fields like the SELECT part of a SQL query.
Have you debugged your code to check the query string that is generated? Also, you have query = query = under the Name switch.
Also, you know that the switch is case sensitive, so ensure you enter your searchQuery option appropriately.

How to add multiple lookup value in sharepoint List.While adding item in sharepoint

My Task have multiple relateddocId for example RelatedDoc="3,5,2,6", now i need to add multiplevalue to the sharepoint lookup fields called related Document which is in task list. how to add this?
For ref see my code below
private static void CreateItem(SPWeb web, SPList TaskList, string FolderURL, string ItemName, string RelatedDoc)
{
var ParentURL = string.Empty;
if (!TaskList.ParentWebUrl.Equals("/"))
{
ParentURL = TaskList.ParentWebUrl;
}
SPListItem _taskList = TaskList.AddItem(ParentURL + FolderURL, SPFileSystemObjectType.File, null);
_taskList["Title"] = ItemName;
string DocName = "4,6,3,6";//Document ref id.
SPFieldLookupValue lookupvalue = new SPFieldLookupValue();
if (DocName != "")
lookupvalue = new SPFieldLookupValue(RelatedDoc, DocName);
_taskList["EYRelatedSharedDocument"] = lookupvalue;
_taskList.Update();
}
SPFieldLookupValueCollection documents = new SPFieldLookupValueCollection();
foreach ( ... )
{
documents.Add(new SPFieldLookupValue(documentId, documentTitle));
}
_taskList["EYRelatedSharedDocument"] = documents;
_taskList.Update();

Resources