0

0

I have a list of urls that are documents in a subfolder of a library.

When I go to update the metadata of a document in the library but not in a subfolder code works as expected.

But some documents in the list are in a subfolder. The URL has the fully qualified path to that document that includes the subfolder.

I can paste the url into a browser and open the document so I know it is correct, but when I get to the

context.Load(file, f.ListItemsAllFields); Context.ExecuteQuery(); -- Error Happens on URL of file in subfolder

I am getting an error stating "File Not Found."

See Code... Again works if file is in root of Library just not when file is in a subfolder.

/// <summary>
/// Updates SharePoint MetaData for a specific document
/// </summary>
/// <param name="urlfilepath">The URL including file name of the file to be updated</param>
/// <param name="values">this is a dictionary of propertyName and value to be updated.</param>
private void UpdateMetaData(string urlfilepath, string library,Dictionary<string, string> mydictionary)
{
    using (var context = new ClientContext(qsURLSite))
    {
        context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
        var web = context.Web;

        // Get drop off library and edit all items without making changes
        context.Load(web, w => w.Lists);
        context.ExecuteQuery();

        List dropOffLibrary = web.Lists.GetByTitle(library);


        context.Load(dropOffLibrary, dl => dl.RootFolder.Files);
        context.ExecuteQuery();

        var file = dropOffLibrary.RootFolder.Files.GetByUrl(urlfilepath);

        context.Load(file, f => f.ListItemAllFields);
        context.ExecuteQuery();

        Microsoft.SharePoint.Client.ListItem newItem = file.ListItemAllFields;


        foreach (KeyValuePair<string, string> entry in mydictionary)
        {
            // entry.Key has to be in the property list of that document
            // the name is very specific
            try
            {
                newItem[entry.Key] = entry.Value;
            }
            catch
            {
                // Key was not found in list
                // go to next key

            }
        }
        newItem.Update();
        //file.Update();
        context.Load(file);
        context.ExecuteQuery();

        context.Load(dropOffLibrary, dl => dl.RootFolder.Files);
        context.ExecuteQuery();
    }
}

2 Answers 2

0

You can get the file using a caml query.

private void UpdateMetaData(string urlfilepath, string library, Dictionary<string, string> mydictionary)
        {
            using (var context = new ClientContext(qsURLSite))
            {
                context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                var web = context.Web;

                // Get drop off library and edit all items without making changes
                context.Load(web, w => w.Lists);
                context.ExecuteQuery();

                List dropOffLibrary = web.Lists.GetByTitle(library);


                context.Load(dropOffLibrary);
                context.ExecuteQuery();

                //make sure urlfilepath is the relative path of the file
                CamlQuery camlQuery = new CamlQuery();
                camlQuery.ViewXml = @"<View Scope='RecursiveAll'>  
                                             <Query> 
                                               <Where><Eq><FieldRef Name='FileRef' /><Value Type='Text'>"+ urlfilepath + @"</Value></Eq></Where> 
                                            </Query> 
                                         </View> ";
                ListItemCollection itemCollection = dropOffLibrary.GetItems(camlQuery);


                if (itemCollection != null)
                {
                    context.Load(itemCollection);
                    context.ExecuteQuery();
                    if (itemCollection.Count > 0)
                    {

                        context.Load(itemCollection[0]);
                        context.ExecuteQuery();

                        var file = itemCollection[0].File;

                        context.Load(file, f => f.ListItemAllFields);
                        context.ExecuteQuery();

                        Microsoft.SharePoint.Client.ListItem newItem = file.ListItemAllFields;


                        foreach (KeyValuePair<string, string> entry in mydictionary)
                        {
                            // entry.Key has to be in the property list of that document
                            // the name is very specific
                            try
                            {
                                newItem[entry.Key] = entry.Value;
                            }

                            catch
                            {
                                // Key was not found in list
                                // go to next key

                            }
                        }
                        newItem.Update();
                        //file.Update();
                        context.Load(file);
                        context.ExecuteQuery();

                        context.Load(dropOffLibrary);
                        context.ExecuteQuery();
                    }
                }
            }
        }

