How to read a Choice Field from Sharepoint 2010 Client Object Model - object

I'm using Sharepoint 2010 Object Model. I'm trying to retrive the content of a Custom List. Everything works fine except if when I try to retrieve a Choice Field.
When I try to retrieve the choice field, I got an PropertyOrFieldNotInitializedException exception...
Here is the code I'm using:
ClientContext clientContext = new ClientContext("https://mysite");
clientContext.FormsAuthenticationLoginInfo = new FormsAuthenticationLoginInfo("aaa", bbb");
clientContext.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
List list = clientContext.Web.Lists.GetByTitle("mylist");
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View/>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems)
{
listBoxControl1.Items.Add(listItem["Assigned_x0020_Company"]);
}

var list = clientContext.Web.Lists.GetByTitle(listName);
clientContext.ExecuteQuery();
clientContext.Load(list.Fields, fields => fields.Include(field => field.Title));
clientContext.ExecuteQuery();
foreach (var field in list.Fields)
{
if (field.Title == "YourChoiceFieldName")
{
clientContext.Load(field);
clientContext.ExecuteQuery();
return ((FieldChoice) field).Choices;
}
}

When you read a ChoiceField in code , It will return a string array of selected choices. For example if you entered in the choice box of the column when you create it : "Company 1" ,"Company 2","Company 3 " , if user select option 1 & 2 , then returned array in code will contain "Company 1" and "Company 2" .You must change the code to the below :
foreach (ListItem listItem in listItems)
{
string[] values = (string[])listItem["Assigned_x0020_Company"];
foreach(string s in values)
{
listBoxControl1.Items.Add(s);
}
}

Related

Is there a Sharepoint API to get nested directory structure for a particular folder at once within a site?

Is there a Sharepoint API to get entire content of files/folders for a particular folder at once ?
I don't want to use GetFolderByServerRelativePath recursively.
If don't want to use GetFolderByServerRelativePath, you can use CSOM with CAML Query like this:
string password = "pwd";
string account = "user#Tenant.onmicrosoft.com";
var secret = new SecureString();
foreach (char c in password)
{
secret.AppendChar(c);
}
using (ClientContext ctx = new ClientContext("https://Tenant.sharepoint.com/sites/sitename"))
{
ctx.Credentials = new SharePointOnlineCredentials(account,secret);
Web web = ctx.Web;
ctx.Load(web);
ctx.ExecuteQuery();
List list = web.Lists.GetByTitle("Documents");
ctx.Load(list);
ctx.ExecuteQuery();
Folder folder = web.GetFolderByServerRelativeUrl(web.ServerRelativeUrl + "/shared%20documents/");
ctx.Load(folder);
ctx.ExecuteQuery();
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = #"<View Scope='RecursiveAll'>
<Query>
</Query>
</View>";
camlQuery.FolderServerRelativeUrl = folder.ServerRelativeUrl;
ListItemCollection listItems = list.GetItems(camlQuery);
ctx.Load(listItems);
ctx.ExecuteQuery();
foreach (var item in listItems)
{
Console.WriteLine(item.FieldValues["FileRef"].ToString());
}
}
will return all folders/subfolders/files together, hopefully, this is what you need.

SharePoint 2013 update fieldvalue

