USING IRONWORD

ASP .NET Core Import & Export A Word File

Published December 16, 2024
Share:

Introduction

This guide explores how to import existing Word documents, display their content, and create documents from scratch using the IronWord library. By the end of this tutorial, you'll have created an ASP.NET Core web application that can:

  1. Upload and read Word documents
  2. Display the content of these documents in a textbox
  3. Export the Docx file

This project is perfect for developers who need to integrate Word document processing into their web applications, whether for document management systems, report generators, or any other scenario involving Microsoft Word files.

Prerequisites

To follow along with this tutorial, you should have:

  • Basic knowledge of C# and ASP.NET Core
  • Visual Studio 2019 or later installed (alternatively, you can use Visual Studio Code with the C# extension)
  • .NET Core SDK 3.1 or later

Don't worry if you're not an expert in these technologies – we'll guide you through each step of the process!

What is IronWord?

IronWord is a .NET library allowing developers to programmatically read, manipulate, and create Microsoft Word documents. It provides a high-level API that simplifies working with Word files, making it an excellent choice for our project.

Some key features of IronWord include:

  • Reading and writing various Word formats (DOCX, DOC, etc.)
  • Manipulating document content and structure
  • Formatting text and paragraphs
  • Working with tables, images, and other document elements
  • Mail Merge process for the Documents
  • Converting a Word document to a PDF document with ease, so you can take your final Word documents and make them easy to share PDF files

Now that we have an overview of what we're building and the tools we'll use, let's dive into setting up our project!

2. Setting up the project

In this section, we'll create a new ASP.NET Core project and install the necessary packages to work with IronWord.

2.1 Creating a new ASP.NET Core Project

  1. Open Visual Studio 2019 or later.
  2. Click on "Create a new project".

    1. Search for "ASP.NET Core Web Application" and select it.

    Broken image Add from Pixabay, select from your files or drag and drop an image here.

  3. Click "Next".
  4. Name your project "WordDocumentProcessor" (or any name you prefer).
  5. Select the .NET Framework and a location for your project and click "Create".

2.2 Installing the IronWord NuGet Package

Now that we have our project set up, let's add the IronWord library:

  1. Right-click on your project in the Solution Explorer.
  2. Select "Manage NuGet Packages".

    1. In the "Browse" tab, search for "IronWord".

    Broken image Add from Pixabay, select from your files or drag and drop an image here.

  3. Look for the official IronWord package.
  4. Click "Install" to add it to your project.

2.3 Updating the Existing Controller and View

Let's update our existing structure to incorporate the document processing functionality:

  1. We'll be using the existing HomeController.cs in the Controllers folder for our document processing logic.

  2. We'll update the existing Index.cshtml view in the Views/Home folder to include the document upload and display functionality.

Now that we have our project set up and the IronWord package installed, we're ready to start implementing the document import and export functionality. We'll be adding new methods to our HomeController and modifying the Index view to handle these features. In the next section, we'll focus on importing Word documents and displaying their content, utilizing our existing controller and view structure. We can add mail merge functionality as well but we'll focus on import and export documents in this article.

3. Importing Word Documents

In this section, we'll explore how to implement a feature for importing and processing Word documents in an ASP.NET MVC application. We'll cover both the user interface design and the back-end controller logic.

3.1 User Interface Design

The user interface for importing Word documents is designed to be intuitive and visually appealing. Let's break down the key components of the UI:

3.1.1 Upload Area

The upload area is the focal point of the interface, inviting users to select and upload their Word documents. Here's how it's structured:

<div class="upload-area">
    <svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
    <polyline points="14 2 14 8 20 8"></polyline>
    <line x1="16" y1="13" x2="8" y2="13"></line>
    <line x1="16" y1="17" x2="8" y2="17"></line>
    <polyline points="10 9 9 9 8 9"></polyline>
</svg>
    <p>Choose a Word document</p>
    <label for="fileInput" class="choose-file">Choose File</label>
    <p class="file-info">.DOC or .DOCX (MAX. 10MB)</p>
    <button id="uploadBtn" class="upload-button">Upload and Process</button>
</div>
<div class="upload-area">
    <svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
    <polyline points="14 2 14 8 20 8"></polyline>
    <line x1="16" y1="13" x2="8" y2="13"></line>
    <line x1="16" y1="17" x2="8" y2="17"></line>
    <polyline points="10 9 9 9 8 9"></polyline>
</svg>
    <p>Choose a Word document</p>
    <label for="fileInput" class="choose-file">Choose File</label>
    <p class="file-info">.DOC or .DOCX (MAX. 10MB)</p>
    <button id="uploadBtn" class="upload-button">Upload and Process</button>
</div>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<div class="upload-area"> <svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> <line x1="16" y1="13" x2="8" y2="13"></line> <line x1="16" y1="17" x2="8" y2="17"></line> <polyline points="10 9 9 9 8 9"></polyline> </svg> <p> Choose a Word document</p> <label for="fileInput" class="choose-file"> Choose File</label> <p class="file-info">.DOC @or.DOCX(MAX. 10MB)</p> <button id="uploadBtn" class="upload-button"> Upload @and Process</button> </div>
VB   C#

This code creates a visually appealing upload area with a file icon, a hidden file input, and a styled label acting as the file selection button. It also includes information about accepted file types and a button to initiate the upload and processing.

3.1.2 Content Display Area

After processing the document, its content is displayed in a dedicated area:

<div class="content-wrapper">
    <h2>Document Content:</h2>
    <div id="documentContent" class="content-area">
        No content to display.
    </div>
</div>
<div class="content-wrapper">
    <h2>Document Content:</h2>
    <div id="documentContent" class="content-area">
        No content to display.
    </div>
</div>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<div class="content-wrapper"> <h2> Document Content:</h2> <div id="documentContent" class="content-area"> No content @to display. </div> </div>
VB   C#

This section provides a scrollable area to display the processed document content.

3.2 Controller Implementation

The HomeController handles the server-side logic for importing and processing Word documents. Let's examine the key methods:

3.2.1 UploadAndProcess Method

This method is responsible for handling the file upload and processing:

[HttpPost]
public IActionResult UploadAndProcess(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return Json(new { success = false, message = "No file uploaded." });
    }
    var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
    if (fileExtension != ".doc" && fileExtension != ".docx")
    {
        return Json(new { success = false, message = "Invalid file type. Please upload a .doc or .docx file." });
    }
    try
    {
        var tempFilePath = Path.GetTempFileName();
        using (var stream = new FileStream(tempFilePath, FileMode.Create))
        {
            file.CopyTo(stream);
        }
        StringBuilder contentBuilder = new StringBuilder();
        WordDocument doc = new WordDocument(tempFilePath);
        foreach (Paragraph paragraph in doc.Paragraphs)
        {
            foreach (Text textRun in paragraph.Texts)
            {
                contentBuilder.AppendLine(textRun.Text);
            }
            contentBuilder.AppendLine(); // Add an extra line between paragraphs
        }
        System.IO.File.Delete(tempFilePath); // Clean up the temporary file
        return Json(new { success = true, content = FormatContentAsHtml(contentBuilder.ToString()) });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error processing document");
        return Json(new { success = false, message = "An error occurred while processing the document." });
    }
}
[HttpPost]
public IActionResult UploadAndProcess(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return Json(new { success = false, message = "No file uploaded." });
    }
    var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
    if (fileExtension != ".doc" && fileExtension != ".docx")
    {
        return Json(new { success = false, message = "Invalid file type. Please upload a .doc or .docx file." });
    }
    try
    {
        var tempFilePath = Path.GetTempFileName();
        using (var stream = new FileStream(tempFilePath, FileMode.Create))
        {
            file.CopyTo(stream);
        }
        StringBuilder contentBuilder = new StringBuilder();
        WordDocument doc = new WordDocument(tempFilePath);
        foreach (Paragraph paragraph in doc.Paragraphs)
        {
            foreach (Text textRun in paragraph.Texts)
            {
                contentBuilder.AppendLine(textRun.Text);
            }
            contentBuilder.AppendLine(); // Add an extra line between paragraphs
        }
        System.IO.File.Delete(tempFilePath); // Clean up the temporary file
        return Json(new { success = true, content = FormatContentAsHtml(contentBuilder.ToString()) });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error processing document");
        return Json(new { success = false, message = "An error occurred while processing the document." });
    }
}
<HttpPost>
Public Function UploadAndProcess(ByVal file As IFormFile) As IActionResult
	If file Is Nothing OrElse file.Length = 0 Then
		Return Json(New With {
			Key .success = False,
			Key .message = "No file uploaded."
		})
	End If
	Dim fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant()
	If fileExtension <> ".doc" AndAlso fileExtension <> ".docx" Then
		Return Json(New With {
			Key .success = False,
			Key .message = "Invalid file type. Please upload a .doc or .docx file."
		})
	End If
	Try
		Dim tempFilePath = Path.GetTempFileName()
		Using stream = New FileStream(tempFilePath, FileMode.Create)
			file.CopyTo(stream)
		End Using
		Dim contentBuilder As New StringBuilder()
		Dim doc As New WordDocument(tempFilePath)
		For Each paragraph As Paragraph In doc.Paragraphs
			For Each textRun As Text In paragraph.Texts
				contentBuilder.AppendLine(textRun.Text)
			Next textRun
			contentBuilder.AppendLine() ' Add an extra line between paragraphs
		Next paragraph
		System.IO.File.Delete(tempFilePath) ' Clean up the temporary file
		Return Json(New With {
			Key .success = True,
			Key .content = FormatContentAsHtml(contentBuilder.ToString())
		})
	Catch ex As Exception
		_logger.LogError(ex, "Error processing document")
		Return Json(New With {
			Key .success = False,
			Key .message = "An error occurred while processing the document."
		})
	End Try
