How to Build a Web Document Scanning App with ASP.NET Core MVC and Dynamic Web TWAIN

ASP.NET Core enables C# server-side applications to run on Windows, Linux, and macOS. In this tutorial, we will go through the steps of building a web document scanning application with ASP.NET Core and Dynamic Web TWAIN SDK.

What you’ll build: A cross-platform web document scanning application using ASP.NET Core MVC and Dynamic Web TWAIN SDK that lets users scan physical documents from a TWAIN-compatible scanner and upload them as JPG, PDF, or TIFF files to a C# backend.

Key Takeaways

  • Dynamic Web TWAIN integrates with ASP.NET Core MVC via a JavaScript front-end and a C# FileController API endpoint to enable full scan-to-upload workflows.
  • The Dynamsoft.DWT.UseLocalService = true flag activates the local scanning service, enabling access to physical TWAIN scanners from a browser.
  • ASP.NET Core MVC projects can be scaffolded on any platform using the .NET CLI (dotnet new webapp), making this solution cross-platform by default.
  • This pattern applies to enterprise document management, healthcare intake forms, and any workflow requiring digitized physical documents.

Common Developer Questions

  • How do I scan documents from a browser using a TWAIN scanner in an ASP.NET Core app?
  • How do I upload scanned documents as PDF or TIFF from JavaScript to a C# controller?
  • How do I configure Dynamic Web TWAIN static resource files in ASP.NET Core?

Download the SDK and Get a License Key

Scaffold an ASP.NET Core MVC Project

There are two ways to scaffold a new ASP.NET Core MVC project: one is using Visual Studio, and the other is using the .NET Core CLI. The former is available only for Windows users, while the latter is accessible on all platforms.

Scaffold the Project in Visual Studio

  1. Create a new project using the ASP.NET Core Web Application template.

    Choose ASP.NET Core Web Application as the template

  2. Initialize the project with the Web Application(Model-View-Controller) template.

    Initialize the ASP.NET Core web application with Model-View-Controller template

Scaffold the Project with the .NET CLI

Open a terminal and enter the following command to create a project:

dotnet new webapp -o dwtDotNet --no-https

This command generates a .NET Core application using the webapp template, suitable for ASP.NET Core MVC projects, with the name dwtDotNet, and disables HTTPS by default.

Configure Dynamic Web TWAIN in Your ASP.NET Core Project

  1. Download the Dynamic Web TWAIN SDK and copy the node_modules\dwt\dist folder to your project directory.

     npm install dwt
    
  2. Configure the Dynamic Web TWAIN resource files in Startup.cs:

     app.UseStaticFiles(new StaticFileOptions
     {
         FileProvider = new PhysicalFileProvider(
     Path.Combine(env.ContentRootPath, "RESOURCE-FILES-FOLDER")),
         RequestPath = "/lib/dwt"
     });
    

    The /lib/dwt is the resource finding path, which will be used later in JavaScript.

Implement Document Scanning and Uploading

The project structure is shown as follows:

SP.NET Core MVC project structure

In the Model-View-Controller (MVC) app, the controller handles requests and returns the corresponding views. The model represents the business abstraction. For this project, since there’s no data to store, models and a database are not required.

Note: To scaffold the project with the CLI, you can install dotnet-aspnet-codegenerator for generating controllers and views.

Document scanning functionality will be implemented in Index.cshtml, and document uploading will be handled in HomeController.cs.