I have sharepoint list I have added a column "DistributionId" as a single line of text. I can see it in the fieldvalues when I debug. I can see it being set by the line listItem.FieldValues["DistributionId"] = "test";. However this is not updated in SharePoint and reverts to a blank value when the execute query is fired underneath. Also value is not set in SharePoint when checked directly. Any idea what I am doing wrong?
using (ClientContext clientContext = new ClientContext(SpEndPointUri))
{
Site site = clientContext.Site;
Web web = clientContext.Web;
List list = clientContext.Web.Lists.GetByTitle(library);
CamlQuery query = new CamlQuery();
query.ViewXml = #"<View><Query><Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>" + documentId + #"</Value></Eq></Where></Query></View>";
ListItemCollection items = list.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
clientContext.Load(items, ic => ic.Include(i => i, i => i["DisplayName"], i => i["Id"], i => i["HasUniqueRoleAssignments"]));
clientContext.ExecuteQuery();
ListItem listItem = items[0];
clientContext.Load(listItem);
clientContext.ExecuteQuery();
listItem.FieldValues["DistributionId"] = "test";
listItem.Update();
clientContext.ExecuteQuery();
clientContext.Load(listItem);
clientContext.ExecuteQuery();
}
Use ListItem.Item property to set field value instead. ListItem.FieldValues property is used only for getting a collection of key/value pairs containing the names and values for the fields of the list item.
How to update ListItem field value:
var list = ctx.Web.Lists.GetByTitle(listTitle);
var listItem = list.GetItemById(listItemId);
listItem[fieldName] = fieldValue;
listItem.Update();
ctx.ExecuteQuery();

Retrieve All Documents from all Subfolders in a Document Library - CSOM

I am using the client side object model approach C# in order to retrieve all list items from a document library containing sub folders. I checked out the MSDN documentation and I am stuck as to why I cannot get the field property, or if I am even doing this right.
NetworkCredential credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
ClientContext clientcontext = new ClientContext(Resources.defaultSPSite);
clientcontext.Credentials = credentials;
//Load Libraries from SharePoint
//Web site = clientcontext.Web;
clientcontext.Load(clientcontext.Web.Lists);
clientcontext.ExecuteQuery();
//List sharedDocumentsList = clientcontext.Web.Lists.GetByTitle("TestLDOCS");
//CamlQuery camlQuery = new CamlQuery();
//camlQuery.ViewXml = #"<View Scope='Recursive'><Query></Query></View>";
foreach (List list in clientcontext.Web.Lists)
{
clientcontext.Load(list);
clientcontext.ExecuteQuery();
//list.TemplateFeatureId.ToString().Equals("") &&
string baseType = list.BaseType.ToString();
string listTitle = list.Title.ToString();
if (list.BaseType.ToString().Equals("DocumentLibrary", StringComparison.InvariantCultureIgnoreCase) && list.Title.ToString().Equals("TestLDOCS", StringComparison.InvariantCultureIgnoreCase))
{
foreach (Folder subFolder in list.RootFolder.Folders)
{
foreach (File f in subFolder.Files)
{
Console.WriteLine((string) f.Title);
}
}
}
}
}
The error that I am receiving is that the "foreach(File f in subFolder.Files)" collection may not be initialized error. Is there anyway to get the field values of all documents in every subfolder within a document library using CSOM?
I know you can strongly type the field values as well with a list item ie (listItem["fieldName"]). Should I go this route instead?
Some recommendations:
1) Prefer ClientRuntimeContext.LoadQuery method to load a specific lists, for example:
var lists = ctx.LoadQuery(ctx.Web.Lists.Where(l => l.BaseType == BaseType.DocumentLibrary));
ctx.ExecuteQuery();
2) Since SharePoint SCOM supports Request Batching it is recommended to minimize the number of requests to the server. The following example demonstrates how to perform a single request to the server in order to load all files from document libraries:
foreach (var list in lists)
{
var items = list.GetItems(CreateAllFilesQuery());
ctx.Load(items, icol => icol.Include(i => i.File));
results[list.Title] = items.Select( i=>i.File);
}
ctx.ExecuteQuery();
3) Prefer to load all files via CAML query as demonstrated below:
public static CamlQuery CreateAllFilesQuery()
{
var qry = new CamlQuery();
qry.ViewXml ="<View Scope=\"RecursiveAll\"><Query><Where><Eq><FieldRef Name=\"FSObjType\" /><Value Type=\"Integer\">0</Value></Eq></Where></Query></View>";
return qry;
}
Then the following example will return all the files in library:
var items = list.GetItems(CreateAllFilesQuery());
ctx.Load(items, icol => icol.Include(i => i.File));
ctx.ExecuteQuery();
var files = items.Select( i=>i.File).ToList();
It is more optimized way of loading specific lists from performance perspective
Complete example
How to load all files from document libraries using SharePoint CSOM:
using (var ctx = new ClientContext(webUri))
{
var results = new Dictionary<string, IEnumerable<File>>();
var lists = ctx.LoadQuery(ctx.Web.Lists.Where(l => l.BaseType == BaseType.DocumentLibrary));
ctx.ExecuteQuery();
foreach (var list in lists)
{
var items = list.GetItems(CreateAllFilesQuery());
ctx.Load(items, icol => icol.Include(i => i.File));
results[list.Title] = items.Select( i=>i.File);
}
ctx.ExecuteQuery();
//Print results
foreach (var result in results)
{
Console.WriteLine("List: {0}",result.Key);
foreach (var file in result.Value)
{
Console.WriteLine("File: {0}", file.Name);
}
}
}
foreach (List list in clientcontext.Web.Lists)
{
clientcontext.Load(list);
clientcontext.ExecuteQuery();
//list.TemplateFeatureId.ToString().Equals("") &&
string baseType = list.BaseType.ToString();
string listTitle = list.Title.ToString();
if (list.BaseType.ToString().Equals("DocumentLibrary", StringComparison.InvariantCultureIgnoreCase) && list.Title.ToString().Equals("TestLDOCS", StringComparison.InvariantCultureIgnoreCase))
{
foreach (Folder subFolder in list.RootFolder.Folders)
{
clientcontext.Load(subFolder.Files);
clientcontext.ExecuteQuery();
foreach (File f in subFolder.Files)
{
Console.WriteLine((string) f.Title);
}
}
}
}
}