End Function
VB   C#

This method performs the following tasks:

  1. Validates the uploaded file, ensuring it's in the correct file format (DOC or DOCX)
  2. Checks for the correct file extension
  3. Processes the document using the IronWord library
  4. Returns the formatted content as JSON

3.2.2 FormatContentAsHtml Method

This private method formats the extracted content into HTML:

private string FormatContentAsHtml(string content)
{
    var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
    var htmlBuilder = new StringBuilder();
    htmlBuilder.Append("<div class='document-content'>");
    foreach (var line in lines)
    {
        if (string.IsNullOrWhiteSpace(line))
        {
            htmlBuilder.Append("<p> </p>");
        }
        else
        {
            htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>");
        }
    }
    htmlBuilder.Append("</div>");
    return htmlBuilder.ToString();
}
private string FormatContentAsHtml(string content)
{
    var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
    var htmlBuilder = new StringBuilder();
    htmlBuilder.Append("<div class='document-content'>");
    foreach (var line in lines)
    {
        if (string.IsNullOrWhiteSpace(line))
        {
            htmlBuilder.Append("<p> </p>");
        }
        else
        {
            htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>");
        }
    }
    htmlBuilder.Append("</div>");
    return htmlBuilder.ToString();
}
Private Function FormatContentAsHtml(ByVal content As String) As String
	Dim lines = content.Split( { Environment.NewLine }, StringSplitOptions.None)
	Dim htmlBuilder = New StringBuilder()
	htmlBuilder.Append("<div class='document-content'>")
	For Each line In lines
		If String.IsNullOrWhiteSpace(line) Then
			htmlBuilder.Append("<p> </p>")
		Else
			htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>")
		End If
	Next line
	htmlBuilder.Append("</div>")
	Return htmlBuilder.ToString()
