Adding extra backslashes in a file URL inside a field returns InvalidOperationException

I don’t want to make this post TL;DR, so I will try to keep it simple. I am trying to grab INCLUDETEXT fields from a document, replace the URL, and re-create/generate the field.

    private void ReplaceFieldCode(Field field, string newFieldCode)
    {
        Document doc = (Document)field.Start.Document;
        DocumentBuilder builder = new DocumentBuilder(doc);
        builder.MoveToField(field, true);

        RemoveField(field);
        builder.InsertField(newFieldCode);
    }


    private void RemoveField(Field field)
    {
        Node currentNode = field.Start;
        Node fieldEnd = field.End;

        while (currentNode != null && currentNode != fieldEnd)
        {
            Node nextNode = currentNode.NextPreOrder(currentNode.Document);
            currentNode.Remove();
            currentNode = nextNode;
        }
        fieldEnd.Remove();
    }

For my new field code, I am using a UNC pathname, and excel expects this to have two backslashes, but when I replace the backslashes, I get an error.

        public async Task<string> DownloadFileToTempAsync(string url)
        {
            var stream = await DownloadFileAsync(url);
            var fileExtension = Path.GetExtension(new Uri(url).AbsolutePath);
            string tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + fileExtension);

            using (var fileStream = File.Create(tempFilePath))
            {
                await stream.CopyToAsync(fileStream);
            }
            tempFilePath = tempFilePath.Replace("\\", "\\\\");

            return tempFilePath;
        }

This error occurs at builder.InsertField(newFieldCode); and only occurs when I include the .Replace(). I’ve checked the difference between the two strings, and the only difference is that the second one has four backslashes instead of 2. I’m at a loss as to why its throwing this error.

@amattice If possible could you please also attach your input document and provide field code that causes the mentioned exception?

Also, why do you use a custom method for removing a field instead a built in Field.Remove() method?

In addition, if you goal is to update INCLUDETEXT field source path, you can simply set FieldIncludeText.SourceFullName property.

1 Like

@alexey.noskov You are right…for some reason I was under the assumption I needed to replace the field entirely. Simplifying that seems to have also fixed my problem with backslash characters. Not sure if you could help me with this as well, but I am calling document.UpdateFields(), but I download the file and it still is not generated content.

    public async Task ReplaceIncludeTextFieldsWithNewContent(Document document, ManifestModel manifest)
    {
        foreach (Field field in document.Range.Fields)
        {
            if (field.Type == FieldType.FieldIncludeText)
            {
                FieldIncludeText includeTextField = (FieldIncludeText)field;
                string fieldCode = field.GetFieldCode();

                var placeholderNameMatch = Regex.Match(fieldCode, "\"([^\"\\:]+)\\:.*?\"");
                if (placeholderNameMatch.Success)
                {
                    string placeholderName = placeholderNameMatch.Groups[1].Value;
                    var placeholder = manifest.Placeholders.FirstOrDefault(p => p.Placeholder == placeholderName);
                    if (placeholder != null && !string.IsNullOrWhiteSpace(placeholder.ContentUrl))
                    {
                        string tempFilePath = await _fileManagementService.DownloadFileToTempAsync(placeholder.ContentUrl);
                        includeTextField.SourceFullName = tempFilePath;
                    }
                }
            }
        }
        document.UpdateFields();
    }

@amattice Please make sure the files specified in the INCLUDETEXT fields are accessible. I have tested the scenario on my side using a simple document with one INCLUDETEXT field and the following code:

Document doc = new Document(@"C:\Temp\in.docx");

// Get the first INCLUDETEXT field.
FieldIncludeText includeText = doc.Range.Fields.Where(f => f.Type == FieldType.FieldIncludeText)
    .Cast<FieldIncludeText>().First();

// Update INCLUDETEXT field source.
includeText.SourceFullName = @"C:\Temp\src2.txt";

doc.UpdateFields();

doc.Save(@"C:\Temp\out.docx");

The field is updated properly.

1 Like

@alexey.noskov It appears that the links were correct but my word was set to automatically show the INCLUDETEXT on startup instead of the rendered content. I will have to look to see if there is a way to lock the fields in the rendered state, so users cannot view the field information.

@amattice Usually, MS Word automatically updates fields, which are marked as “dirty”. Please make sure Field.IsDirty property is set to false after updating the field.