I am in the process of creating a massive SSIS project to move the data from a series of Sharepoint Lists to a new Dynamics CRM Implementation (On-line). The SSIS package uses an OData Source to pull the data from the lists.
There are two columns on my list that do not show up on the OData call. These two columns have Multi-Select or Multi-Lookup values. REST services do not support multi-select choice fields. (Found on another thread: The methods you are attempting only work with choice columns that are NOT multi-select. Unfortunately, multi-select choice columns are not supported by the REST interface. Same holds true for SharePoint 2013 apparently.)
Therefore, I need to try to access the data in these columns on the SharePoint List using the OWSSVR.dll. The list I am having issues with gives me a "This page can’t be displayed" or a "This site can’t be reached" depending on the browser I use.
I verified the List ID by grabbing It from the list settings. Since it didn't work, I went to another SharePoint List I already migrated to verify the URL format. The other list works and brings back the data in XML format.
I am wondering if the OWSSVR.dll has the same restriction on Multi-select values. Any ideas or suggestions?
Psuedo URLS (restricted access site):
Works: http://dummy.sharepointSite.Com/cases/_vti_bin/owssvr.dll?Cmd=Display&List={b703d405-48c8-4211-9137-e1b50bdb0330}&XMLDATA=TRUE
Broken: http://dummy.sharepointSite.Com/cases/_vti_bin/owssvr.dll?Cmd=Display&List={8e148584-b5be-48f5-9343-85d23a7731cc}&XMLDATA=TRUE
I figured out a way to do this without using OWSSVR. I have to set up the User Context to the SharePoint site then retrieve the list of items.
Methods:
public static ClientContext SetupSPContext(string documentLibrarySiteURL,
string userName, string password, string domain = "")
{
ClientContext clientContext = new ClientContext(documentLibrarySiteURL);
SecureString pwString = new SecureString();
foreach (char c in password.ToCharArray()) { pwString.AppendChar(c); }
if (!String.IsNullOrWhiteSpace(domain))
clientContext.Credentials = new NetworkCredential(userName, pwString, domain);
else
clientContext.Credentials = new SharePointOnlineCredentials(userName, pwString);
Web web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
return clientContext;
}
public static ListItemCollection GetListItems(ClientContext context, string listName)
{
ListCollection listCollection = context.Web.Lists;
List targetList = context.Web.Lists.GetByTitle(listName);
CamlQuery query = new CamlQuery();
query.ViewXml = "<Query><OrderBy><FieldRef Name='fieldName' /></OrderBy></Query>";
ListItemCollection collListItem = targetList.GetItems(query);
context.Load(collListItem);
context.ExecuteQuery();
if (collListItem.Count == 0)
{
return null;
}
else
{
return collListItem;
}
}
Code in SSIS Script Component:
//In the PreExecute method:
// Variables were defined for the class and not in the preExecute Method
ClientContext spContext = SetupSPContext(Variables.spLocation, Variables.spUserName,
Variables.spPassword, Variables.spDomain);
ListItemCollection listItems = GetListItems(spContext, "List Name");
//Inside the Individual loop inside SSIS (Input0_ProcessInputRow):
ListItem listItem = GetListItem(listItems, fieldValue);
//Multiple Lookup Code
var values = (FieldLookupValue[])listItem["fieldName"];
var finalValue = "FieldName values: ";
if (values.Length > 0)
{
foreach (var value in values)
{
finalValue = value.LookupValue + "; ";
}
}
//Multiple Select
if (listItem["fieldName2"] != null)
{
var valuesTwo = (string[])listItem["fieldName2"];
string combinedValues = "fieldName2 Values: ";
foreach (var value in valuesTwo)
{
combinedValues += value + "; ";
}
}
Related
I am trying to create a Windows Form for populating the information from SharePoint List into Windows Form. However, when I am trying to fetch the item from the list, it throws me an error message
An unhandled exception of type 'Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException' occurred in Microsoft.SharePoint.Client.dll
Additional information: 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."
Here is the code for the same.
private void btn_populatecontainer_Click(object sender, EventArgs e)
{
var authManager = new AuthenticationManager();
ClientContext overviewlistClientcontext = authManager.GetWebLoginClientContext("Tenant URL");
var tenant = new Tenant(overviewlistClientcontext);
var siteProperties = tenant.GetSiteByUrl("SiteCollectionURL");
Web web = siteProperties.RootWeb;
List olist = web.Lists.GetByTitle("SiteOverviewList");
overviewlistClientcontext.Load(siteProperties);
overviewlistClientcontext.ExecuteQuery();
ListItemCollectionPosition position = null;
var page = 1;
do
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = #"<View Scope='Recursive'><RowLimit>4000</RowLimit><Query><Where><Eq><FieldRef Name='Site URL'/><Value Type='Text'>" + txtSite.Text + "</Value></Eq></Where></Query></View>";
camlQuery.ListItemCollectionPosition = position;
ListItemCollection listItems = olist.GetItems(camlQuery);
overviewlistClientcontext.Load(listItems);
overviewlistClientcontext.ExecuteQuery();
position = listItems.ListItemCollectionPosition;
DataTable dataTable = new DataTable();
DataRow dr;
DataColumn dc = new DataColumn("Site Owner");
dc.DataType = Type.GetType("System.String");
dataTable.Columns.Add(dc);
foreach (var listItem in listItems)
{
dr = dataTable.NewRow();
dr["Site Owner"] = listItem["Site Owner"];
dataTable.Rows.Add(dr);
}
OverViewListGrid.DataSource = dataTable;
OverViewListGrid.DataBindings
page++;*/
}
while (position != null);
}
}
}
I have debugged the code and it fails when it tries to execute query after fetching from Caml Query.
When CamlQuery gets executed, it doesn't work at all.
However, for the testing purpose, I have tried to fetch other columns and the code works if I try to fetch Title/Id Column directly using inbuilt functions (i.e. GetItembyID).
But even the second steps won't work if i use another column from the same list.
Can anyone help me with this?
To filter list items from list which over threshold, need use indexed column.
The Site URL need to be indexed column.
<Query><Where><Eq><FieldRef Name='Site URL'/><Value Type='Text'>" + txtSite.Text + "</Value></Eq></Where></Query>
Otherwise, you need get all items from SharePoint by pagination.
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = #"<View Scope='Recursive'><RowLimit>4000</RowLimit><Query></Query></View>";
Then, filter by Linq.
How I can filter a dataTable with Linq to datatable?
the exception says that You are trying to get value of a column that has not been initialized in the context. In order to get it You need to load it to the client context together with the list item collection. The simplest way to get all fields is to use 'FieldValuesAsText'. For Your code example the updated code would look like
.....
overviewlistClientcontext.Load(listItems, includes => includes.Include(i => i.FieldValuesAsText));
overviewlistClientcontext.ExecuteQuery();
position = listItems.ListItemCollectionPosition;
DataTable dataTable = new DataTable();
DataRow dr;
DataColumn dc = new DataColumn("Site Owner");
dc.DataType = Type.GetType("System.String");
dataTable.Columns.Add(dc);
foreach (var listItem in listItems)
{
dr = dataTable.NewRow();
dr["Site Owner"] = listItem.FieldValuesAsText["Site Owner"];
dataTable.Rows.Add(dr);
}
.....
Also please be aware that You should use internal name (not display name) of column to get the field value. So I suspect that the internal name for You column 'Site Owner' would be 'Site_x0020_Owner' so You should take it like:
dr["Site Owner"] = listItem.FieldValuesAsText["Site_x0020_Owner"];
In order to check what is the internal name of Your column, the easiest way is to enter edit page of Your column and the internal name will be part of the URL as one of the GET parameters
Is there any way to update the Modified field in Office 365? I have checked both CSOM and Batch update methods. But it's failed. Could anybody help me to update this field.
Before attempting to set Modified, Created, Editor, and Author fields for a list item you need to disable a couple of properties on the List, specifically EnableVersioning and for good measure ForceCheckout.
SharePoint Online prerequisite is the SharePointOnline CSOM:
.NET client API reference for SharePoint Online
Nuget - Microsoft.SharePointOnline.CSOM
using (var context = new ClientContext(webUrl))
{
context.Credentials = new SharePointOnlineCredentials(userName,password);
var list = context.Web.Lists.GetByTitle(listTitle);
var item = list.GetItemById(itemID);
var user = context.Web.EnsureUser(accountName);
context.Load(user);
context.Load(list);
context.Load(item);
context.ExecuteQuery();
// If the properties are enabled on the list then disable them
bool updateList = list.ForceCheckout || list.EnableVersioning;
if (list.ForceCheckout) list.ForceCheckout = false;
if (list.EnableVersioning) list.EnableVersioning = false;
if (updateList)
{
list.Update();
context.ExecuteQuery();
}
// Now set the fields that are normally locked
item["Modified"] = DateTime.Now;
item["Created"] = DateTime.Now.AddDays(-3);
item["Author"] = user.Id;
item["Editor"] = user.Id;
item.Update();
context.ExecuteQuery();
}
SharePoint CSOM API does not support system update (SystemUpdate method counterpart from SSOM API) but you could manipulate system fields like Modified By and Modified fields directly as demonstrated below.
Prerequisites: SharePoint Server 2013 Client Components SDK
using (var ctx = GetContext(webUri, userName, password))
{
//get List Item
var list = ctx.Web.Lists.GetByTitle(listTitle);
var item = list.GetItemById(itemId);
//Retrieve User
var user = ctx.Web.EnsureUser(accountName);
ctx.Load(user);
ctx.ExecuteQuery();
//Update system fields
item["Modified"] = DateTime.Now.AddMonths(-6);
item["Created"] = DateTime.Now.AddYears(-1);
item["Editor"] = user.Id;
item["Author"] = user.Id;
item.Update();
ctx.ExecuteQuery();
}
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) };
}
SharePoint CSOM API now support system update using UpdateOverwriteVersion method. This way you can modify Modified, Created, Author and Editor properties without changing the item Version. For example:
$file = Get-PnPFile -Url $FileUrl -AsListItem
##update file properties
$item["Modified"] = $FileModifiedDate
$item["Created"] = $FileCreatedDate
$item["Author"] = $FileCreatedByDest.ID
$item["Editor"] = $FileModifiedByDest.ID
$fileTest2.UpdateOverwriteVersion()
Invoke-PnPQuery
That should do the trick.
My SharePoint site having a Large List that contains large data
I have to fetch all items and show them in gridview?
I am using below code and getting the below error
"The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator"
private void GetData()
{
using (SPSite site = new SPSite("URL"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists.TryGetList("BulkData");
if (list != null)
{
SPQuery query = new SPQuery();
query.Query = "<Where><IsNotNull><FieldRef Name=\"Title\" /></IsNotNull></Where>";
query.QueryThrottleMode = SPQueryThrottleOption.Override;
SPListItemCollection items = list.GetItems(query);
int itemCount = items.Count;
StringBuilder sb = new StringBuilder();
string str1 = string.Empty;
foreach (SPListItem item in items)
{
int i = 1;
sb.Append("\r\n").Append(Convert.ToString(item["Title"])).Append("\r\n");
i++;
}
Log(sb);
}
}
}
}
region Log File
public void Log(StringBuilder ErrorMessage)
{
string LogFileTime = DateTime.Now.ToString("ddMMyyyyHHmmss");
string LogFilePath = Server.MapPath(#"~\\Logs\");
if (!File.Exists(LogFilePath + "BulkData" + LogFileTime + ".txt"))
{
var LogFileName = File.Create(LogFilePath + "BulkData" + LogFileTime + ".txt");
var WriteToLogFile = new StreamWriter(LogFileName);
WriteToLogFile.Write(ErrorMessage);
WriteToLogFile.Close();
LogFileName.Close();
}
}
#endregion
You have to modify the List View threshold in Central Admin, setup by default to 5000 elements.
To minimize database contention, SQL Server often uses row-level locking as a strategy to ensure accurate updates without adversely impacting other users who are accessing other rows.
However, if a read or write database operation, such as a query, causes more than 5,000 rows to be locked at once, then it's more efficient for SQL Server to temporarily escalate the lock to the entire table until the database operation is completed.
See this link on MSDN
See this link for instructions step-by-step
However if you must change this value by code you can
SPQuery q1 = new SPQuery();
q1.QueryThrottleMode = SPQueryThrottleOption.Override;
Caution! Remember to grant privileges to the account that will run the code.
see this link for details.
Try using SPQuery.RowLimit to specify the number of items to be fetched. (The MSDN link also has an example of loading limited number of items in multiple pages)
You may use two different approaches:
ContentIterator object - is not available in SharePoint
Foundation
SPWeb.ProcessBatchData with Display method - is available in SP Foundation but is very complicated as it's very complex.
I'm working on an app that reuses some code from a previous solution.
The idea is to show a user all of the lists of a certain type in all the webs in a site collection so that the user can aggregate some data.
static public List<SPListMeta> AllSiteAnnouncementsLists(ClientContext clientContext)
{
var returnList = new List<SPListMeta>();
var per = new BasePermissions();
per.Set(PermissionKind.Open);
if (clientContext.Site.RootWeb.DoesUserHavePermissions(per).Value)
{
var rootWebLists = clientContext.Site.RootWeb.Lists;
returnList.AddRange(from List oList in rootWebLists
where oList.DoesUserHavePermissions(SPBasePermissions.ViewListItems) &&
where oList.BaseTemplate == (int)ListTemplateType.Announcements
select new SPListMeta(oList));
var collWebs =
clientContext.Site.OpenWebById(clientContext.Site.RootWeb.Id).GetSubwebsForCurrentUser(null);
foreach(Web oWeb in collWebs)
{
}
}
return returnList;
}
The critical line that does not work and does not seem to have a replacement is
oList.DoesUserHavePermissions(SPBasePermissions.ViewListItems)
as this has been removed from the CSOM List object
What's the new way to do this?
The new way to check for permissions is:
List.EffectiveBasePermissions.Has(PermissionKind.Open)
I have created a new Document Library and set up custom content type with MS Word Document Template. When i click on Create new template it works fine. but i need to be able to add some logic on a button event where it will go into that library and create a new document, so that when i go into that library i will see a new document that has been created by that button event.
i tried doing it as i would do a regular list item, but i got the following error on item.update:
To add an item to a document library, use SPFileCollection.Add()
Now i did some research but everywhere i see the code for uploading a file to the document library but no where i can find how to add a new document using my template that is associated in that doc library.
please help and thanks.
public static void colFileMtod()
{
using (SPSite objsite = new SPSite("http://smi-dev.na.sysco.net/SyscoFinance/FSR/"))
{
using (SPWeb objWeb = objsite.OpenWeb())
{
SPFileCollection collFiles = objWeb.GetFolder("BPCPublishRecord").Files;
SPList lst = objWeb.Lists["BPCPublishRecordCopy"];
if (lst != null)
{
if (objWeb.Lists.Cast<SPList>().Any(list => list.Title.Equals("BPCPublishRecordCopy", StringComparison.OrdinalIgnoreCase)))
{
foreach (SPFile file in collFiles)
{
string strDestUrl = collFiles.Folder.Url + "/" + file.Name;
byte[] binFile = file.OpenBinary();
SPUser oUserAuthor = file.Author;
SPUser oUserModified = file.ModifiedBy;
System.DateTime dtCreated = file.TimeCreated;
System.DateTime dtModified = file.TimeLastModified;
SPFile oFileNew = collFiles.Add(strDestUrl, binFile, oUserAuthor, oUserModified, dtCreated, dtModified);
SPListItem oListItem = lst.AddItem();
oListItem = oFileNew.Item;
oListItem["Created"] = dtCreated;
oListItem["Modified"] = dtModified;
oListItem.Update();
objWeb.AllowUnsafeUpdates = true;
}
}
}
}
}
}