End Function
VB   C#

This method ensures the document content is properly formatted as HTML, with each line wrapped in paragraph tags and empty lines preserved.

3.3 Client-Side JavaScript

To handle the file upload and display the processed content, we use JavaScript:

uploadBtn.addEventListener('click', () => {
    const file = fileInput.files[0];
    if (!file) {
        alert('Please select a file first.');
        return;
    }
    const formData = new FormData();
    formData.append('file', file);
    uploadBtn.disabled = true;
    uploadBtn.textContent = 'Processing...';
    documentContent.innerHTML = 'Processing document...';
    fetch('/Home/UploadAndProcess', {
        method: 'POST',
        body: formData
    })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                documentContent.innerHTML = data.content;
            } else {
                documentContent.innerHTML = `<p>Error: ${data.message}</p>`;
            }
        })
        .catch(error => {
            console.error('Error:', error);
            documentContent.innerHTML = '<p>An error occurred while processing the document.</p>';
        })
        .finally(() => {
            uploadBtn.disabled = false;
            uploadBtn.textContent = 'Upload and Process';
        });
});
uploadBtn.addEventListener('click', () => {
    const file = fileInput.files[0];
    if (!file) {
        alert('Please select a file first.');
        return;
    }
    const formData = new FormData();
    formData.append('file', file);
    uploadBtn.disabled = true;
    uploadBtn.textContent = 'Processing...';
    documentContent.innerHTML = 'Processing document...';
    fetch('/Home/UploadAndProcess', {
        method: 'POST',
        body: formData
    })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                documentContent.innerHTML = data.content;
            } else {
                documentContent.innerHTML = `<p>Error: ${data.message}</p>`;
            }
        })
        .catch(error => {
            console.error('Error:', error);
            documentContent.innerHTML = '<p>An error occurred while processing the document.</p>';
        })
        .finally(() => {
            uploadBtn.disabled = false;
            uploadBtn.textContent = 'Upload and Process';
        });
});
uploadBtn.addEventListener( 'click', () =>
If True Then
	const file = fileInput.files(0)
	If Not file Then
		alert( 'Please select a file first.');
		Return
	End If
	const formData = New FormData()
	formData.append( 'file', file);
	uploadBtn.disabled = True
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'	uploadBtn.textContent = 'Processing...'; documentContent.innerHTML = 'Processing document...'; fetch('/Home/UploadAndProcess', { method: 'POST', body: formData }).@then(response => response.json()).@then(data => { if(data.success) { documentContent.innerHTML = data.content; } else { documentContent.innerHTML = `<p> @Error: ${data.message}</p>`; } }).catch(@error => { console.@error('@Error:', @error); documentContent.innerHTML = '<p> An @error occurred while processing the document.</p>'; }).finally(() => { uploadBtn.disabled = False; uploadBtn.textContent = 'Upload @and Process'; }); });
VB   C#

This JavaScript code handles the file upload process, sends the file to the server for processing, and updates the UI with the processed content or error messages.

3.4 Styling the User Interface

The application uses custom CSS to create an attractive and user-friendly interface.

<style>
    body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background-color: #f7f7f7;
        color: #333;
    }
    .container {
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
        padding-top: 0.5rem;
    }
    h1 {
        font-weight: 300;
        color: #2c3e50;
        text-align: center;
        margin-bottom: 1rem;
    }
    .lead {
        text-align: center;
        color: #7f8c8d;
        margin-bottom: 2rem;
    }
    .upload-area {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 2rem;
        text-align: center;
        margin-bottom: 2rem;
        transition: all 0.3s ease;
    }
        .upload-area:hover {
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
        }
    .file-icon {
        width: 64px;
        height: 64px;
        margin-bottom: 1rem;
        color: #3498db;
    }
    .choose-file {
        background-color: #ecf0f1;
        color: #2c3e50;
        border: none;
        padding: 0.5rem 1rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
    }
        .choose-file:hover {
            background-color: #d5dbdb;
        }
    .file-info {
        font-size: 0.9em;
        color: #95a5a6;
        margin-top: 0.5rem;
    }
    .upload-button {
        background-color: #3498db;
        color: white;
        border: none;
        padding: 0.75rem 1.5rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
        margin-top: 1rem;
    }
        .upload-button:hover {
            background-color: #2980b9;
        }
    .content-wrapper {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 1rem;
        margin-top: 2rem;
    }
    .content-area {
        max-height: 300px;
        overflow-y: auto;
        padding: 1rem;
        background-color: #f9f9f9;
        border-radius: 4px;
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        font-size: 14px;
        line-height: 1.6;
    }
        .content-area::-webkit-scrollbar {
            width: 8px;
        }
        .content-area::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 4px;
        }
        .content-area::-webkit-scrollbar-thumb {
            background: #bdc3c7;
            border-radius: 4px;
        }
            .content-area::-webkit-scrollbar-thumb:hover {
                background: #95a5a6;
            }
    .document-content p {
        margin: 0 0 10px 0;
    }
