How to update File metadata in Sharepoint CSOM? - c#

I know this question has been asked in the past, but I can't seem to find a working solution.
I want to update The CreatedDateTime, ModifiedBy and CreatedBy metadata on a file that I uploaded with CSOM. I have this code. It does not crash, but does not update the properties either.
FileCreationInformation newFile = new FileCreationInformation();
byte[] FileContent = null;
using (var webClient = new WebClient())
{
webClient.Headers.Add("Authorization", authorization);
FileContent = webClient.DownloadData(file.DowlnloadUrl);
}
newFile.ContentStream = new System.IO.MemoryStream(FileContent);
newFile.Url = System.IO.Path.GetFileName(file.Name);
Microsoft.SharePoint.Client.File sharepointFile = _spFolder.Files.Add(newFile);
_context.ExecuteQuery();
sharepointFile.ListItemAllFields["Modified"] = DateTime.Today.AddDays(-3);
sharepointFile.ListItemAllFields["Created"] = DateTime.Today.AddDays(-3);
sharepointFile.ListItemAllFields.Update();
_context.ExecuteQuery();
The file still appears that it was created/modified a few seconds ago.
Any help would be appreciated. PS: if this can be done in one go (one single ExecuteQuery), that would be great.

I ended up finding a code snippet that works.
Beware, this works only if the account your are using to generate the context is a Sharepoint Admin (has the SP admin role, and not only a Global Admin role).
Being an owner of the site does not suffice either.
Code can be found here:
https://www.c-sharpcorner.com/blogs/update-a-sharepoint-listitem-without-increasing-its-item-file-version-using-sharepoint-client-side-modelcsom

Related

Changing Microsoft Sharepoint fieldvalues for files with C#?