Build the Scan and Upload UI in Index.cshtml

  1. Build the user interface (UI) within the Index.cshtml file. Include a first button for scanning documents and a second button for uploading documents. Add radio buttons to allow the user to select the format of the document to be uploaded. Provide an input box for specifying the name of the uploaded document.

     <div class="container-fluid">
         <div id="control-panel">
             <button class="btn btn-primary" onclick="AcquireImage()">Scan</button>
             <br />
             <button class="btn btn-outline-secondary" onclick="Upload()">Upload</button>
             <input type="radio" value="jpg" name="format"/>JPG
             <input type="radio" value="pdf" name="format"/>PDF
             <input type="radio" value="tif" name="format"/>TIFF
             <label for="filename-input">File Name: </label>
             <input type="text" id="filename-input"/>
         </div>
         <div id="dwt-container">
        
         </div>
     </div>
    
  2. Include the Dynamic Web TWAIN JavaScript files in your project.

     <script src="~/lib/dwt/dynamsoft.webtwain.min.js"></script>
    
  3. Initialize a Dynamic Web TWAIN object using a valid license key.

     <script>
         var DWObj;
         var viewerWidth = 960, viewerHeight = 960;
         var containerName = 'dwt-container';
         Dynamsoft.DWT.ResourcesPath = 'lib/dwt';
         Dynamsoft.DWT.ProductKey = "LICENSE-KEY"; // https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform
         function initDWT() {
                 Dynamsoft.DWT.UseLocalService = true;
                 Dynamsoft.DWT.AutoLoad = true;
                 Dynamsoft.DWT.Containers = [{ ContainerId: containerName, Width: viewerWidth, Height: viewerHeight }];
                 Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', function () {
                     DWObj = Dynamsoft.DWT.GetWebTwain(containerName);
                     if (DWObj) {
                         DWObj.Width = viewerWidth;
                         DWObj.Height = viewerHeight;
                         DWObj.MouseShape = true;
                     }
                 });
             }
         initDWT(); 
     </script>
    
  4. Implement functionality to scan documents.

     <script>
         function AcquireImage() {
             if (DWObj) {
                 if (DWObj.UseLocalService) {
                     DWObj.SelectSourceAsync().then(function () {
                         return DWObj.AcquireImageAsync({
                             IfCloseSourceAfterAcquire: true 
                         });
                     }).catch(function (exp) {
                         alert(exp.message);
                     });
                 } else {
                     DWObj.LoadImageEx('', -1)
                 }
             }
         }
     </script>
    

Upload Scanned Documents to the ASP.NET Core Server

To facilitate document file uploading, it’s necessary to implement JavaScript code on the front-end and C# code on the back-end.

  1. Incorporate the specified JavaScript into the Index.cshtml file to enable the uploading of the scanned document to the server.

     function Upload() {
         const host = location.hostname
         const protocol = location.protocol
         const uploadPath = '/api/File'
         let uploadFileName = document.getElementById('filename-input').value
         const port = location.port || (protocol === 'https:' ? 443 : 80)
        
         var formatSelector = document.getElementsByName('format')
         let format = (selector => {
             let select = ''
             selector.forEach(e => {
                 if (e.checked) {
                     select = e.value
                 }
             })
             uploadFileName = uploadFileName + '.' + select
             switch (select) {
                 case 'jpg': { return Dynamsoft.DWT.EnumDWT_ImageType.IT_JPG }
                 case 'pdf': { return Dynamsoft.DWT.EnumDWT_ImageType.IT_PDF }
                 case 'tif': { return Dynamsoft.DWT.EnumDWT_ImageType.IT_TIF }
             }
         })(formatSelector)
        
         let uploadFormat = Dynamsoft.DWT.EnumDWT_UploadDataFormat.Binary
        
         if (DWObj) {
             DWObj.HTTPPort = port
             DWObj.IfSSL = true
             let indices = DWObj.SelectedImagesIndices
             DWObj.HTTPUpload(
                 protocol + '//' + host + ':' + port + uploadPath,
                 indices,
                 format,
                 uploadFormat,
                 uploadFileName,
                 () => { alert('success') },
                 (errCode, errStr, res) => {
                     console.error(`${errCode}: ${errStr}. Server return: ${ res }`)
                 }
             )
         }
     }
    
  2. Add a new controller dedicated to managing the file upload process.

    Select "New Scaffolded Item" to create a new controller

    The C# code is written as follows:

     [Route("api/[controller]")]
     [ApiController]
     public class FileController : ControllerBase
     {
         // POST api/<FileController>
         [HttpPost]
         public async Task<IActionResult> Upload()
         {
             var files = Request.Form.Files;
             var path = Path.Combine(Directory.GetCurrentDirectory(), "Upload");
             if (!Directory.Exists(path))
             {
                 try
                 {
                     Directory.CreateDirectory(path);
                 }
                 catch (Exception e)
                 {
                     Debug.WriteLine(e.StackTrace.ToString());
                     return Unauthorized("not able to create");
                 }
             }
             foreach (var uploadFile in files)
             {
                 var fileName = uploadFile.FileName;
                 using (var stream = System.IO.File.Create(Path.Combine(path, fileName)))
                 {
                     await uploadFile.CopyToAsync(stream);
                 }
             }
             return Ok();
         }
     } 
    

Testing the ASP.NET Core Document Scanning Application

  1. Launch the application.

    First page of the application

  2. Click on the “Scan” button to start the scanning process.

    DotNet core document scanning

  3. Scan documents from the available source.

    DotNet core document upload

  4. Upload the scanned document to the server. After uploading, check your designated upload folder to view the files you’ve uploaded.

Source Code

https://github.com/yushulx/web-twain-document-scan-management/tree/main/examples/asp_dotnet_upload