How to Build a Barcode Scanner API in C# Using IronBarcode
Building a C# scanner API in .NET has traditionally required complex scanner SDK integration or limited software libraries. With IronBarcode, developers can create a powerful, production-ready barcode scanner API in minutes. These can easily process barcode data from images, PDFs, and even damaged scan inputs.
This tutorial demonstrates how to build a RESTful scanner API using ASP.NET Core on Windows, providing a scalable alternative to hardware scanner devices while maintaining enterprise-level accuracy. The API is capable of handling multiple scanner types, working with binary data, and extracting barcode values from any supported matrix or table format.
How Do I Install and Set Up IronBarcode?
Getting started with IronBarcode is as simple as installing a single NuGet package. Open your ASP.NET Core project and run this command in the Package Manager Console:
Install-Package BarCode
After installation, add the IronBarcode namespace to your controller and test the library with this one-line example:
using IronBarCode;
// Simple test to verify installation
var result = BarcodeReader.Read("test-barcode.png");
Console.WriteLine($"Scanned: {result.First().Value}");
using IronBarCode;
// Simple test to verify installation
var result = BarcodeReader.Read("test-barcode.png");
Console.WriteLine($"Scanned: {result.First().Value}");
IRON VB CONVERTER ERROR developers@ironsoftware.com
This code reads a barcode image and outputs its value. The BarcodeReader.Read() method automatically detects the barcode format and returns a collection of results, making it incredibly straightforward to extract barcode data from any supported images (jpeg, bmp, png, tiff) and work with array or binary data formats.
How Can I Build a Complete Scanner API Controller?
Creating a scanner API with ASP.NET Core involves setting up a controller with parameters that accept various input sources. Here's a complete implementation:
using Microsoft.AspNetCore.Mvc;
using IronBarCode;
using System.Drawing;
namespace BarcodeScannerAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ScannerController : ControllerBase
{
// Model for API responses
public class ScanResult
{
public bool Success { get; set; }
public List<string> BarcodeValues { get; set; } = new List<string>();
public string BarcodeFormat { get; set; }
public string ErrorMessage { get; set; }
}
[HttpPost("scan-file")]
public async Task<ActionResult<ScanResult>> ScanFile(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest(new ScanResult
{
Success = false,
ErrorMessage = "No file uploaded"
});
try
{
using var stream = new MemoryStream();
await file.CopyToAsync(stream);
// Configure scanner options for better accuracy
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.All
};
// Read barcodes from the uploaded file
var results = BarcodeReader.Read(stream.ToArray(), options);
if (results.Any())
{
return Ok(new ScanResult
{
Success = true,
BarcodeValues = results.Select(r => r.Value).ToList(),
BarcodeFormat = results.First().BarcodeType.ToString()
});
}
return Ok(new ScanResult
{
Success = false,
ErrorMessage = "No barcodes found"
});
}
catch (Exception ex)
{
return StatusCode(500, new ScanResult
{
Success = false,
ErrorMessage = $"Processing error: {ex.Message}"
});
}
}
[HttpPost("scan-base64")]
public ActionResult<ScanResult> ScanBase64([FromBody] string base64Image)
{
try
{
// Convert Base64 string to byte array
byte[] imageBytes = Convert.FromBase64String(base64Image);
// Process with IronBarcode
var results = BarcodeReader.Read(imageBytes);
return ProcessResults(results);
}
catch (Exception ex)
{
return BadRequest(new ScanResult
{
Success = false,
ErrorMessage = $"Invalid Base64 data: {ex.Message}"
});
}
}
private ScanResult ProcessResults(BarcodeResults results)
{
if (results.Any())
{
return new ScanResult
{
Success = true,
BarcodeValues = results.Select(r => r.Value).ToList(),
BarcodeFormat = results.First().BarcodeType.ToString()
};
}
return new ScanResult
{
Success = false,
ErrorMessage = "No barcodes detected"
};
}
}
}
using Microsoft.AspNetCore.Mvc;
using IronBarCode;
using System.Drawing;
namespace BarcodeScannerAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ScannerController : ControllerBase
{
// Model for API responses
public class ScanResult
{
public bool Success { get; set; }
public List<string> BarcodeValues { get; set; } = new List<string>();
public string BarcodeFormat { get; set; }
public string ErrorMessage { get; set; }
}
[HttpPost("scan-file")]
public async Task<ActionResult<ScanResult>> ScanFile(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest(new ScanResult
{
Success = false,
ErrorMessage = "No file uploaded"
});
try
{
using var stream = new MemoryStream();
await file.CopyToAsync(stream);
// Configure scanner options for better accuracy
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.All
};
// Read barcodes from the uploaded file
var results = BarcodeReader.Read(stream.ToArray(), options);
if (results.Any())
{
return Ok(new ScanResult
{
Success = true,
BarcodeValues = results.Select(r => r.Value).ToList(),
BarcodeFormat = results.First().BarcodeType.ToString()
});
}
return Ok(new ScanResult
{
Success = false,
ErrorMessage = "No barcodes found"
});
}
catch (Exception ex)
{
return StatusCode(500, new ScanResult
{
Success = false,
ErrorMessage = $"Processing error: {ex.Message}"
});
}
}
[HttpPost("scan-base64")]
public ActionResult<ScanResult> ScanBase64([FromBody] string base64Image)
{
try
{
// Convert Base64 string to byte array
byte[] imageBytes = Convert.FromBase64String(base64Image);
// Process with IronBarcode
var results = BarcodeReader.Read(imageBytes);
return ProcessResults(results);
}
catch (Exception ex)
{
return BadRequest(new ScanResult
{
Success = false,
ErrorMessage = $"Invalid Base64 data: {ex.Message}"
});
}
}
private ScanResult ProcessResults(BarcodeResults results)
{
if (results.Any())
{
return new ScanResult
{
Success = true,
BarcodeValues = results.Select(r => r.Value).ToList(),
BarcodeFormat = results.First().BarcodeType.ToString()
};
}
return new ScanResult
{
Success = false,
ErrorMessage = "No barcodes detected"
};
}
}
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
This controller provides two endpoints: one for file uploads and another for Base64-encoded images. The ScanFile endpoint accepts multipart form data, making it perfect for web applications where users upload images directly. The stream processing ensures efficient memory usage, while the BarcodeReaderOptions configuration strikes a balance between speed and accuracy.
The ScanBase64 endpoint handles scenarios where images are transmitted as Base64 strings, standard in mobile applications and API-to-API communications. It is capable of reading both 1D and 2D (matrix) barcodes from uploaded images or streams.
Output
First, we're using Swagger to test our endpoints. Here, you can see the scanner API endpoints:
Now, let's test them and review the output. For this example, I'll use a sample barcode image that is encoded with a simple string value "Hello World". As you can see here, our program has correctly scanned the barcode and retrieved the data within it.
What Different Input Sources Can the Scanner Handle?
IronBarcode's flexibility shines when processing various input formats. Beyond standard images, the scanner API handles PDFs, upload streams, and multiple graphics formats:
// Scanning PDFs with multiple pages
[HttpPost("scan-pdf")]
public async Task<ActionResult<ScanResult>> ScanPdf(IFormFile pdfFile
{
using var stream = new MemoryStream();
await pdfFile.CopyToAsync(stream);
// ReadPdf method handles multi-page documents
var results = BarcodeReader.ReadPdf(stream.ToArray());
return ProcessResults(results);
}
// Processing from URL
[HttpPost("scan-url")]
public async Task<ActionResult<ScanResult>> ScanFromUrl([FromBody] string imageUrl)
{
using var client = new HttpClient();
var imageBytes = await client.GetByteArrayAsync(imageUrl);
var results = BarcodeReader.Read(imageBytes);
return ProcessResults(results);
}
// Scanning PDFs with multiple pages
[HttpPost("scan-pdf")]
public async Task<ActionResult<ScanResult>> ScanPdf(IFormFile pdfFile
{
using var stream = new MemoryStream();
await pdfFile.CopyToAsync(stream);
// ReadPdf method handles multi-page documents
var results = BarcodeReader.ReadPdf(stream.ToArray());
return ProcessResults(results);
}
// Processing from URL
[HttpPost("scan-url")]
public async Task<ActionResult<ScanResult>> ScanFromUrl([FromBody] string imageUrl)
{
using var client = new HttpClient();
var imageBytes = await client.GetByteArrayAsync(imageUrl);
var results = BarcodeReader.Read(imageBytes);
return ProcessResults(results);
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
The ReadPdf method automatically scans all pages in a PDF document, extracting barcodes from shipping labels, invoices, or multi-page reports. For URL-based scanning, the API fetches remote images and processes them without requiring local storage, ideal for integrating with cloud storage services or processing images from external systems.
Now, you will be able to see the updated Swagger UI with our new endpoints:
To test our new methods, I used our example PDF that contains two sample barcodes.
The first is a basic barcode with a URL, and the second is the basic string encoded barcode from our last example. Here is the output from running our PDF through the endpoint:
As you can see, it has correctly detected both barcodes and extracted the data from the scanned barcodes.
Optimizing the Barcode Scanner for Performance and Accuracy
Fine-tuning the scanner for specific use cases dramatically improves both speed and accuracy:
var optimizedOptions = new BarcodeReaderOptions
{
// Speed settings: Faster, Balanced, Detailed, ExtremeDetail
Speed = ReadingSpeed.Detailed,
// Specify expected barcode types to reduce processing time
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128,
// Enable parallel processing for batch operations
Multithreaded = true,
MaxParallelThreads = 4,
// Define scanning area to focus on specific regions
CropArea = new Rectangle(100, 100, 400, 200), // Optional: define specific scanning area
// Apply image corrections for damaged barcodes
ImageFilters = new ImageFilterCollection() {
new SharpenFilter(),
new ContrastFilter()
}
};
var optimizedOptions = new BarcodeReaderOptions
{
// Speed settings: Faster, Balanced, Detailed, ExtremeDetail
Speed = ReadingSpeed.Detailed,
// Specify expected barcode types to reduce processing time
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128,
// Enable parallel processing for batch operations
Multithreaded = true,
MaxParallelThreads = 4,
// Define scanning area to focus on specific regions
CropArea = new Rectangle(100, 100, 400, 200), // Optional: define specific scanning area
// Apply image corrections for damaged barcodes
ImageFilters = new ImageFilterCollection() {
new SharpenFilter(),
new ContrastFilter()
}
};
IRON VB CONVERTER ERROR developers@ironsoftware.com
Note: The CropArea property allows the scanner to focus on a specific matrix or table region within the image. However, some objects or barcode locations may fall outside the defined area, causing the scanner to fail. If this occurs, simply remove or comment out the CropArea property. IronBarcode will then identify and decode all barcode data in the default full image, ensuring the scanner is capable of handling any Windows or Microsoft run time scenario.
Using optimized options for known scanner types reduces processing time. Embedded image filters enhance scanned barcode readability for low-quality input. Developers can configure the scanner SDK, enumerate available scanners, and integrate UI components or video capture devices.
Summary
Building a C# scanner API with IronBarcode transforms complex barcode processing into straightforward REST endpoints. The library handles everything from perfect digital barcodes to challenging real-world captures, providing enterprise-grade accuracy without hardware dependencies.
With support for multiple input formats, advanced image correction, and optimized performance settings, developers can deploy production-ready scanning solutions in minutes. Get started with a free trial to implement your scanner API today, or explore the complete documentation for advanced features like batch processing and machine learning-powered detection.
Frequently Asked Questions
What is the main benefit of using IronBarcode for building a scanner API in C#?
IronBarcode allows developers to quickly create a powerful, production-ready barcode scanner API with minimal complexity. It simplifies the process by eliminating the need for complex scanner SDK integrations.
Can IronBarcode handle damaged barcode inputs?
Yes, IronBarcode is designed to process barcode data even from damaged scan inputs, ensuring high reliability in real-world applications.
What types of input can IronBarcode process in a C# scanner API?
IronBarcode can process barcode data from various inputs such as images and PDFs, offering versatile solutions for different scanning needs.
Is there a tutorial available for building a barcode scanner API using IronBarcode?
Yes, the web page provides a comprehensive tutorial with code examples to guide developers in building a RESTful barcode scanning endpoint using IronBarcode.
How quickly can a barcode scanner API be set up using IronBarcode?
With IronBarcode, developers can set up a barcode scanner API in minutes, streamlining development time and effort.
Does IronBarcode require any complex SDK integrations?
No, IronBarcode eliminates the need for complex scanner SDK integrations, making it easier for developers to implement barcode scanning functionality.
What programming language is used with IronBarcode for building a scanner API?
IronBarcode is used with C# to build a scanner API, leveraging the .NET framework for robust performance.