</style>
<style>
    body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background-color: #f7f7f7;
        color: #333;
    }
    .container {
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
        padding-top: 0.5rem;
    }
    h1 {
        font-weight: 300;
        color: #2c3e50;
        text-align: center;
        margin-bottom: 1rem;
    }
    .lead {
        text-align: center;
        color: #7f8c8d;
        margin-bottom: 2rem;
    }
    .upload-area {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 2rem;
        text-align: center;
        margin-bottom: 2rem;
        transition: all 0.3s ease;
    }
        .upload-area:hover {
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
        }
    .file-icon {
        width: 64px;
        height: 64px;
        margin-bottom: 1rem;
        color: #3498db;
    }
    .choose-file {
        background-color: #ecf0f1;
        color: #2c3e50;
        border: none;
        padding: 0.5rem 1rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
    }
        .choose-file:hover {
            background-color: #d5dbdb;
        }
    .file-info {
        font-size: 0.9em;
        color: #95a5a6;
        margin-top: 0.5rem;
    }
    .upload-button {
        background-color: #3498db;
        color: white;
        border: none;
        padding: 0.75rem 1.5rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
        margin-top: 1rem;
    }
        .upload-button:hover {
            background-color: #2980b9;
        }
    .content-wrapper {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 1rem;
        margin-top: 2rem;
    }
    .content-area {
        max-height: 300px;
        overflow-y: auto;
        padding: 1rem;
        background-color: #f9f9f9;
        border-radius: 4px;
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        font-size: 14px;
        line-height: 1.6;
    }
        .content-area::-webkit-scrollbar {
            width: 8px;
        }
        .content-area::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 4px;
        }
        .content-area::-webkit-scrollbar-thumb {
            background: #bdc3c7;
            border-radius: 4px;
        }
            .content-area::-webkit-scrollbar-thumb:hover {
                background: #95a5a6;
            }
    .document-content p {
        margin: 0 0 10px 0;
    }
