Update Modified field in Office 365 - sharepoint

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.

Related

Add/update item with users information Sharepoint Client C#

Using Microsoft.Sharepoint.CLient & .Runtime.dll ver.16.0.0.0
I have a Item list (Lost packages) with Tracking number(title),Description(currier),MailTo(Type: Person, Show Field: E-Mail)
I also have another list (buyers) of available User to pick up from
So from my C# client program I want to add or update an item from Lost packages and with the MailTo -Email- of an user. Right now I can only get the Name as String of the Author of a ListItem. How do I get the user information from a ListItem so I can change the MailTo to a specific user
public Package(ListItem _package) {
this.item = _package;
if (this.item != null) {
this.exist = true;
this.id = this.item["ID"].ToString();
this.trackNo = (String)this.item["Title"];
this.currier = (String)this.item["Description"];
this.status = (String)this.item["Status"];
FieldUserValue userAuthor = (FieldUserValue)this.item["Author"];
this.Owner = userAuthor.LookupValue.ToString();
Here is a sample code for your reference, just need to set the User Id to FieldUserValue class, then set to MailTo field:
ClientContext clientContext = new ClientContext("http://sp/sites/dev");
Web web = clientContext.Web;
Microsoft.SharePoint.Client.List spList = clientContext.Web.Lists.GetByTitle("JerryList4");
clientContext.Load(spList);
clientContext.ExecuteQuery();
ListItem item = spList.GetItemById(3);
clientContext.Load(item);
clientContext.ExecuteQuery();
FieldUserValue userValue = new FieldUserValue();
userValue.LookupId = 19; //set user Id here
item["MailTo"] = userValue;
item.Update();
clientContext.ExecuteQuery();
For the user id, you can get it from this Rest EndPoint:
http://siteurl/_api/web/siteusers?$select=Id,LoginName

How to create a anonymous link for the documents in Sharepoint Online 2018

I am trying to create a anonymous link for the documents in Sharepoint online 2018.
I have tried using the CreateAnonymousLink method provided by Microsoft.SharePoint.Client but it throws error.
ClientResult<string> result = Microsoft.SharePoint.Client.Web.CreateAnonymousLink(clientContext, absoluteurl, false);
clientContext.ExecuteQuery();
My Sample test code for your reference.
using (var context = new ClientContext("https://tenant.sharepoint.com/sites/Developer"))
{
Console.ForegroundColor = ConsoleColor.Green;
string password = "pw";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();
context.Credentials = new SharePointOnlineCredentials("lee#tenant.onmicrosoft.com", sec_pass);
ClientResult<string> a = Web.CreateAnonymousLink((ClientRuntimeContext)context, "https://tenant.sharepoint.com/sites/Developer/Shared%20Documents/Culture%20Training.docx", false);
context.ExecuteQuery();
Console.WriteLine("done");
Console.ReadKey();
}

Multi-Select fields on a Sharepoint list using OWSSVR.dll

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 + "; ";
}
}

Add/Create new document in SharePoint document Library programmatically

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;
}
}
}
}
}
}

How to get Sharepoint User object from the "AssignedTo" field using client side object model?

I am using managed client side object model in sharepoint 2010. And I want to get loginaName of the AssignedTo user in Task list.
In server side object model I use SPFieldUserValue.User.LoginName to get this property but in client side object model FieldUserValue.User does not exists.
How can I resolve this situation ?
Thanks
Here is the code for that. I've taken an example of AssignedTo field from Task list. I hope that helps.
public static User GetUserFromAssignedToField(string siteUrl)
{
// create site context
ClientContext ctx = new ClientContext(siteUrl);
// create web object
Web web = ctx.Web;
ctx.Load(web);
// get Tasks list
List list = ctx.Web.Lists.GetByTitle("Tasks");
ctx.Load(list);
// get list item using Id e.g. updating first item in the list
ListItem targetListItem = list.GetItemById(1);
// Load only the assigned to field from the list item
ctx.Load(targetListItem,
item => item["AssignedTo"]);
ctx.ExecuteQuery();
// create and cast the FieldUserValue from the value
FieldUserValue fuv = (FieldUserValue)targetListItem["AssignedTo"];
Console.WriteLine("Request succeeded. \n\n");
Console.WriteLine("Retrieved user Id is: {0}", fuv.LookupId);
Console.WriteLine("Retrieved login name is: {0}", fuv.LookupValue);
User user = ctx.Web.EnsureUser(fuv.LookupValue);
ctx.Load(user);
ctx.ExecuteQuery();
// display the user's email address.
Consol.writeLine("User Email: " + user.Email);
return user;
}
The fuv.LookupValue may contain the display name, not the login name, so my suggestion is (assuming you have the FieldUserValue - fuv in code (as descibed by #ekhanna):
var userId = fuv.LookupId;
var user = ctx.Web.GetUserById(userId);
ctx.Load(user);
ctx.ExecuteQuery();
You get the column which as the FieldUserValue from the list, once you have that you use the lookup id value and then query against the Sites User Info List. In the example below I cache the results to prevent looking up the same id more than once since the query can be expensive.
private readonly Dictionary<int, string> userNameCache = new Dictionary<int, string>();
public string GetUserName(object user)
{
if (user == null)
{
return string.Empty;
}
var username = string.Empty;
var spUser = user as FieldUserValue;
if (spUser != null)
{
if (!userNameCache.TryGetValue(spUser.LookupId, out username))
{
var userInfoList = context.Web.SiteUserInfoList;
context.Load(userInfoList);
var query = new CamlQuery { ViewXml = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='ID' /><Value Type='int'>" + spUser.LookupId + "</Value></Eq></Where></Query></View>" };
var users = userInfoList.GetItems(query);
context.Load(users, items => items.Include(
item => item.Id,
item => item["Name"]));
if (context.TryExecuteQuery())
{
var principal = users.GetById(spUser.LookupId);
context.Load(principal);
context.ExecuteQuery()
username = principal["Name"] as string;
userNameCache.Add(spUser.LookupId, username);
}
}
}
return username;
}
Everything above worked for me, but instead of:
FieldUserValue fuv = (FieldUserValue)targetListItem["AssignedTo"];
I used:
FieldUserValue[] fuv = targetListItem["AssignedTo"] as FieldUserValue[];

Resources