How can we update a people picker field in sharepoint online? - c#

Trying to update a people picker field in SP online list.I'm able to update with single value, but when I try to update with new value in the filed, the existing value is being removed. I need to append the new input value, with existing values in that field. How can this be achieved?
List list = ctx.Web.Lists.GetByTitle("ListName");
ListItem targetListItem = list.GetItemById(ItemID);
ctx.Load(targetListItem);
ctx.ExecuteQuery();
FieldUserValue[] userValueCollection = new FieldUserValue[1];
//Get all the users of this Web
User user = ctx.Web.SiteUsers.GetByEmail(emailIdOfUser);
ctx.Load(user);
ctx.ExecuteQuery();
if (user != null)
{
FieldUserValue fieldUserVal = new FieldUserValue();
fieldUserVal.LookupId = user.Id;
userValueCollection.SetValue(fieldUserVal, 0);
}
FieldUserValue[] existingUsers = targetListItem["PeoplePickerColumnName"] as FieldUserValue[];
List<int> userValues = new List<int>();
foreach (FieldUserValue x in existingUsers)
{
userValues.Add(x.LookupId);
int counts = userValues.Count();
}
targetListItem["PeoplePickerColumnName"] = userValueCollection;
targetListItem.Update();
ctx.ExecuteQuery();

You could read the old value and then update the column with all values which you want to set in column.
You could get a update multi selection user field demo here:
https://social.msdn.microsoft.com/Forums/office/en-US/900b5143-f5b3-4fd5-a9ce-3e7d7c3ecfc1/csomjsom-operation-to-update-user-field-value?forum=sharepointdevelopment

I faced same challenge in C# and I use below code to solve the problem.
public void Update_SPO_ListItemMultiplePeoplePicker(int SPO_Item_ID)
{
string siteUrl = "https://yourtenant.sharepoint.com/sites/subsite/";
string ListTitle = "SharePointListTitle";
string NewUserLookupValue = "MySPOLogin#email.com";
using (var clientcontext = new AuthenticationManager().GetWebLoginClientContext(siteUrl))
{
// connect to sharepoint online list by lookup List name
List list = clientcontext.Web.Lists.GetByTitle(ListTitle);
clientcontext.Load(list);
clientcontext.ExecuteQuery();
// Get list item by ID.
ListItem listItem = list.GetItemById(SPO_Item_ID);
clientcontext.Load(listItem);
clientcontext.ExecuteQuery();
// get multiple people picker old value , replace [attendees] with your internal people picker field value
var attendees = listItem["attendees"] as Microsoft.SharePoint.Client.FieldUserValue[];
//Initiate a FieldUserValue array which can carry additional 1 more elements ontop existing array .
int NewArayLength = attendees.Length + 1;
FieldUserValue[] users = new FieldUserValue[NewArayLength];
// Loop existing multiple people picker value then saved existing old values to new FieldUserValue array
int i = 0;
foreach (var attendee in attendees)
{
users[i] = new FieldUserValue();
users[i].LookupId = attendee.LookupId;
i++;
}
// set new user object which will be prepare add to new FieldUserValue array
Microsoft.SharePoint.Client.User Newattendee = clientcontext.Web.EnsureUser(NewUserLookupValue);
clientcontext.Load(Newattendee);
clientcontext.ExecuteQuery();
// add new user to the last index of FieldUserValue array
users[i] = new FieldUserValue();
users[i].LookupId = Newattendee.Id;
// Update list item with new FieldUserValue array
listItem["attendees"] = users;
listItem.Update();
clientcontext.ExecuteQuery();
}
}

Related

C# GoogleSheets Update Request not Executing