</style>
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'(Of style) body
'{
''INSTANT VB TODO TASK: The following line uses invalid syntax:
''		font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f7f7f7; color: #333; } .container { max-width: 800px; margin: 0 auto; padding: 2rem; padding-top: 0.5rem; } h1 { font-weight: 300; color: #2c3e50; text-align: center; margin-bottom: 1rem; } .lead { text-align: center; color: #7f8c8d; margin-bottom: 2rem; } .upload-area { background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 2rem; text-align: center; margin-bottom: 2rem; transition: all 0.3s ease; } .upload-area:hover { box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); } .file-icon { width: 64px; height: 64px; margin-bottom: 1rem; color: #3498db; } .choose-file { background-color: #ecf0f1; color: #2c3e50; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; transition: background-color 0.3s ease; } .choose-file:hover { background-color: #d5dbdb; } .file-info { font-size: 0.9em; color: #95a5a6; margin-top: 0.5rem; } .upload-button { background-color: #3498db; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 4px; cursor: pointer; transition: background-color 0.3s ease; margin-top: 1rem; } .upload-button:hover { background-color: #2980b9; } .content-wrapper { background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 1rem; margin-top: 2rem; } .content-area { max-height: 300px; overflow-y: auto; padding: 1rem; background-color: #f9f9f9; border-radius: 4px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 14px; line-height: 1.6; } .content-area::-webkit-scrollbar { width: 8px; } .content-area::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 4px; } .content-area::-webkit-scrollbar-thumb { background: #bdc3c7; border-radius: 4px; } .content-area::-webkit-scrollbar-thumb:hover { background: #95a5a6; } .document-content p { margin: 0 0 10px 0; } </style>
VB   C#

This CSS creates a clean, modern look with a light color scheme. The upload area features a white background with subtle shadow effects, while the content area has a scrollable design with a light grey background. Using border-radius and box-shadow properties adds depth and visual interest to the interface elements.

4. Exporting Word Documents

As we continue to enhance our Word Document Processor, let's add the ability to export documents. This feature will allow users to generate a new Word document from our application.

4.1 Updating the User Interface

First, we'll add an "Export" option to our navigation bar. Open the _Layout.cshtml file in the Views/Shared folder and locate the

element. Let's add a new list item for our export function:

<li class="nav-item">
    <a class="nav-link" id="exportLink" href="#" onclick="exportDocument(); return false;"><i class="fas fa-file-export"></i> Export</a>
</li>
<li class="nav-item">
    <a class="nav-link" id="exportLink" href="#" onclick="exportDocument(); return false;"><i class="fas fa-file-export"></i> Export</a>
</li>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<li class="nav-item"> <a class="nav-link" id="exportLink" href="#" onclick="exportDocument(); return false;"><i class="fas fa-file-export"></i> Export</a> </li>
VB   C#

We're using Font Awesome for the icon, so ensure we have the CSS link in our

section. This code adds an "Export" link to the navigation bar. It uses Font Awesome for the icon and calls the exportDocument() function when clicked. The href="#" and return false prevent the default link behavior.

4.2 Implementing Client-Side Export Logic

Now, let's add the JavaScript function that will handle the export process. At the bottom of our _Layout.cshtml file, just before the closing

tag, we'll add the following script:

<script>
function exportDocument() {
    $.ajax({
        url: '/Home/ExportWordDocument',
        type: 'POST',
        success: function (response) {
            if (response.success) {
                var fileName = prompt("Enter a name for the document (without extension):", "ExportedDocument");
                if (fileName === null) {
                    return;
                }
                fileName = (fileName.trim() || "ExportedDocument").replace(/\.[^/.]+$/, "") + ".docx";
                var a = document.createElement('a');
                a.style.display = 'none';
                a.href = '/Home/DownloadFile?tempFilePath=' + encodeURIComponent(response.tempFilePath) + '&userFileName=' + encodeURIComponent(fileName);
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            } else {
                alert('Failed to export document: ' + response.message);
            }
        },
        error: function () {
            alert('An error occurred while exporting the document.');
        }
    });
}
</script>
<script>
function exportDocument() {
    $.ajax({
        url: '/Home/ExportWordDocument',
        type: 'POST',
        success: function (response) {
            if (response.success) {
                var fileName = prompt("Enter a name for the document (without extension):", "ExportedDocument");
                if (fileName === null) {
                    return;
                }
                fileName = (fileName.trim() || "ExportedDocument").replace(/\.[^/.]+$/, "") + ".docx";
                var a = document.createElement('a');
                a.style.display = 'none';
                a.href = '/Home/DownloadFile?tempFilePath=' + encodeURIComponent(response.tempFilePath) + '&userFileName=' + encodeURIComponent(fileName);
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            } else {
                alert('Failed to export document: ' + response.message);
            }
        },
        error: function () {
            alert('An error occurred while exporting the document.');
        }
    });
}
</script>
Private Function exportDocument() As [function](Of script)
	$.ajax({ url: '/Home/ExportWordDocument', type: 'POST', success: @function(response) { if(response.success) { var fileName = prompt("Enter a name for the document (without extension):", "ExportedDocument"); if(fileName === Nothing) { Return; } fileName = (fileName.trim() || "ExportedDocument").replace(/\.[^/.]+$/, "") + ".docx"; var a = document.createElement("a"c); a.style.display = 'none'; a.href = '/Home/System.Nullable<DownloadFile>tempFilePath=' + encodeURIComponent(response.tempFilePath) + '&userFileName=' + encodeURIComponent(fileName); document.body.appendChild(a); a.click(); document.body.removeChild(a); } else { alert('Failed @to export document: ' + response.message); } }, @error: @function() { alert('An @error occurred while exporting the document.'); } });
 End Function
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'</script>
VB   C#