RecursiveAll will get the files from subfolders as well. Just pass the relative URL in the caml query.

0

Here is what I ended up getting to work...

eq is a record number I needed to use to create the subfolder or look in that subfolder.

      /// <summary>
      /// This procedure uploads documents to the Authorizations Library
      /// </summary>
      /// <param name="filename">File Being Uploaded</param>
      /// <param name="p">file in bytes</param>
      /// <param name="library">Library to upload to</param>
      /// <returns></returns>
        private string UploadToSharePoint(string filename, byte[] p,string library)  //p is path to file to load
        {
            string newUrl;
            string siteUrl = string.Empty; 


            siteUrl = qsURL + @"/repository/current/";
            // Calculate block size in bytes.
            int blockSize = fileChunkSizeInMB * 1024 * 1024;



            //Insert Credentials

             Microsoft.SharePoint.Client.ClientContext context = new Microsoft.SharePoint.Client.ClientContext(siteUrl);

            context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            Microsoft.SharePoint.Client.Web site = context.Web;

            if (context.HasPendingRequest)
                context.ExecuteQuery();

            try
            {

                //Get the required RootFolder
                string barRootFolderRelativeUrl = library;

                // Getting Folder List to see if EQCode Folder Exists  If not create it.

                string eq = txtEQCode.Text;
                FolderCollection folders = site.GetFolderByServerRelativeUrl(barRootFolderRelativeUrl).Folders;   //list.RootFolder.Folders;
                context.Load(folders, fl => fl.Include(ct => ct.Name)
                .Where(ct => ct.Name == eq));
                context.ExecuteQuery();

                if (folders.Count < 1)  // Create Folder because it does not exist on SharePoint Library
                {
                    folders.Add(eq);
                    context.ExecuteQuery();
                }

                Microsoft.SharePoint.Client.Folder barFolder = site.GetFolderByServerRelativeUrl(barRootFolderRelativeUrl);
                Microsoft.SharePoint.Client.Folder currentRunFolder = site.GetFolderByServerRelativeUrl(barRootFolderRelativeUrl + "/" + eq);

                //Microsoft.SharePoint.Client.FileCreationInformation newFile = new Microsoft.SharePoint.Client.FileCreationInformation { Content = p, Url = filename, Overwrite = true };
                //Microsoft.SharePoint.Client.File uploadFile = currentRunFolder.Files.Add(newFile);

                MemoryStream stream = new MemoryStream(p);

                FileCreationInformation flciNewFile = new FileCreationInformation();

                // This is the key difference for the first case – using ContentStream property
                flciNewFile.ContentStream = stream;
                flciNewFile.Url = System.IO.Path.GetFileName(fixInvalidCharactersInFileName(filename));
                flciNewFile.Overwrite = false;
                Microsoft.SharePoint.Client.File uploadFile = currentRunFolder.Files.Add(flciNewFile);

                currentRunFolder.Update();
                context.Load(uploadFile);
                context.ExecuteQuery();

                newUrl = siteUrl + barRootFolderRelativeUrl + "/" + filename;

                // Set document properties
                // Have to check out document to upldate properties.

                uploadFile.CheckOut();

                Microsoft.SharePoint.Client.ListItem listItem = uploadFile.ListItemAllFields;

                // Sets up ListItem fields based on Content Type 
                // as each content type has a different set of Required Fields.

                SetUpListItems(listItem, EQCode);

                listItem["Title"] = filename;
                listItem.Update();

                uploadFile.CheckIn("File Uploaded Manually added metadata", Microsoft.SharePoint.Client.CheckinType.MinorCheckIn);
                context.ExecuteQuery();

                //Return the URL of the new uploaded file
                return newUrl;
            }
            catch (Exception e)
            {
                Page.ClientScript.RegisterStartupScript(this.GetType(), "Error Uploading!", "alert('" + e.Message + "');", true);
                return "FALSE";
            }
        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.