I'm trying to update values in a Google Spreadsheet, The code executes up to the addRequest.Execute(); however, it does not run the execute statement.
This does work if i run a Append Request, however im not trying to append, im trying to update.
I have the following Scopes for the program static readonly string[] Scope = { SheetsService.Scope.Spreadsheets, DriveService.Scope.Drive};
var range = $"{ClashImport[i][0].ToString()}!B7:F106";
var REALInsertList = new sData.ValueRange();
var InsertList = new List<object>();
for (int n = 0; n < DataImport[i].Count; n++) {
InsertList.Add(DataImport[i][n].AccountName);
InsertList.Add(DataImport[i][n].AccountID);
InsertList.Add(DataImport[i][n].Banned);
InsertList.Add(DataImport[i][n].Suspended);
InsertList.Add(DataImport[i][n].History);
}
REALInsertList.Values = new List<IList<object>> { InsertList };
var addRequest = sheetsService.Spreadsheets.Values.Update(REALInsertList, SheetToImportTo, range);
addRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.UpdateRequest.ValueInputOptionEnum.USERENTERED;
addRequest.Execute();
This example will help you to achieve what you are trying to do:
// Define request parameters.
// The ID of the spreadsheet to update.
string spreadsheetId = "YOUR-SPREADSHEET-ID"; // TODO: Update placeholder value.
// How the input data should be interpreted.
string valueInputOption = "RAW"; // TODO: Update placeholder value. Ex -> RAW
// The new values to apply to the spreadsheet.
List<ValueRange> data = new List<ValueRange>(); // Instanciate a list of type ValueRange
ValueRange values = new ValueRange(); // Instanciate a ValueRange object
values.Range = "A1:B2"; // The range you want to update
// Depending in your number of rows, create some logic to populate them
List<object> firstRow = new List<object> { "Hello", 2};
List<object> secondRow = new List<object> { 3, "Hey!"};
// Populate the values to be inserted in the sheet
values.Values = new List<IList<object>> { firstRow, secondRow };
// add values to the data ValueRange List
data.Add(values);
// TODO: Assign values to desired properties of `requestBody`:
BatchUpdateValuesRequest requestBody = new BatchUpdateValuesRequest();
requestBody.ValueInputOption = valueInputOption;
requestBody.IncludeValuesInResponse = true;
requestBody.Data = data;
// Build and make the request
SpreadsheetsResource.ValuesResource.BatchUpdateRequest request
= service.Spreadsheets.Values.BatchUpdate(requestBody, spreadsheetId);
BatchUpdateValuesResponse response = request.Execute();
IList<IList<object>> updatedValues = response.Responses[0].UpdatedData.Values;
// Print updated values
Console.WriteLine("These are the updated values");
foreach (var row in updatedValues)
{
Console.WriteLine("{0}, {1}", row[0], row[1]);
}
Console.Read();
Following the Method: spreadsheets.values.batchUpdate endpoint documentation and the Try this API, I was able to get an idea on how to build the request update body.
Notice I created a List<ValueRange>, which I populate with the appropriate data and in that way make the request.
Documentation
For more info, you can check:
.NET Quickstart
Google Sheets API .NET reference documentation

Why is this ArrayList duplicating he rows