This JavaScript function sends an AJAX POST request to the server to create a Word document. On success, it prompts the user for a file name and then creates a temporary link to download the file. The link is automatically clicked and then removed from the DOM. If there's an error at any stage, an alert is shown to the user.

4.3 Adding Server-Side Export Functionality

Now, let's implement the server-side logic. Open the HomeController.cs file in the Controllers folder. We'll add two new methods to handle the export process.

First, let's add the method to create the Word document:

[HttpPost]
public IActionResult ExportWordDocument()
{
    try
    {
        WordDocument doc = new WordDocument();
        doc.AddText("Test Word");
        string tempFileName = $"TempDoc_{Guid.NewGuid()}.docx";
        string tempFilePath = Path.Combine(_environment.WebRootPath, "TempFiles", tempFileName);
        Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath));
        doc.SaveAs(tempFilePath);
        return Json(new { success = true, tempFilePath = $"/TempFiles/{tempFileName}" });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error exporting Word document");
        return Json(new { success = false, message = "An error occurred while exporting the document." });
    }
}
[HttpPost]
public IActionResult ExportWordDocument()
{
    try
    {
        WordDocument doc = new WordDocument();
        doc.AddText("Test Word");
        string tempFileName = $"TempDoc_{Guid.NewGuid()}.docx";
        string tempFilePath = Path.Combine(_environment.WebRootPath, "TempFiles", tempFileName);
        Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath));
        doc.SaveAs(tempFilePath);
        return Json(new { success = true, tempFilePath = $"/TempFiles/{tempFileName}" });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error exporting Word document");
        return Json(new { success = false, message = "An error occurred while exporting the document." });
    }
}
<HttpPost>
Public Function ExportWordDocument() As IActionResult
	Try
		Dim doc As New WordDocument()
		doc.AddText("Test Word")
		Dim tempFileName As String = $"TempDoc_{Guid.NewGuid()}.docx"
		Dim tempFilePath As String = Path.Combine(_environment.WebRootPath, "TempFiles", tempFileName)
		Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath))
		doc.SaveAs(tempFilePath)
		Return Json(New With {
			Key .success = True,
			Key .tempFilePath = $"/TempFiles/{tempFileName}"
		})
	Catch ex As Exception
		_logger.LogError(ex, "Error exporting Word document")
		Return Json(New With {
			Key .success = False,
			Key .message = "An error occurred while exporting the document."
		})
	End Try
End Function
VB   C#

This method creates a new Word document using the IronWord library, adds some test text, and saves it to a temporary file with a unique name. It returns a JSON object with the success status and the path to the temporary file. If an error occurs, it logs the exception and returns a failure message.

Next, let's add the method to handle the file download:

[HttpGet]
public IActionResult DownloadFile(string tempFilePath, string userFileName)
{
    try
    {
        string fullPath = Path.Combine(_environment.WebRootPath, tempFilePath.TrimStart('/'));
        if (!System.IO.File.Exists(fullPath))
        {
            return NotFound();
        }
        byte[] fileBytes = System.IO.File.ReadAllBytes(fullPath);
        System.IO.File.Delete(fullPath);
        string fileName = !string.IsNullOrEmpty(userFileName) ? userFileName : "ExportedDocument.docx";
        return File(fileBytes, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileName);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error downloading file");
        return BadRequest("An error occurred while downloading the file.");
    }
}
[HttpGet]
public IActionResult DownloadFile(string tempFilePath, string userFileName)
{
    try
    {
        string fullPath = Path.Combine(_environment.WebRootPath, tempFilePath.TrimStart('/'));
        if (!System.IO.File.Exists(fullPath))
        {
            return NotFound();
        }
        byte[] fileBytes = System.IO.File.ReadAllBytes(fullPath);
        System.IO.File.Delete(fullPath);
        string fileName = !string.IsNullOrEmpty(userFileName) ? userFileName : "ExportedDocument.docx";
        return File(fileBytes, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileName);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error downloading file");
        return BadRequest("An error occurred while downloading the file.");
    }
}
<HttpGet>
Public Function DownloadFile(ByVal tempFilePath As String, ByVal userFileName As String) As IActionResult
	Try
		Dim fullPath As String = Path.Combine(_environment.WebRootPath, tempFilePath.TrimStart("/"c))
		If Not System.IO.File.Exists(fullPath) Then
			Return NotFound()
		End If
		Dim fileBytes() As Byte = System.IO.File.ReadAllBytes(fullPath)
		System.IO.File.Delete(fullPath)
		Dim fileName As String = If(Not String.IsNullOrEmpty(userFileName), userFileName, "ExportedDocument.docx")
		Return File(fileBytes, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileName)
	Catch ex As Exception
		_logger.LogError(ex, "Error downloading file")
		Return BadRequest("An error occurred while downloading the file.")
	End Try
