Cross-platform Web Document Scanning with ASP.NET Core

If you are a C# developer, what technology you can use to create a cross-platform web document scanning app? The answer is ASP.NET Core and Dynamic Web TWAIN. In this post, I will share how to use these technologies to build a simple web app from scratch.

The Real Cross-platform Document Scanning Solution

Why Dynamic Web TWAIN for document scanning development? The powerful SDK supports Windows, Linux, and macOS.

cross-platform document scanning sdk

Installation

Hello World

How to create a new ASP.NET Core project? You can read the tutorial provided by Microsoft:

mkdir aspnetcoreapp
cd aspnetcoreapp
dotnet new -t web

It is a fancy web project with so many files. Let’s create an empty project with the command:

dotnet new

The command only generates two files Program.cs and project.json. To run the app as a web server:

  1. Modify Program.cs:
    using System.IO;
    using aspnetcoreapp;
    using Microsoft.AspNetCore.Hosting;
    
    namespace ConsoleApplication
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var host = new WebHostBuilder()
                    .UseKestrel()
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseStartup<Startup>()
                    .Build();
    
                host.Run();
            }
        }
    }
    
  2. Add dependencies to project.json:
    {
      "version": "1.0.0-*",
      "buildOptions": {
        "debugType": "portable",
        "emitEntryPoint": true
      },
      "dependencies": {},
      "frameworks": {
        "netcoreapp1.0": {
          "dependencies": {
            "Microsoft.NETCore.App": {
              "type": "platform",
              "version": "1.0.1"
            },
            "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
            "Microsoft.AspNetCore.StaticFiles": "1.0.0"
          },
          "imports": "dnxcore50"
        }
      }
    }

With the dependencies, we can run a web server and load static resources like HTML files, CSS files, and images.

Create Startup.cs:

using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;

namespace aspnetcoreapp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            // app.UseDefaultFiles();
            // app.UseStaticFiles();
            app.UseFileServer();
        }
    }
}

The code will load index.html as the default web page.

Create the default static file folder wwwroot. Copy sample code from <Your Dynamic Web TWAIN Path>\Samples to this folder. What if you want to upload scanned documents to a web server? Map the action route and save files as follows:

using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;

namespace aspnetcoreapp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            // app.UseDefaultFiles();
            // app.UseStaticFiles();
            app.UseFileServer();

            app.Map("/upload", UploadFile);
        }

        private static void UploadFile(IApplicationBuilder app)
        {
            app.Run(async context =>
            {
                var files = context.Request.Form.Files;
                var uploads = Path.Combine(Directory.GetCurrentDirectory(), "uploads");
                if (!Directory.Exists(uploads)) {
                    Directory.CreateDirectory(uploads);
                }

                foreach (var file in files)
                {
                    var filename = file.FileName;
                    using (var fileStream = new FileStream(Path.Combine(uploads, filename), FileMode.Create))
                    {
                        await file.CopyToAsync(fileStream);
                    }
                }
            });
        }
    }
}

Now run the web project:

dotnet restore
dotnet run

Visit localhost:5000 to scan and upload documents in web browsers.

linux document scanning

Using MVC

If there are more actions to take, it is recommended to use MVC. Let’s see how to change the code.

Add dependency in project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.1"
        },
        "Microsoft.AspNetCore.Mvc": "1.0.1",
        "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
        "Microsoft.AspNetCore.StaticFiles": "1.0.0"
      },
      "imports": "dnxcore50"
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  }
}

Add MVC service and replace route mapping with MVC in Startup.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace aspnetcoreapp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }
    }
}

The default controller is Home and the default action is Index. Let’s move wwwroot/index.html to Views/home/index.cshtml. I don’t want to add any code but change the file suffix. Create Controllers/HomeController.cs for rendering index.cshtml:

using Microsoft.AspNetCore.Mvc;

namespace aspnetcoreapp.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

So far, we can run and display the web page with no problem. The next step is to implement the functionality of uploading files.

Open index.cshtml and change the action page:

var strActionPage = CurrentPath + "upload";

To process the action page, we have to create Controllers/UploadController.cs:

using Microsoft.AspNetCore.Mvc;
using System.IO;

namespace aspnetcoreapp.Controllers
{
    public class UploadController : Controller
    {
        [HttpPost]
        public void Index()
        {
            var files = Request.Form.Files;
            var uploads = Path.Combine(Directory.GetCurrentDirectory(), "uploads");
            if (!Directory.Exists(uploads))
            {
                Directory.CreateDirectory(uploads);
            }

            foreach (var file in files)
            {
                var filename = file.FileName;
                using (var fileStream = new FileStream(Path.Combine(uploads, filename), FileMode.Create))
                {
                    file.CopyTo(fileStream);
                    fileStream.Flush();
                }
            }
        }
    }
}

That’s all. Pretty simple!

Source Code

https://github.com/dynamsoft-dwt/ASP.NET-Core