How do I speed up below Sharepoint CSOM code? - sharepoint

I have below CSOM code to delete all list items from the list. But it is very slow. How can I make it faster.
public void DeleteListData()
{
string root = "mysite.com/";
using (ClientContext clientContext = new ClientContext(root))
{
Web web = clientContext.Web;
List list = web.Lists.GetByTitle("Search");
var query = new CamlQuery() { ViewXml = "<View><Query><Where><IsNotNull><FieldRef Name='First_x0020_Name' /></IsNotNull></Where></Query></View>" };
var items = list.GetItems(query);
clientContext.Load(items);
clientContext.ExecuteQuery();
var count = items.Count;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
items[i].DeleteObject();
items[i].Update();
}
}
clientContext.ExecuteQuery();
}
}

Almost fine according to my knowledge, just trying to add batch logic to limit deleting items count each query.
I think below code is good sample.
andyhuey/deleteAllFromList.cs
private void deleteAllFromList(ClientContext cc, List myList)
{
int queryLimit = 4000;
int batchLimit = 100;
bool moreItems = true;
string viewXml = string.Format(#"
<View>
<Query><Where></Where></Query>
<ViewFields>
<FieldRef Name='ID' />
</ViewFields>
<RowLimit>{0}</RowLimit>
</View>", queryLimit);
var camlQuery = new CamlQuery();
camlQuery.ViewXml = viewXml;
while (moreItems)
{
ListItemCollection listItems = myList.GetItems(camlQuery); // CamlQuery.CreateAllItemsQuery());
cc.Load(listItems,
eachItem => eachItem.Include(
item => item,
item => item["ID"]));
cc.ExecuteQuery();
var totalListItems = listItems.Count;
if (totalListItems > 0)
{
Console.WriteLine("Deleting {0} items from {1}...", totalListItems, myList.Title);
for (var i = totalListItems - 1; i > -1; i--)
{
listItems[i].DeleteObject();
if (i % batchLimit == 0)
cc.ExecuteQuery();
}
cc.ExecuteQuery();
}
else
{
moreItems = false;
}
}
Console.WriteLine("Deletion complete.");
}

Related

How do I connect to sharepoint syntex library in c# and read files from there?

private static void sharepointConnection()
{
try
{
Console.WriteLine("Trying to connect");
const string rootUrl = "";
const string reqUrl = "";
const string pwd = "";
const string username = "";
SecureString securestring = new SecureString();
pwd.ToCharArray().ToList().ForEach(s => securestring.AppendChar(s));
ClientContext context = new ClientContext(reqUrl);
context.Credentials = new SharePointOnlineCredentials(username, securestring);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Use CSOM code in below format after authentication:
public static List<ListItem> GetAllDocumentsInaLibrary()
{
List<ListItem> items = new List<ListItem>();
string sitrUrl = "https://spotenant.sharepoint.com/sites/yoursite";
using (var ctx = new ClientContext(sitrUrl))
{
//ctx.Credentials = Your Credentials
ctx.Load(ctx.Web, a => a.Lists);
ctx.ExecuteQuery();
List list = ctx.Web.Lists.GetByTitle("Documents");
ListItemCollectionPosition position = null;
// Page Size: 100
int rowLimit = 100;
var camlQuery = new CamlQuery();
camlQuery.ViewXml = #"<View Scope='RecursiveAll'>
<Query>
<OrderBy Override='TRUE'><FieldRef Name='ID'/></OrderBy>
</Query>
<ViewFields>
<FieldRef Name='Title'/><FieldRef Name='Modified' /><FieldRef Name='Editor' />
</ViewFields>
<RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit></View>";
do
{
ListItemCollection listItems = null;
camlQuery.ListItemCollectionPosition = position;
listItems = list.GetItems(camlQuery);
ctx.Load(listItems);
ctx.ExecuteQuery();
position = listItems.ListItemCollectionPosition;
items.AddRange(listItems.ToList());
}
while (position != null);
}
return items;
}
References:
Get all files from a SharePoint Document Library using CSOM
Download all files from Sharepoint Online Document Library using C# CSOM

MVC Linq throws intermittent null reference exception during export to Excel

I'm using the same code in 6 Areas, each a separate database. Been working fine for a long time, now fails in 3 of the 6 with a null reference exception. Classes all the same, all database tables hold data. First method is the view which displays the data, second called by a link in the view to export the data to Excel. 3 cases display and export correctly. In 2 out of the other 3 cases the data is displayed correctly in the view, and the null exception is thrown at the point the data should be being retrieved in the export method. In the last case the null exception is thrown when trying to return the view. Simply can't understand how it works in some instances but not in others.
public ActionResult PVS(string studySite, string currentFilter, int? page)
{
ViewBag.SelectedID = studySite;
if (studySite != null)
page = 1;
else
studySite = currentFilter;
ViewBag.CurrentFilter = studySite;
IQueryable<PVS> schedule = db.PVS.OrderBy(v => v.SiteNumber).ThenBy(v => v.Participant);
if (studySite != null)
{
string selectedID = studySite;
images = schedule.Where(v => v.SiteNumber == selectedID);
}
int pageSize = 10;
int pageNumber = (page ?? 1);
return View(schedule.ToPagedList(pageNumber, pageSize));
}
public void ExportPVSToExcel()
{
var grid = new System.Web.UI.WebControls.GridView();
var pvs = db.PVS.OrderBy(p => p.SiteNumber).ThenBy(p => p.Participant).ToList();
grid.DataSource = pvs;
grid.DataBind();
// create an Excel worksheet for the data export
ExcelPackage excel = new ExcelPackage();
var workSheet = excel.Workbook.Worksheets.Add("PVS");
var totalCols = grid.Rows[0].Cells.Count;
var totalRows = grid.Rows.Count;
var headerRow = grid.HeaderRow;
for (var i = 1; i <= totalCols; i++)
{
workSheet.Cells[1, i].Value = headerRow.Cells[i - 1].Text;
}
for (var j = 1; j <= totalRows; j++)
{
for (var i = 1; i <= totalCols; i++)
{
var data = pvs.ElementAt(j - 1);
workSheet.Cells[j + 1, i].Value = data.GetType().GetProperty(headerRow.Cells[i - 1].Text).GetValue(data, null);
}
}
using (var memoryStream = new MemoryStream())
{
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=PVS.xlsx");
excel.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}

Update a SavedQuery (View) from the SDK

I am trying to change all the Business Unit references I got after importing a solution to the ones in the Acceptance environment.
QueryExpression ViewQuery = new QueryExpression("savedquery");
String[] viewArrayFields = { "name", "fetchxml" };
ViewQuery.ColumnSet = new ColumnSet(viewArrayFields);
ViewQuery.PageInfo = new PagingInfo();
ViewQuery.PageInfo.Count = 5000;
ViewQuery.PageInfo.PageNumber = 1;
ViewQuery.PageInfo.ReturnTotalRecordCount = true;
EntityCollection retrievedViews = service.RetrieveMultiple(ViewQuery);
//iterate though the values and print the right one for the current user
int oldValues = 0;
int accValuesUpdated = 0;
int prodValuesUpdated = 0;
int total = 0;
foreach (var entity in retrievedViews.Entities)
{
total++;
if (!entity.Contains("fetchxml"))
{ }
else
{
string fetchXML = entity.Attributes["fetchxml"].ToString();
for (int i = 0; i < guidDictionnary.Count; i++)
{
var entry = guidDictionnary.ElementAt(i);
if (fetchXML.Contains(entry.Key.ToString().ToUpperInvariant()))
{
Console.WriteLine(entity.Attributes["name"].ToString());
oldValues++;
if (destinationEnv.Equals("acc"))
{
accValuesUpdated++;
Console.WriteLine();
Console.WriteLine("BEFORE:");
Console.WriteLine();
Console.WriteLine(entity.Attributes["fetchxml"].ToString());
string query = entity.Attributes["fetchxml"].ToString();
query = query.Replace(entry.Key.ToString().ToUpperInvariant(), entry.Value.AccGuid.ToString().ToUpperInvariant());
entity.Attributes["fetchxml"] = query;
Console.WriteLine();
Console.WriteLine("AFTER:");
Console.WriteLine();
Console.WriteLine(entity.Attributes["fetchxml"].ToString());
}
else
{
prodValuesUpdated++;
string query = entity.Attributes["fetchxml"].ToString();
query = query.Replace(entry.Key.ToString().ToUpperInvariant(), entry.Value.ProdGuid.ToString().ToUpperInvariant());
entity.Attributes["fetchxml"] = query;
}
service.Update(entity);
}
}
}
}
Console.WriteLine("{0} values to be updated. {1} shall be mapped to acceptance, {2} to prod. Total = {3} : {4}", oldValues, accValuesUpdated, prodValuesUpdated, total, retrievedViews.Entities.Count);
I see that the new value is corrected, but it does not get saved. I get no error while updating the record and publishing the changes in CRM does not help.
Any hint?
According to your comments, it sounds like the value you're saving the entity as, is the value that you want it to be. I'm guessing your issue is with not publishing your change. If you don't publish it, it'll still give you the old value of the FetchXml I believe.
Try calling this method:
PublishEntity(service, "savedquery");
private void PublishEntity(IOrganizationService service, string logicalName)
{
service.Execute(new PublishXmlRequest()
{
ParameterXml = "<importexportxml>"
+ " <entities>"
+ " <entity>" + logicalName + "</entity>"
+ " </entities>"
+ "</importexportxml>"
});
}

How can I programmatically get Approval Status in SharePoint?

I wanted to programmatically get SharePoint Page Approval Status, I tried as below
public string GetApprovalStatus(string url, string listName, string fileref)
{
string result = string.Empty;
string caml = #"
" + fileref + #"
";
using (SPSite site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[listName];
SPQuery query = new SPQuery();
query.Query = caml;
SPListItemCollection myItems = list.GetItems(query);
if (myItems != null && myItems.Count > 0)
{
DataTable dt = myItems.GetDataTable();
result = dt.Rows[0]["_ModerationStatus"].ToString();
dt.Dispose();
}
}
}
return result;
}
And I return a number, how can I get the Approval Status in text?
Appreciate any help, thank you in advanced
The following code is from the MSDN article for SPModerationInformation.Status:
using (SPSite oSiteCollection = new SPSite("http://localhost"))
{
SPWebCollection collWebsites = oSiteCollection.AllWebs;
foreach (SPWeb oWebsite in collWebsites)
{
SPListCollection collLists = oWebsite.Lists;
foreach (SPList oList in collLists)
{
if (oList.BaseType == SPBaseType.DocumentLibrary)
{
SPDocumentLibrary oDocumentLibrary = (SPDocumentLibrary)oList;
if (!oDocumentLibrary.IsCatalog && oDocumentLibrary.EnableModeration ==
true)
{
SPQuery oQuery = new SPQuery();
oQuery.ViewAttributes =
"ModerationType='Moderator'";
SPListItemCollection collListItems =
oDocumentLibrary.GetItems(oQuery);
foreach (SPListItem oListItem in collListItems)
{
if (oListItem.ModerationInformation.Status ==
SPModerationStatusType.Pending)
{
Console.WriteLine(oWebsite.Url + "/" +
oListItem.File.Url);
oListItem.ModerationInformation.Comment =
"Automatic Approval of items";
oListItem.ModerationInformation.Status =
SPModerationStatusType.Approved;
oListItem.Update();
}
}
}
}
}
oWebsite.Dispose();
}
}
You can use the SPModerationStatusType enum SPModerationStatusType Enum - MSDN to get the text values that you want.
More info: http://spuser.blogspot.com.br/2011/03/how-to-programmatically-get-content.html
Here is the full code that gets and sets (optional) approval status (Possible values for this.oListItem.get_item('_ModerationStatus'): 0 - "Approved", 1 - "Denied", 2- "Pending"):
<script type="text/javascript" src="/jquery-1.10.2.min.js"></script>
<script src="/jquery.SPServices-2013.02a.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { ExecuteOrDelayUntilScriptLoaded(loadConstants, "sp.js"); });
function loadConstants() {
var userid= _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
var requestHeaders = { "accept" : "application/json;odata=verbose" };
$.ajax({
url : requestUri,
contentType : "application/json;odata=verbose",
headers : requestHeaders,
success : onSuccess,
error : onError
});
function onSuccess(data, request){
var loginName = data.d.Title;
//get current (selected) list item id
var docurl = document.URL;
var beginindex = docurl.indexOf('?ID=') + 4;
var endindex = docurl.indexOf('&Source=');
var itemid = docurl.substring(beginindex, endindex);
var ctx = new SP.ClientContext("your site url");
var oList = ctx.get_web().get_lists().getByTitle('your list name');
this.oListItem = oList.getItemById(itemid);
var appStatus = "";
ctx.load(this.oListItem);
ctx.executeQueryAsync(Function.createDelegate(this, function () {
//get approval status
appStatus = this.oListItem.get_item('_ModerationStatus');
//set approval status to Approved (0)
this.oListItem.set_item('_ModerationStatus', 0);
this.oListItem.update();
ctx.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}), function (sender, args) { alert('Error occured' + args.get_message());});
}
function onError(error) {
alert("error");
}
}
</script>

How do I create a KPI list programmatically in SharePoint?

I want to be able to create a KPI List on my MOSS 2007 installation via the object model. Is this possible?
using (SPWeb web1 = properties.Feature.Parent as SPWeb)
{
using (SPSite objSite = new SPSite(web1.Site.ID))
{
using (SPWeb web = objSite.OpenWeb(web1.ID))
{
SPListTemplate template = null;
foreach (SPListTemplate t in web.ListTemplates)
{
if (t.Type.ToString() == "432")
{
template = t;
break;
}
}
Guid gG = Guid.Empty;
SPList list = null;
string sListTitle = "Status List";
SPSecurity.RunWithElevatedPrivileges(delegate
{
try
{
web.AllowUnsafeUpdates = true;
gG = web.Lists.Add(sListTitle, sListTitle, template);
list = web.Lists[gG];
}
catch
{
// exists
list = web.Lists[sListTitle];
}
SPContentType ct =
list.ContentTypes["SharePoint List based Status Indicator"];
//declare each item which u want to insert in the kpi list
SPListItem item1 = list.Items.Add();
SPFieldUrlValue value1 = new SPFieldUrlValue();
item1["ContentTypeId"] = ct.Id;
item1.SystemUpdate();
item1["Title"] = "Project Specific Doc.Lib.Rating";
value1.Url = web.Url + "/Lists/Project Specific Documents";
item1["DataSource"] = value1;
item1["Indicator Goal Threshold"] = "3";
item1["Indicator Warning Threshold"] = "3";
item1["Value Expression"] =
"Average;Average_x0020_Rating:Number";
item1.SystemUpdate();
}
}
}
average is the calculation value and the column is Average_x0020_Rating.
http://alonsorobles.com/2010/03/17/important-custom-sharepoint-list-template-notes/
I found that the Template ID for a Status Indicator (KPI List) is 432. Google for this to find some info on creating a new list. I'm needing to read up what properties I can set on this list.
this is work for me:
private void CreateKPIDocumentLibrary(List<PageStructure> list)
{
SPListTemplate kpi = null;
foreach (SPListTemplate t in web.ListTemplates)
{
if (t.Type.ToString() == "432")
{
kpi = t;
break;
}
}
foreach (PageStructure st in list)
{
bool find = false;
string[] periodType = st.tag.Split('_');
string name = periodType[0] + "-" + st.effdate + "-" + st.template;
SPListCollection lstCol = site.OpenWeb().GetListsOfType(SPBaseType.GenericList);
foreach (SPList l in lstCol)
{
string title = l.Title;
if (title == name)
{
find = true;
break;
}
}
if (find == false)
{
Guid docLibID = web.Lists.Add(name, "", kpi);
}
SPList itemList = web.Lists[name];
SPListItem item = itemList.Items.Add();
SPFieldUrlValue value = new SPFieldUrlValue();
item["Title"] = st.tag;
value.Url = st.docUrl;
item["DetailLink"] = st.url;
item["DataSource"] = value;
item["Indicator Goal Threshold"] = "2";
item["Indicator Warning Threshold"] = "1";
item["View Name"] = "All Documents";
item.SystemUpdate();
web.Update();
KpiObject kp = new KpiObject(name, SPContext.Current.Site.Url + itemList.DefaultViewUrl);
this.kpiList.Add(kp);
}
}

Resources