End Function
VB   C#

This method retrieves the temporary file created by ExportWordDocument, reads its contents into a byte array, and then deletes the temporary file. It uses the provided user filename or a default name if none is provided. The method then returns the file content as a downloadable Word document. If the file is not found or an error occurs, appropriate HTTP responses are returned.

4.4 Enhancing the Application's Visual Design

To improve the overall look and feel of our Word Document Processor, we've added custom CSS directly in the _Layout.cshtml file. Let's examine the styling we've implemented:

<style>
    :root {
        --primary-color: #3498db;
        --text-color: #333;
        --bg-color: #f8f9fa;
        --nav-bg: #fff;
        --nav-text: #2c3e50;
        --nav-hover: #3498db;
    }
    body {
        font-family: 'Segoe UI', sans-serif;
        background-color: var(--bg-color);
        color: var(--text-color);
        line-height: 1.6;
    }
    .navbar { background-color: var(--nav-bg); }
    .navbar-brand {
        font-size: 1.5rem;
        font-weight: 700;
        color: var(--primary-color);
        margin-right: 2rem;
    }
    .navbar-nav { margin-left: auto; }
    .navbar-nav .nav-item { margin-left: 1rem; }
    .navbar-nav .nav-link {
        color: var(--nav-text);
        font-weight: 500;
        transition: all 0.3s ease;
        padding: 0.5rem 1rem;
        border-radius: 4px;
    }
    .navbar-nav .nav-link:hover, .navbar-nav .nav-link.active {
        color: var(--primary-color);
        background-color: rgba(52, 152, 219, 0.1);
    }
    .navbar-nav .nav-link i {
        margin-right: 0.5rem;
        font-size: 1.1em;
    }
    .centered-container {
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
    }
    .footer {
        background-color: var(--nav-bg);
        border-top: 1px solid #ecf0f1;
        font-size: 0.9em;
        color: var(--nav-text);
    }
    .footer a {
        color: var(--primary-color);
        text-decoration: none;
        transition: color 0.3s ease;
    }
    .footer a:hover { color: var(--nav-hover); }
    @@media (max-width: 576px) {
        .navbar-nav {
            margin-left: 0;
            margin-top: 1rem;
        }
        .navbar-nav .nav-item {
            margin-left: 0;
            margin-bottom: 0.5rem;
        }
    }
</style>
<style>
    :root {
        --primary-color: #3498db;
        --text-color: #333;
        --bg-color: #f8f9fa;
        --nav-bg: #fff;
        --nav-text: #2c3e50;
        --nav-hover: #3498db;
    }
    body {
        font-family: 'Segoe UI', sans-serif;
        background-color: var(--bg-color);
        color: var(--text-color);
        line-height: 1.6;
    }
    .navbar { background-color: var(--nav-bg); }
    .navbar-brand {
        font-size: 1.5rem;
        font-weight: 700;
        color: var(--primary-color);
        margin-right: 2rem;
    }
    .navbar-nav { margin-left: auto; }
    .navbar-nav .nav-item { margin-left: 1rem; }
    .navbar-nav .nav-link {
        color: var(--nav-text);
        font-weight: 500;
        transition: all 0.3s ease;
        padding: 0.5rem 1rem;
        border-radius: 4px;
    }
    .navbar-nav .nav-link:hover, .navbar-nav .nav-link.active {
        color: var(--primary-color);
        background-color: rgba(52, 152, 219, 0.1);
    }
    .navbar-nav .nav-link i {
        margin-right: 0.5rem;
        font-size: 1.1em;
    }
    .centered-container {
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
    }
    .footer {
        background-color: var(--nav-bg);
        border-top: 1px solid #ecf0f1;
        font-size: 0.9em;
        color: var(--nav-text);
    }
    .footer a {
        color: var(--primary-color);
        text-decoration: none;
        transition: color 0.3s ease;
    }
    .footer a:hover { color: var(--nav-hover); }
    @@media (max-width: 576px) {
        .navbar-nav {
            margin-left: 0;
            margin-top: 1rem;
        }
        .navbar-nav .nav-item {
            margin-left: 0;
            margin-bottom: 0.5rem;
        }
    }