I'm trying to change the field values for files stored in a Sharepoint List programmatically, but it seems i can't access these. There have been some helpful ideas and they look very promising, but it seems not to work at all. Here my code so far:
ClientContext context = new ClientContext(#"https://.........de");
Microsoft.SharePoint.Client.File file = context.Web.GetFileByServerRelativeUrl(#"https://............de/software/ap_ck/Dokumenten%20Management%20System/100_001_000_1.txt");
ListItem lstitem = file.ListItemAllFields;
context.Load(lstitem);
context.ExecuteQuery();
lstitem["Mandant"] = "Mercedes";
lstitem.Update();
context.ExecuteQuery();
Is there maybe something wrong with the code itself?
In Line two GetFileByServerRelativeUrl method, it needs the file relative url, please check the working demo below:
ClientContext context = new ClientContext(#"http://sp2016/sites/test");
Microsoft.SharePoint.Client.File file = context.Web.GetFileByServerRelativeUrl(#"/sites/test/Documents1/folder2/test.txt");
ListItem lstitem = file.ListItemAllFields;
context.Load(lstitem);
context.ExecuteQuery();
lstitem["Title"] = "Mercedes";
lstitem.Update();
context.ExecuteQuery();

AddAttachment Method in Kentico

We are using Kentico v9 and are importing blog posts from Wordpress into Kentico. We are having a problem importing the attachments into the blog post. Here's the code currently being used:
var attachmentNode = TreeNode.New(FILE_PAGE_TYPE);
attachmentNode.DocumentName = filename;
attachmentNode.DocumentCulture = postNode.DocumentCulture;
attachmentNode.Insert(postNode);
DocumentHelper.AddAttachment(attachmentNode, "ce4c5d10-c143-4ada-9d8a-7e7481b167ef", localFileLocation, postNode.TreeProvider);
attachmentNode.Update();
This does not produce any error, and there is a record in the database for the file. However, the file itself is not in Kentico. Does anyone know what I'm doing wrong here?
See the answer I provided in the Kentico DevNet.
TreeNode newNode = TreeNode.New(PageType, tree);
newNode.DocumentName = mediaFile.FileName;
newNode.DocumentName = fileName.Trim();
newNode.SetValue("FileDate", fileDate);
DocumentHelper.InsertDocument(newNode, parentNode.NodeID);
AttachmentInfo newAttachment = null;
// Path to the file to be inserted. This example uses an explicitly defined file path. However, you can use an object of the HttpPostedFile type (uploaded via an upload control).
string filePath = MediaLibraryPath + #"\" + mediaFile.FileName + mediaFile.FileExtension;
// Insert the attachment and update the document with its GUID
newAttachment = DocumentHelper.AddUnsortedAttachment(newNode, Guid.NewGuid(), filePath, tree, ImageHelper.AUTOSIZE, ImageHelper.AUTOSIZE, ImageHelper.AUTOSIZE);
// attach the new attachment to the page/document
newNode.SetValue("FileAttachment", newAttachment.AttachmentGUID);
DocumentHelper.UpdateDocument(newNode);
newNode.Publish();
I don't think this code does any operation/processing of an actual file - it just saves a reference to that file into a database. If you want to save it in particular location in your file system you have to implement appropriate functionality.
See some examples of API working with attachments.

Create folder google cloud storage bucket .NET Client Library

I'm looking to at a way to create a folder inside a bucket using the following client library:
https://cloud.google.com/storage/docs/json_api/v1/json-api-dotnet-samples
I've looked at the following thread, and it appears I need to use the simple method upload.
Creating folder in bucket google cloud storage using php
I can't see any way of being able to specify a uploadtype, all requests appear to be uploadType=resumable.
Looking at the above post and a fiddler trace I need to use uploadType=media. Is there away to accomplish this?
It is a bit more straighforward to do this in the latest version of the API.
You still have to make sure that you check for the "/" as Salem has suggested.
public void AddFolder(string folder)
{
StorageClient storageClient = StorageClient.Create();
if (!FolderName.EndsWith("/"))
FolderName += "/";
var content = Encoding.UTF8.GetBytes("");
storageClient.UploadObject(bucketName, folder, "application/x-directory", new MemoryStream(content));
}
This worked for me! Don't know if it's the right way to do it, but there are not enough on this.
public void CreateDir(string FolderName)
{
if (!FolderName.EndsWith("/"))
FolderName += "/";
var uploadStream = new MemoryStream(Encoding.UTF8.GetBytes(""));
Storage.Objects.Insert(
bucket: BucketName,
stream: uploadStream,
contentType: "application/x-directory",
body: new Google.Apis.Storage.v1.Data.Object() { Name = FolderName}
).Upload();
}
EDIT: Just found out that you can directly upload the file to your destination objects, and if the directories/sub-directories don't exist the upload function will create them for you.
All you need to do is put the folder(s) you want before the file name
using (MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(json)))
{
string fileName = $"/test/somefolder/{sourceId}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.json";
await gcpClient.UploadObjectAsync(gcpBucketName, fileName, null, ms);
}

Uploading file with metadata

Could you help me for how to add a file to the Sharepoint document library? I found some articles in .NET, but I didn't get the complete concept of how to accomplish this.
I uploaded a file without metadata by using this code:
if (fuDocument.PostedFile != null)
{
if (fuDocument.PostedFile.ContentLength > 0)
{
Stream fileStream = fuDocument.PostedFile.InputStream;
byte[] byt = new byte[Convert.ToInt32(fuDocument.PostedFile.ContentLength)];
fileStream.Read(byt, 0, Convert.ToInt32(fuDocument.PostedFile.ContentLength));
fileStream.Close();
using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
using (SPWeb webcollection = site.OpenWeb())
{
SPFolder myfolder = webcollection.Folders["My Library"];
webcollection.AllowUnsafeUpdates = true;
myfolder.Files.Add(System.IO.Path.GetFileName(fuDocument.PostedFile.FileName), byt);
}
}
}
}
This code is working fine as is, but I need to upload a file with metadata. Please help me by editing this code if it is possible. I created 3 columns in my document library.
SPFolder.Files.Add returns a SPFile object
SPFile.Item returns an SPListItem object
You can then use SPlistItem["FieldName"] to access each field (see bottom of SPListItem link)
So adding this into your code (this is not tested, but you should get the idea)
SPFile file = myfolder.Files.Add(System.IO.Path.GetFileName(document.PostedFile.FileName);
SPListItem item = file.Item;
item["My Field"] = "Some value for your field";
item.Update()
There is also an overload where you can send in a hashtable with the metadata you want to add. For example:
Hashtable metaData = new Hashtable();
metaData.Add("ContentTypeId", "some CT ID");
metaData.Add("Your Custom Field", "Your custom value");
SPFile file = library.RootFolder.Files.Add(
"filename.fileextension",
bytearray,
metaData,
false);

How to upload an image file to Active Directory user profile in C#?

I need a method which will take an *.jpg image file and upload it to a user profile in the Active Directory of Windows AD 2003.
Also a method to retrieve the photo as stream or expose it as secure web service to be called by cross platform apps in java etc (Damn! am I asking too much!!!)
The file being uploaded will be a *.jpg which is basically a visual signature file created by a user.
Does anyone having any experience working with Active Directory in C# provide some information as to how this can be done with minimum implication related to security.
From the point of view of the Windows Active Directory Administrator what does he have to
do to make this possible.Changes/provisions to schema of user profile etc.
The image is being uploaded so that it can be later retrieved from the AD to be inserted into PDF document for signature purposes.
Can this be done in C#? Or is there any done libraries etc?
Here's a series of blog postings with code that shows how to do it:
(The first shows how to get a photo in, the second shows how to get it out)
Using the jpegPhoto attribute in AD - Part I
Using the jpegPhoto attribute in AD - Part II
EDIT: Here's a generic function implementing the code from Part I:
void AddPictureToUser(
string strDN, // User Distinguished Name, in the form "CN=Joe User,OU=Employees,DC=company,DC=local"
string strDCName, // Domain Controller, ie: "DC-01"
string strFileName // Picture file to open and import into AD
)
{
// Open file
System.IO.FileStream inFile = new System.IO.FileStream(strFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
// Retrive Data into a byte array variable
byte[] binaryData = new byte[inFile.Length];
int bytesRead = inFile.Read(binaryData, 0, (int)inFile.Length);
inFile.Close();
// Connect to AD
System.DirectoryServices.DirectoryEntry myUser = new System.DirectoryServices.DirectoryEntry(#"LDAP://" + strDCName + #"/" + strDN);
// Clear existing picture if exists
myUser.Properties["jpegPhoto"].Clear();
// Update attribute with binary data from file
myUser.Properties["jpegPhoto"].Add(binaryData);
myUser.CommitChanges();
}
EDIT: I found that in my organisation, the correct attribute to set was "thumbnailPhoto" like this:
myUser.Properties["thumbnailPhoto"].Add(binaryData);
This also seems to tbe the one that the commercial product Exclaimer is setting (but it might be only doing that in my organization)
The common AD attribute for a user photo is jpegPhoto but you can use what ever name you want
This sample shows the basic AD way to get and set an image stream. You need to flesh these methods out to be a useful class
Consider making your web service to just return the URL of the image. The request handler for that URL should then return the image with the correct content type etc. Much more useful in a web environment
using System;
using System.DirectoryServices;
using System.Collections;
using System.IO;
public class ADPhoto {
public void Set() {
try {
var de = new DirectoryEntry("LDAP://cn=username,cn=users,DC=domain, DC=com");
de.Username = "username";
de.Password = "password";
var forceAuth = de.NativeObject;
var fs = new FileStream("path\\photo.jpg", FileMode.Open);
var br = new BinaryReader(fs);
br.BaseStream.Seek(0, SeekOrigin.Begin);
byte[] ba = new byte[br.BaseStream.Length];
ba = br.ReadBytes((int)br.BaseStream.Length);
de.Properties["jpegPhoto"].Insert(0, ba);
de.CommitChanges();
}
catch(Exception ex) {
Console.WriteLine(ex.Message);
}
}
public Stream Get() {
var fs = new MemoryStream();
try {
var de = new DirectoryEntry("LDAP://cn=username,cn=users,DC=domain, DC=com");
de.Username = "username";
de.Password = "password";
var forceAuth = de.NativeObject;
var wr = new BinaryWriter(fs);
byte[] bb = (byte[])de.Properties["jpegPhoto"][0];
wr.Write(bb);
wr.Close();
}
catch (Exception e) {
Console.WriteLine(e.Message);
}
return fs;
}
}
Found an article that describes how to upload pictures to Active Directory and how to get them to show on the end-users computers.
http://blog.jocha.se/tech/ad-user-pictures-in-windows-10
Each Active Directory User Profile will have a home folder.
If you are not sure about this please checkout the below article
http://support.microsoft.com/kb/816313
I believe that you have to upload the image file to this directory.
Also if this doesn't solve your problem, please update if you find something else.
MNK...

Categories

Resources