I am junior developer and I am trying to populate an ArrayList from a Dictionary. My problem is rather then adding a new record to the ArrayList it adds the new record but also overwrites the values for all the other values in the array.
So if I inspect the values as the ArrayList is being populated I see the values from the Dictionary as expected. But when that row is inserted into the ArrayList all of the existing rows are over written with the data from current Dictionary Row. So I end up with an ArrayList with several rows that are a duplicate of the last record added from the dictionary. My code is shown below. Can someone please tell me what am I doing wrong? Code below
ArrayList arrData = new ArrayList();
eSummary edata = new eSummary();
//Starts with the first 50 recods retrieved and adds them to the ArrayList. Loops thru to get remaining records
while (blnEmpty)
{
if (response.IsSuccessStatusCode)
{
string json = response.Content.ReadAsStringAsync().Result;
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string, dynamic>>(json);
for (int i = 0; i < dict.Values.Sum(x => x.Count); i++)
{
foreach (var item in dict)
{
string checkId = (dict["data"][i]["Id"]);
edata.Id = dict["data"][i]["Id"];
edata.idExternal = (dict["data"][i]["idExternal"]) == null ? "" : (dict["data"][i]["idExternal"]);
edata.Type = "Video";
edata.ownerId = (dict["data"][i]["uploadedByOwnerId"]);
edata.dateUploaded = Convert.ToDateTime((dict["data"][i]["dateUploaded"]));
edata.durationSeconds = Convert.ToDouble((dict["data"][i]["durationSeconds"]));
edata.category = (dict["data"][i]["categories"]).Count < 1 ? string.Empty : (dict["data"][i]["categories"][0]);
edata.title = (dict["data"][i]["title"]) == string.Empty ? string.Empty : (dict["data"][i]["title"]);
edata.dateRecordStarted = Convert.ToDateTime((dict["data"][i]["dateRecordStart"]));
edata.DateAPIRan = DateTime.Now;
if (CheckAutoTag(checkId, dict["data"][i]["tags"]))
{
edata.AutoTagged = true;
}
else edata.AutoTagged = false;
arrData.Add(edata);
edata is a reference type. You keep updating the values of a single object within the loop.
You need to call new eSummary() and set the values on the new object and then add that to your list.
But do note, you should not be using ArrayList in modern c#. Use a List<eSummary> instead.

Update list item multiple lookup value field Microsoft Graph

I am trying to update a multiple lookup value field for a list item.
I tried the following code :
List < QueryOption > options = new List < QueryOption > {
new QueryOption("$expand", "listitem")
};
//get drive item with list item
var driveItem = graphClient.Sites[IdGestDoc].Drive.Items[itemResult.Id].Request(options).GetAsync().Result;
var fieldValueSet = new FieldValueSet {
AdditionalData = new Dictionary < string,
object > {
{
"Theme_fonctionnel#odata.type",
"Collection(Edm.String)"
}, {
"Theme_fonctionnel", ThemeFonctionnel.ToArray()
} //ThemeFonctionnel is a List<string> => lookupid
}
};
await graphClient.Sites[IdGestDoc].Lists["Documents"].Items[driveItem.ListItem.Id].Fields.Request().UpdateAsync(fieldValueSet);
But this code don't work and I don't find what I am missing.
Any help will be appreciated !
To set a Lookup field, you need to set the property by passing in the property name and the addition 'LookupId':
string propertyName = "Theme_fonctionnel";
var fieldValueSet = new FieldValueSet();
var propertyValuesArray = options.ToArray();
var attributes = new Dictionary<string, object>();
//first, we need to specify the input data type
string oDataTypeInfoPropertyName = propertyName + "LookupId#odata.type";
string oDataDataType = "Collection(Edm.String)";
attributes.Add(oDataTypeInfoPropertyName, oDataDataType);
//next, we need to pass the values as an array
string newPropertyName = propertyName + "LookupId";
attributes.Add(newPropertyName, propertyValuesArray);
fieldValueSet.AdditionalData = attributes;

How to add distinct value in database using Entity Framework

IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
}
}
db.SaveChanges();
I want to add only distinct values to database in above code. Kindly help me how to do it as I am not able to find any solution.
IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
var a = db.WebsiteWebPages.Where(i => i.WebPage == value.WebPage.ToString()).ToList();
if (a.Count == 0)
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
db.SaveChanges();
}
}
}
This is the code that I used to add distinct data.I hope it helps
In addition to the code sample Furkan Öztürk supplied, Make sure your DB has a constraint so that you cannot enter duplicate values in the column. Belt and braces approach.
I assume that by "distinct values" you mean "distinct value.WebPage values":
// get existing values (if you ever need this)
var existingWebPages = db.WebsiteWebPages.Select(v => v.WebPage);
// get your pages
var webPages = GetWebPages().Where(v => v.WebPage.Contains(".htm"));
// get distinct WebPage values except existing ones
var distinctWebPages = webPages.Select(v => v.WebPage).Distinct().Except(existingWebPages);
// create WebsiteWebPage objects
var websiteWebPages = distinctWebPages.Select(v =>
new WebsiteWebPage { WebPage = v, WebsiteId = websiteid});
// save all at once
db.WebsiteWebPages.AddRange(websiteWebPages);
db.SaveChanges();
Assuming that you need them to be unique by WebPage and WebSiteId
IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
if (db.WebsiteWebPages.All(c=>c.WebPage != value.WebPage|| c.WebsiteId != websiteid))
{
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
}
}
}
db.SaveChanges();
UPDATE
To optimize this (given that your table contains much more data than your current list), override your equals in WebsiteWebPage class to define your uniqueness criteria then:
var myWebsiteWebPages = data.select(x=> new WebsiteWebPage { WebPage = x.WebPage, WebsiteId = websiteid}).Distinct();
var duplicates = db.WebsiteWebPages.Where(x=> myWebsiteWebPage.Contains(x));
db.WebsiteWebPages.AddRange(myWebsiteWebPages.Where(x=> !duplicates.Contains(x)));
this is a one database query to retrieve ONLY duplicates and then removing them from the list
You can use the following code,
IEnumerable<WebsiteWebPage> data = GetWebPages();
var templist = new List<WebsiteWebPage>();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
templist.Add(pagesinfo);
}
}
var distinctList = templist.GroupBy(x => x.WebsiteId).Select(group => group.First()).ToList();
db.WebsiteWebPages.AddRange(distinctList);
db.SaveChanges();
Or you can use MoreLINQ here to filter distinct the list by parameter like,
var res = tempList.Distinct(x=>x.WebsiteId).ToList();
db.WebsiteWebPages.AddRange(res);
db.SaveChanges();