</style>
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'(Of style) :root
'{
'		--primary-color: #3498db;
'		--text-color: #333;
'		--bg-color: #f8f9fa;
'		--nav-bg: #fff;
'		--nav-text: #2c3e50;
'		--nav-hover: #3498db;
'	}
	body
	If True Then
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'		font-family: 'Segoe UI', sans-serif; background-color: var(--bg-color); color: var(--text-color); line-height: 1.6; } .navbar { background-color: var(--nav-bg); } .navbar-brand { font-size: 1.5rem; font-weight: 700; color: var(--primary-color); margin-right: 2rem; } .navbar-nav { margin-left: auto; } .navbar-nav.nav-item { margin-left: 1rem; } .navbar-nav.nav-link { color: var(--nav-text); font-weight: 500; transition: all 0.3s ease; padding: 0.5rem 1rem; border-radius: 4px; } .navbar-nav.nav-link:hover, .navbar-nav.nav-link.active { color: var(--primary-color); background-color: rgba(52, 152, 219, 0.1); } .navbar-nav.nav-link i { margin-right: 0.5rem; font-size: 1.1em; } .centered-container { max-width: 800px; margin: 0 auto; padding: 2rem; } .footer { background-color: var(--nav-bg); border-top: 1px solid #ecf0f1; font-size: 0.9em; color: var(--nav-text); } .footer a { color: var(--primary-color); text-decoration: none; transition: color 0.3s ease; } .footer a:hover { color: var(--nav-hover); } @@media(max-width: 576px) { .navbar-nav { margin-left: 0; margin-top: 1rem; } .navbar-nav.nav-item { margin-left: 0; margin-bottom: 0.5rem; } } </style>
VB   C#

This CSS block defines our application's color scheme and layout. We're using CSS variables (custom properties) to create a consistent color palette throughout the app. The styles target various elements including the body, navbar, and footer, ensuring a cohesive design. We've set up the navbar with a clean, modern look, featuring hover effects and icon integration. W

hile our application currently focuses on Word documents, we can use IronPDF to include support for PDF documents to expand its functionality to cover a wider range of file types. The system could be extended to allow users to export their documents as a PDF file in addition to the current Word format options.

5. Running the Application

Let's start by running our WordDocumentProcessor application. As we can see in the Image, the application has loaded successfully in the browser. The interface is clean and user-friendly, with a navigation bar at the top showing "Home" and "Export" options. The main content area displays the title "Word Document Processor" and a brief description: "Upload and process your Word documents with ease."

ASP .NET Core Import & Export A Word File: Figure 3

Now, let's try importing a document. In the image, we can see that we've selected a file named "Honey research synopsis.docx". The file name is displayed in the upload area, replacing the "Choose File" button. We're now ready to upload and process this document.

ASP .NET Core Import & Export A Word File: Figure 4

After clicking "Upload and Process", the application processes the document and displays its content. The "Document Content" section now shows the beginning of the uploaded document. We can see the title "Beekeeping Technologies and Quality of Honey Production in Urban Areas" followed by an abstract. This demonstrates that our application has successfully read and displayed the content of the Word document.

ASP .NET Core Import & Export A Word File: Figure 5

Finally, let's test the export functionality. In the image, we see a prompt that appears when we click the "Export" button in the navigation bar. The prompt asks us to "Enter a name for the document (without extension)". The default name "ExportedDocument" is pre-filled, but we can change this if we wish. This prompt allows us to customize the name of our exported document before downloading it.

ASP .NET Core Import & Export A Word File: Figure 6

After clicking "OK", the application generates a new Word document with the specified name and initiates the download process. This exported document contains the content we've processed or any modifications we've made within the application.

ASP .NET Core Import & Export A Word File: Figure 7

Throughout this process, we can see that the application is functioning as intended. We can use this application for importing Word documents, creating documents, and exporting them with ease. The user interface is intuitive and responsive.

Conclusion

In conclusion, our WordDocumentProcessor application successfully demonstrates the power and flexibility of integrating Word document processing into an ASP.NET Core web application. By leveraging the IronWord library, we've created a robust solution for importing, displaying, and exporting Word documents with ease. This application serves as a solid foundation for more complex document management systems or report generators. For developers interested in exploring IronWords's capabilities, the library offers a free trial. After the trial, licensing starts at $749, making it a cost-effective solution for businesses requiring advanced Word document processing functionality in their web applications.

NEXT >
VS 2022 Programmatically Create New Word Documents (Tutorial)

Ready to get started? Version: 2024.12 just released

Free NuGet Download Total downloads: 8,594 View Licenses >