C# – Update the “Created By” of a Sharepoint Document Library column via ClientContext

csharepoint-2013

I wanted to updated the Created By column in SharePoint via client context, but my code is not working. The column is a document library column.

I tried a few options. My first code block fails to update the field, but my second code block actually does the trick, but it couldn't manage to upload files bigger than 150 MB which my first code block is able to do.

Here is my first code block:

using (var ctx = new ClientContext(spSiteUrl))
{
    ctx.RequestTimeout = 1000000;
    Web web = ctx.Web;

    string strUser = "spDomain\\adminUser1";

    var file = ctx.Web.GetFileByServerRelativeUrl(newServerRelPath);
    var item = file.ListItemAllFields;

    //First approach and it doesn't work
    // -> Start
    FieldUserValue fuvUser = new FieldUserValue();
    User oUser = web.EnsureUser(strUser);
    ctx.Load(oUser,
    props=>props.Id,
    props=>props.LoginName);
    item["Author"] = oUser;
    item["Created_x0020_By"] = oUser;
    // -> End

    //Second approach and still it doesn't work
    // -> Start
    List list = web.GetList(spDocLibUrl);
    list.Fields.GetByInternalNameOrTitle("Author").ReadOnlyField = false;
    list.Fields.GetByInternalNameOrTitle("Created_x0020_By").ReadOnlyField = false;
    list.Update();
    item["Author"]=web.EnsureUser(strUser);
    item["Created_x0020_By"] = web.EnsureUser(strUser);
    // -> End

    item.Update();
    ctx.ExecuteQuery();

}

How do I update the Created By field?

Another approach I did on my code can actually update the Created By field, but my problem here is that I can't upload files bigger that 150 MB.

Here is my second code block:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite site = new SPSite(spSiteUrl))
    {
        using (SPWeb web = site.OpenWeb())
        {
            //read file in filestream
            System.IO.FileStream fStream = System.IO.File.OpenRead(filePath);
            byte[] contents = new byte[fStream.Length];
            fStream.Read(contents, 0, (int)fStream.Length);
            fStream.Close();

            web.AllowUnsafeUpdates = true;
            SPFolder rootFolder = web.GetFolder(spFolderUrl);

            string strUser = "spDomain\\adminUser1";
            SPUser userCreatedBy = web.EnsureUser(strUser);

            //This part sets the created by field successfully but fails to add files bigger than 150mb.
            SPFile file = rootFolder.Files.Add(item.Name, contents,userCreatedBy,userCreatedBy,DateTime.Now,DateTime.Now);

            int id = file.Item.ID;
            SPListItem listItem = file.Item;//docsLibrary.GetItemById(id);
            listItem["Created"] = item.CreationTime;
            listItem["Modified"] = item.LastWriteTime;
            listItem.Update();

            web.AllowUnsafeUpdates = false;
        }
    }
});

It's also obvious that my second code block doesn't have the RequestTimeOut settings. Maybe this could be the reason why it couldn't upload bigger files. I wanted to set the RequestTimeOut, but how do I add it in my code or is there any other better approach to do this?

Business requirement: Programmatically upload files bigger than 150 MB (300 MB, 800 MB and even 1 GB up) to SharePoint Document Library and set the Created By field to whoever is the author of the file from the local source folder.

Please let me know if there's anything that is not clear on my question so that I can update it.

Best Answer

Try setting MaxReceivedMessageSize:

SPWebService ws = SPWebService.ContentService;
SPClientRequestServiceSettings clientSettings = ws.ClientRequestServiceSettings;
clientSettings.MaxReceivedMessageSize = 10485760;
ws.Update();
Console.WriteLine(clientSettings.MaxReceivedMessageSize);

or use HTTP DAV:

ClientContext context = new ClientContext("http://spdevinwin");
using (FileStream fs = new FileStream(@"C:\Work\Files\17580_FAST2010_S03_Arch.pptx", FileMode.Open))
{
Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, "/documents/17580_FAST2010_S03_Arch from client OM.pptx", fs, true);
}

to change modified by use:

RunCodeWithNewClientContext((ctx, item) => {
    const string template = "i:0#.f|membership|{0}@<tenant>.onmicrosoft.com";
    var modifiedBy = ctx.Web.EnsureUser(string.Format(template, vm.ModifiedBy));
    var createdBy = ctx.Web.EnsureUser(string.Format(template, vm.CreatedBy));

    ctx.Load(modifiedBy);
    ctx.Load(createdBy);
    ctx.ExecuteQuery();

    item["Editor"] = modifiedBy.Id;
    var modifiedByField = new ListItemFormUpdateValue {
        FieldName = "Modified_x0020_By",
        FieldValue = modifiedBy.Id.ToString()
    };

    item["Author"] = createdBy.Id;
    var createdByField = new ListItemFormUpdateValue {
        FieldName = "Created_x0020_By",
        FieldValue = createdBy.Id.ToString()
    };

    item["Modified"] = vm.ModifiedAt.ToUniversalTime();
    item["Created"] = vm.CreatedAt.ToUniversalTime();

    // it doesn't matter if you add both modifiedByField and createdByField.
    // As long as the list is non-empty all changes appear to carry over.
    var updatedValues = new List<ListItemFormUpdateValue> { modifiedByField, createdByField };
    item.ValidateUpdateListItem(updatedValues, true, "Ignored on explicit checkin/checkout");
    ctx.ExecuteQuery();
});