I have the following code, which successfully gets the list, but the spListItems variable never seems to never yield any results, even though the spList reports having listitems.
Any Ideas???
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
ListItemCollection spListItems = null;
List spList = null;
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
CamlQuery caml = new CamlQuery();
// initilize our collections and vars
spList = clientContext.Web.Lists.GetByTitle("EclipseAppPages");
clientContext.Load<List>(spList);
clientContext.ExecuteQuery();
// do it again
spListItems = spList.GetItems(caml);
clientContext.Load<ListItemCollection>(spListItems);
clientContext.ExecuteQuery();
// loop items and populate model
foreach (ListItem l in spListItems)
{
model.Add(l);
}
}
}
Edit 18-09: A little bit more info into this, this code is hosted inside a 'autohosted' mvc app for sharepoint. I am accessing the HostWeb from my AppWeb, my first conclusion would be permissions, however the fact that im getting the list back, and interestingly when i debug the variable the spListItems has an item count of > 0 but for some reason the context ISNT lazy loading the values.
Turns out it was app permissions, I found the solution to this, trying to find a solution to a query string filter issue.
If you get the same problem, go into your AppParts AppManifest.xml and add the following node:
<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web"
Right="FullControl" />
</AppPermissionRequests>
Alternatively you can do this via the visual studio wizard, double click your AppManifest file, goto permisions tab, Scope is 'Web', Permission 'Choose relavent permission'.
For more info on app permissions goto http://msdn.microsoft.com/en-us/library/fp179892(office.15).aspx
The reason that the result of your query is empty is that there CamlQuery object does not have ViewXml or Query property value.
Read the following article on how to query SharePoint Lists. http://msdn.microsoft.com/en-us/library/ff798388.aspx
Also, Use RowLimit & ViewFields properties to limit the results, for performance considerations.
alternatively you can use Linq to SharePoint if you are comfortable with that.
Related
I am trying to retrieve all of the items in a list from a SharePoint site. The fields are titled "Review Level Title", "Reviewer IDs", and "Review Level Priority". What I'm trying to do is to get the information from all three fields seperately, put them into the object I created, and then return the list with all of the objects I have created for each SharePoint item.
I have researched a lot on how to access this information from the SharePoint site, but I can not get it to work. Here is what I have created so far:
public List<OperationsReviewLevel> Get()
{
var operationsReviewLevels = new List<OperationsReviewLevel>();
ClientContext context = new ClientContext(ConfigurationManager.AppSettings["SharePointEngineeringChangeRequest"]);
var SPList = context.Web.Lists.GetByTitle("Review Levels");
CamlQuery query = new CamlQuery();
ListItemCollection entries = SPList.GetItems(query);
context.Load(entries);
context.ExecuteQuery();
foreach(ListItem currentEntry in entries)
{
operationsReviewLevels.Add(new OperationsReviewLevel(currentEntry["Review Level Title"].ToString(), currentEntry["Reviewer IDs"].ToString(), (int)currentEntry["Review Level Priority"]));
}
return operationsReviewLevels;
}
Whenever I try this code, I receive an error saying:
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: 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.
I can not find any solutions to this error (in my scenario) online, and was wondering if anyone could see what I am doing wrong in this scenario.
Thanks everyone!
After reading the comment from Alessandra Amosso under my question, I ended up debugging entries. It took a lot of digging in the debugger, but I was able to find what the field names were being retrieved as. Debugging your ListItemCollection, if you go into Data, then any entry there, and then into FieldValues, you can see what each field value should be retrieved as.
In my case, all spaces were replaces with _x0020_ and the word priority was cut to just priorit due to length of the field name.
With this, I was able to change my foreach loop to:
foreach (ListItem currentEntry in entries)
{
operationsReviewLevels.Add(new OperationsReviewLevel(currentEntry["Review_x0020_Level_x0020_Title"].ToString(), currentEntry["Reviewer_x0020_IDs"].ToString(), Convert.ToInt32(currentEntry["Review_x0020_Level_x0020_Priorit"].ToString())));
}
And it now works properly.
Hope this helps anyone in the future!
Guess you're using SharePoint online, SharePoint online will remove the field special characters as staticname when creating fields, for example: Review Level Title will be ReviewLevelTitle.
Here is my test code.
foreach (ListItem currentEntry in entries)
{
Console.WriteLine(currentEntry["ReviewLevelTitle"].ToString()+'-'+ currentEntry["ReviewerIDs"].ToString()+'-'+ currentEntry["ReviewLevelPriority"]);
//operationsReviewLevels.Add(new OperationsReviewLevel(currentEntry["Review Level Title"].ToString(), currentEntry["Reviewer IDs"].ToString(), (int)currentEntry["Review Level Priority"]));
}
If you're not using SharePoint online,make sure the fields match also.
In SharePoint Online site via my Office 365 account, I've added a column - "CustomerId" to my documents. I want to find all documents with CustomerId of 102 in C# (not in JavaScript).
So far, I'm able to get all files under a folder
var files = graphClient.Sites[siteId].Drive.Items[driveItemId]
.Children.Request().GetAsync().Result;
Or see the same result in Graph Explorer
https://graph.microsoft.com/v1.0/sites/{siteId}/drive/items/{driveItemId}/children
but I haven't figured out the correct syntax to get all documents (driveIems) using the custom column filter condition in C# or in Graph Explorer. Examples of things I've tried:
In C#
var files = graphClient.Sites[siteId].Drive.Items[driveItemId]
.Search("fields/CustomerId eq 102").Request().GetAsync().Result;
In Graph Explorer
https://graph.microsoft.com/v1.0/sites/{siteId}/drive/items/{driveItemId}/search(q='CustomerId eq 102')
Hope someone can help me out on this.
Update:
Previously I got the driveItemId from
var customerFolder = graphClient.Sites[siteId].Drive.Root
.ItemWithPath("CustomerGroup/IndustryGroup").Request().GetAsync().Result;
string driveItemId = customerFolder.Id;
I see I can get a ListItem
var customerFolder = graphClient.Sites[siteId].Drive.Root
.ItemWithPath("CustomerGroup/IndustryGroup").Request()
.Expand(d => d.ListItem).GetAsync().Result;
but I only found a list ID of "4" from customerFolder.ListItem.Id
How shall I get a list ID so that I can use it in graphClient.Sites[siteId].Lists[listId]?
I would suggest to utilize the following query:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?filter=fields/CustomerId eq 123&expand=driveItem
Explanation:
filter items in a list via filter query option
return associated drive items for a list item via expand query option
Here is an example for msgraph-sdk-dotnet:
var request = await graphClient.Sites[siteId].Lists[listId].Items.Request().Filter("fields/CustomerId eq 123").Expand(item => item.DriveItem).GetAsync();
foreach (var item in request)
{
Console.WriteLine(item.DriveItem.WebUrl);
}
Update
The underlying document library list (along with its properties) for a drive could be retrieved like this:
var list = await graphClient.Sites[siteId].Drive.List.Request().GetAsync();
Console.WriteLine(list.Id); //gives SharePoint List Id
Note: https://graph.microsoft.com/beta/sites/{site-id}/drive
endpoint returns the default drive (document library) for this site
Reference
Working with SharePoint sites in Microsoft Graph
I'm hoping to be able to append to the V3Comments (Append-Only Comments) column on a Sharepoint list item programmatically using Microsoft.SharePoint.Client.
I'm using a sequence similar to:
using (ClientContext context = new ClientContext("path_to_site"))
{
List list = context.Web.Lists.GetByTitle("list_name");
CamlQuery query = new CamlQuery();
ListItemCollection list_items = list.GetItems(query);
context.Load(list_items);
context.ExecuteQuery();
ListItem list_item = list_items[0];
list_item["V3Comments"] = "New comment.";
list_item.Update();
context.ExecuteQuery();
}
When I attempt to do this, the following InnerException is thrown:
Field or property "AttachmentFiles" does not exist.
Any pointers on what I need to get this working would be useful.
The list I am using had attachments enabled (despite not actually being used). After disabling the attachments, and leaving it for some time, it works as intended.
I wish I could explain the reason for this, but it would be pure speculation.
I've no idea how this would be done for a list with attachments.
Background
We have a custom developed installed .WSP on a SharePoint 2007 environment and have been in the process of upgrading to 2010. With the upgrade the custom event trigger no longer worked so trying to update and make it work in 2010. But I am running into one issue. Original developers no longer here and I've been the lucky one to have to figure this one out without much of a background with SP Dev.
Goal
When a new list item is created trigger event. Within event, create a shared folder using Item Name and return url, create a wiki-page using item name and include shared document link and return url to wiki page. Part three is update newly created list item with the New Folder url and Wiki Page URL.
Issue
I've gotten the first two parts working but so far have been unable to update the newly created list item with the new Links. I'm able to get the links. I've tried all the basic stuff for updating the list that I have been able to find online with no luck. Nothing to complicated(or so I think). But code is included below. VS is not installed on the server so unable to run debug mode, I don't have direct access to the server. When you create the item there are no client/user side error. Haven't been able to find a log file that has any, that is if it collects errors if the script were to fail out.
Initiation of the Event
public class CreateWikiAndFolder : Microsoft.SharePoint.SPItemEventReceiver
{
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
//this.DisableEventFiring();
base.EventFiringEnabled = false;
string sUrlOfWikiPage = string.Empty;
string sUrlOfNewFolder = string.Empty;
string sSubsiteRUL = string.Empty;
string sCurrentItemTitle = properties.ListItem["Title"].ToString();
string sWikiListName = "TR Wikis";
string sDocLibName = "Shared Documents";
string sTRListID = "TR Status";
if (sTRListID.ToUpper().Equals(properties.ListTitle.ToString().ToUpper()))
{
//Create the Folder
sUrlOfNewFolder = CreateFolder(properties.ListItem.Web, sDocLibName, sCurrentItemTitle);
//Create the Wiki
string ItemDispFormUrl = String.Concat(properties.ListItem.Web.Url, "/", properties.ListItem.ParentList.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url, "?ID=", properties.ListItem.ID.ToString());
sUrlOfWikiPage = CreateWiki(properties.ListItem.Web, sWikiListName, sCurrentItemTitle, ItemDispFormUrl, sUrlOfNewFolder);
//Update the current TR Item
//Have tried. properties.ListItem["WikiURL"] = sUrlOfWikiPage + ", " + "Wiki";
SPListItem myListItem = properties.ListItem;
SPFieldUrlValue shareFolderURLValue = new SPFieldUrlValue();
shareFolderURLValue.Description = "Shared Folder";
shareFolderURLValue.Url = sUrlOfNewFolder ;
myListItem["SharedFolder"] = shareFolderURLValue;
//I've tried each one separate and together to no luck
myListItem.UpdateOverwriteVersion();
myListItem.Update();
//properties.ListItem.UpdateOverwriteVersion();
}
base.EventFiringEnabled = true;
}
}
}
Note that this is the last thing needed to be figured out for our upgrade.
Got it working. I did both of these at the same time so I'm not sure if it was the combination of both or only one of the items. But one I removed the myListItem.UpdateOverwriteVersion(); line and surrounded the item updated with web.AllowUnsafeUpdates being set to true before and then back to false afterwards.
Also as a note to others, you need to save the properties.ListItem to its own SPListItem which you then update versus trying to manipulate the values at the properties.ListItem["Attribute"], and then update the properties.ListItem.Update. SharePoint doesn't allow the latter option so you have to save to an independent SPListItem, and then modify and update that one. This might not be the best SharePoint lingo, but that is what needs to be done.
Hopefully you can help. I am working on a Browser Enabled InfoPath 2010 form that lives in a Document Library on a SharePoint site (2007 and 2010). In this form there is a repeating table with data that needs to be captured for reporting purposes. The solution I have chosen is to use the built in SharePoint lists.asmx Web Service to write the lines in the repeating table to a separate list on the sane SharePoint site, in the same site collection. I used the steps here, http://msdn.microsoft.com/en-us/library/cc162745(v=office.12).aspx, as my baseline.
I have gotten everything set up and working when run directly from the InfoPath form client site. The form opens and, on submit, the rows in the repeating table are written to the SharePoint list without any problems. However, once I deploy the form through Central Admin and test, none of the rows in the repeating table are getting written to the list. There are no errors or anything to indicate a problem with the code, and a boolean field used to indicate whether or not a row has been uploaded is set to true.
My first thought is that there is a problem with the permissions somewhere. Maybe when the service is called from client side it passes my credentials but when run from the server through the Document Library it's using something different? Shouldn't it use the credentials that are used to gain access to the SharePoint (which are also my AD credentials)? Is there a way to specify the use of the current users AD credentials when calling the lists.asmx web service in the code?
Anyway, not really sure where else to go with this. Any searching I do comes up with the same how two documentation on submitting to a SharePoint list in general. Any help would be greatly appreciated. Below is the code I am using to accomplish this.
if (MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:ShippingInformation/my:ShipDate", NamespaceManager).Value != "")
{
// If Ship Date is not blank, upload items in Material used to SP List where ForQuote is False
// Quote Number, RMA Number, Ship Date, Unit S/N,
// Create a WebServiceConnection object for submitting
// to the Lists Web service data connection.
WebServiceConnection wsSubmit =
(WebServiceConnection)this.DataConnections["Material Web Service Submit"];
//Create XPathNodeIterator object for the new Material Lines
XPathNodeIterator MaterialLines = this.MainDataSource.CreateNavigator().Select("/my:myFields/my:RepairQuote/my:QuoteLines/my:QuoteLine", NamespaceManager);
int lineCount = 0;
foreach (XPathNavigator NewLines in MaterialLines)
{
lineCount += 1;
if (NewLines.SelectSingleNode(".//my:ForQuote", NamespaceManager).Value == "false" && NewLines.SelectSingleNode(".//my:LineSubmitted", NamespaceManager).Value == "false")
{
// Set the values in the Add List Item Template
// XML file using the values in the new row.
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='Title']", NamespaceManager).SetValue(NewLines.SelectSingleNode(".//my:lineItem", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='RMANumber']", NamespaceManager).SetValue(MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:EntitlementContainer/my:RMANumber", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='UnitSerialNumber']", NamespaceManager).SetValue(MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:EntitlementContainer/my:serialNumber", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='ShipDate']", NamespaceManager).SetValue(MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:ShippingInformation/my:ShipDate", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='OrderType']", NamespaceManager).SetValue(MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:RepairQuote/my:orderType", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='QuoteNumber']", NamespaceManager).SetValue(MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:RepairQuote/my:quoteNumber", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='LineQuantity']", NamespaceManager).SetValue(NewLines.SelectSingleNode(".//my:lineQuantity", NamespaceManager).Value);
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/Field[#Name='LineNumber']", NamespaceManager).SetValue(lineCount.ToString());
// Set the value of Cmd attribute to "New".
DataSources["AddListItemTemplate"].CreateNavigator().SelectSingleNode("/Batch/Method/#Cmd", NamespaceManager).SetValue("New");
// Submit the new row.
wsSubmit.Execute();
NewLines.SelectSingleNode(".//my:LineSubmitted", NamespaceManager).SetValue("true");
}
}
}
I'm unsure why the code doesn't work when you deploy and call the lists web service in code. However I would suggest you to try debugging it to get to the root of the problem:
Step by Step – Debug InfoPath 2010 Forms Deployed on SharePoint 2010 Using Visual Studio 2010
Please try this out and step through it to see if it goes through the code as expected.
Well, I am not sure if it is the answer per se, but I believe the problem was related to security on the site. I got around this by using the SharePoint Object Model instead of the web service to create the list items (See http://www.bizsupportonline.net/browserforms/how-to-use-sharepoint-object-model-submit-data-infopath-browser-form-sharepoint-list.htm). With the SharePoint Object Model I am able to use AllowUnsafeUpdates. Also, where it took me quite a bit of time to get the web service set up, including the data connections, CAML file, etc. This way, however, only took a few minutes. Lesson learned, use the SharePoint Object Model if at all possible.
foreach (XPathNavigator NewLines in MaterialLines)
{
lineCount += 1;
if (NewLines.SelectSingleNode(".//my:ForQuote", NamespaceManager).Value == "false" && NewLines.SelectSingleNode(".//my:LineSubmitted", NamespaceManager).Value == "false")
{
using (SPSite site = SPContext.Current.Site)
{
if (site != null)
{
using (SPWeb web = site.OpenWeb())
{
// Turn on AllowUnsafeUpdates on the site
web.AllowUnsafeUpdates = true;
// Update the SharePoint list based on the values
// from the InfoPath form
SPList list = web.GetList("/Lists/InfoPathRtpItems");
if (list != null)
{
SPListItem item = list.Items.Add();
item["Title"] = NewLines.SelectSingleNode(".//my:lineItem", NamespaceManager).Value;
item["RMANumber"] = MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:EntitlementContainer/my:RMANumber", NamespaceManager).Value;
item["UnitSerialNumber"] = MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:EntitlementContainer/my:serialNumber", NamespaceManager).Value;
item["ShipDate"] = MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:ShippingInformation/my:ShipDate", NamespaceManager).Value;
item["OrderType"] = MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:RepairQuote/my:orderType", NamespaceManager).Value;
item["QuoteNumber"] = MainDataSource.CreateNavigator().SelectSingleNode("./my:myFields/my:RepairQuote/my:quoteNumber", NamespaceManager).Value;
item["LineQuantity"] = NewLines.SelectSingleNode(".//my:lineQuantity", NamespaceManager).Value;
item["LineNumber"] = lineCount.ToString();
item.Update();
}
// Turn off AllowUnsafeUpdates on the site
web.AllowUnsafeUpdates = false;
// Close the connection to the site
web.Close();
}
// Close the connection to the site collection
site.Close();
}
}
}