Add values to a list contains a Lookup Field

I have a list named "Designation" that contains a Designation Code and Designation Name.
I have another list named "Employee" that contains Employee Name and Designation Name (as a Lookup Field).
I am able to insert values to "Employee" list using the following code.
protected void AddEmp(object sender, EventArgs e)
{
string emp_name = txtEmployeeName.Text;
string emp_designation = ddlDesignation.SelectedValue;
using (SPSite site = new SPSite("My Site"))
{
using (SPWeb web = site.OpenWeb())
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
web.AllowUnsafeUpdates = true;
SPList splist_employees = web.Lists["Employee"];
SPList splist_designations = web.Lists["Designations"];
SPListItemCollection splc_items = splist_employees.Items;
SPListItem spli_item = splc_items.Add();
SPFieldLookup lookup = splist_employees.Fields["Designated"] as SPFieldLookup;
string fieldName = lookup.LookupField;
spli_item["Employee Name"] = emp_name;
spli_item[fieldName] = GetLookFieldIDS(emp_designation, splist_designations);
spli_item.Update();
});
}
}
}
public static string GetLookFieldIDS(string lookupValues, SPList lookupSourceList)
{
string id = string.Empty;
SPFieldLookupValueCollection lookupIds = new SPFieldLookupValueCollection();
SPQuery query = new Microsoft.SharePoint.SPQuery();
query.Query = "<Where><Eq><FieldRef Name='Designation' /><Value type='Text'>"+lookupValues + "</Value></Eq></Where>";
SPListItemCollection listItems = lookupSourceList.GetItems(query);
foreach (Microsoft.SharePoint.SPListItem item in listItems)
{
id = item.ID.ToString();
}
return id;
}
Here I have given the field name as 'Designation' inside the query.
But, I want to find the field name based on the value given from the user end instead of hard-coding the field name as 'Designation'.
Any help is greatly appreciated. Thanks in advance.
Not sure about your request but, you could pass SPFieldLookup.LookupField property to your GetLookFieldIDS method and use that variable instead of "Designation"
spli_item[fieldName] = GetLookFieldIDS(emp_designation, splist_designations, lookup.LookupField);