Populate Drop Down List based on multiple user roles

I am trying to populate a DropDownList based on roles. I have a view in SQL with the value and text of each item based on the user role (Windows Auth) and can populate the DropDownList if a user was in all roles with:
using (var db=new GPSE_2.DAL.GPSE2Entities())
{
var locations = (from loc in db.LocationLOBViews
orderby loc.LocationNumber
select new { loc.DataValue, loc.DataText});
ddlShops.DataValueField = "DataValue" ;
ddlShops.DataTextField = "DataText";
ddlShops.DataSource = locations.ToList();
DataBind();
}
I would like to add items only the logged in user is a member of. Users can be in multiple groups(roles).
For instance, the logged in user is in a group called Location 01 LOB 100 and they are also in a group called Location 01 LOB 200 and also in Location o2 LOB 100. Only those options should appear in the DropDownList.
I was able to loop through the roles the user is in by the code below.
string UPN = UserPrincipal.Current.UserPrincipalName.ToString();
WindowsIdentity wi = new WindowsIdentity(UPN);
string GroupName;
foreach (IdentityReference group in wi.Groups)
{
GroupName = group.Translate(typeof(NTAccount)).ToString();
if (GroupName.Contains("Location 01 LOB 100"))
{
var item = new ListItem
{
Text = "Location 01 LOB 100",
Value = "01,100"
};
ddlShops.Items.Add(item);
}
}
Now I am trying to combine the 2 I ran into problems adding loc.DataValue and the loc.DataText to the DDL if the query returns results. This is where I an stuck, it adds the string in the quotes instead of the values.
using (var db = new GPSE_2.DAL.GPSE2Entities())
{
string UPN = UserPrincipal.Current.UserPrincipalName.ToString();
WindowsIdentity wi = new WindowsIdentity(UPN);
string GroupName;
foreach (IdentityReference group in wi.Groups)
{
GroupName = group.Translate(typeof(NTAccount)).ToString();
var locations = (from loc in db.LocationLOBViews
where loc.DataValue.Contains(GroupName)
orderby loc.LocationNumber
select new { loc.DataValue, loc.DataText });
if (locations !=null)
{
var item = new ListItem
{
Text = "DataText",
Value = "DataValue"
};
ddlShops.Items.Add(item);
}
}
}
Thanks,
-Doug
I got it working by creating a list of groups the user is in and then populating the Drop Down List with the appropriate information.
private List<string> GetGroups()
{
string UPN = UserPrincipal.Current.UserPrincipalName.ToString();
List<string> result = new List<string>();
WindowsIdentity wi = new WindowsIdentity(UPN);
foreach (IdentityReference group in wi.Groups)
{
string GroupName = group.Translate(typeof(NTAccount)).ToString();
//if text location and lob is in the name add to results
if (GroupName.Contains("Location") && GroupName.Contains("LOB"))
{
string DataValue1 = GroupName.Substring(GroupName.Length - 3);
string DataValue2 = GroupName.Substring(GroupName.Length - 10, 2);
string DataValue = DataValue2 + "," + DataValue1;
result.Add(DataValue);
}
}
result.Sort();
return result;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
using (var db = new GPSE2Entities())
{
for (int i = 0; i < GetGroups().ToArray().Length; i++)
{
string DataValue = GetGroups().ToArray()[i].ToString();
var locations = (from loc in db.LocationLOBViews
where loc.DataValue == DataValue
orderby loc.LocationNumber
select loc).FirstOrDefault();
if (locations != null)
{
var item = new ListItem
{
Text = locations.DataText,
Value = locations.DataValue
};
ddlShops.Items.Add(item);
}
}
}
ddlShops.Items.Insert(0, "--Select Location and LOB--");
}
}

Categories