How to access List Items in a list

I'm trying to display the ListItems in a gridview.
Please help me in finding a way to access the list items.
using (SPSite site = new SPSite("http://mysitehere......"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["TestList"];
.......
.......
}
}
Please help me in accessing the list item values.
The below code should do the trick, get the full article from msdn here
using (SPSite site = new SPSite("http://mysitehere......"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["TestList"];
SPListItemCollection collListItems = list.Items;
foreach (SPListItem oListItem in collListItems)
{
string value = SPEncode.HtmlEncode(oListItem["Field1_Name"]);
// do something with value
}
}
}
You may use any of the below:
SPList list;
foreach (SPListItem item in list.Items)
{
string title = item["Title"];
}
SPQuery query = new SPQuery();
query.ViewFields = "<FieldRef Name='Title'/>";
SPListItemCollection items = list.GetItems(query);
foreach (SPListItem item in list.Items)
{
string title = item["Title"];
}
for (int i = 0; i < list.Items.Count; i++ )
{
string title = list.Items[i]["Title"];
}
From the performance point of view, I suggest using the SP Query as then you can specify which fields to fetch and whether or not to fetch any associated metadata with the list items. This results in fewer db calls.
Kind regards,
Use SPDataSource to display list items in a grid view, i.e. create and configure an SPDataSource object and bind it to a SPGridView control.
For displaying items in a gridview (if you don't want to use SPGridView), I would use the GetDataTable method, instead of using a foreach loop as many of the answers do.
if (items.Count > 0)
{
DataTable dt = items.GetDataTable();
GridView1.DataSource = dt;
GridView1.DataBind();
}
Well, I haven't done any sharepoint work, but I believe you can use:
foreach (SPListItem item in list.Items)
or
foreach (SPListItem item in list.GetItems(view)) // or query
or access by index or guid:
SPListItem item = list.Items[10];
SPListItem item = list.Items[guid];
The SPQuery approach as suggested by unknown(yahoo) is the way to go, however you should remember that the default rowlimit of SPQuery is 100:
try
{
using (SPSite site = new SPSite(theURL))
{
SPWeb web = site.OpenWeb();
SPList list = web.Lists["TheNameOfTheList"];
//search each ListItem where the date is after 1/1 2009
SPQuery query = new SPQuery();
//the default is 100, which is less then the expected max
query.RowLimit = 500;
// The U2U CAML Query builder rules :-)
query.Query = "<Where><Gt><FieldRef Name='StartDate' /><Value Type='DateTime'>";
query.Query += "2009-01-01T00:00:00Z</Value></Gt></Where>";
SPListItemCollection resultset = list.GetItems(query);
foreach (SPListItem item in resultset)
{
// do something
}
}
}
If you´re using .NET 3.5 I would recommend using the linq datasource together with the spgridview to bind splistitems to a gridview. Saves you a lot of time.
I have an example of this on my blog.
To display images you have to get the url of the image. Here is an example of that:
SPListItem item = GetItem();
string imagefieldhtml = item["NameOfImageField"].ToString();
ImageFieldValue imagefield = new ImageFieldValue(imagefieldhtml);
var url = imagefield.ImageUrl;
The url variable will now hold the image url.
Ok, I have solved the above issue. In my case I did not need to use the SPEncode.HTML, so I have commented out everything that's not needed. Here is the fixed code if anyone else needs it:
using (SPSite site3 = SPContext.Current.Site)
{
using (SPWeb web2 = site3.OpenWeb())
{
// SPWeb site3 = SPContext.Current.Site.RootWeb;
SPList list2 = web2.Lists["Configuration"];
SPListItemCollection collListItems = list2.Items;
foreach (SPListItem oListItem in list2.Items)
{
//string value = SPEncode.HtmlEncode.ToString(oListItem["List name"]);
string valueListName = oListItem["List name"].ToString();
string valueListURL = oListItem["List URL"].ToString();
}
}
}

Resources