Migrating from BarcodeScanning.Native.Maui to IronBarcode
This guide provides a complete migration path from BarcodeScanning.Native.Maui to IronBarcode, covering the camera event pattern replacement, namespace changes, code migration examples, and the handling of scenarios that BarcodeScanning.Native.Maui cannot address - Windows MAUI, file and PDF input, server-side processing, and barcode generation.
Why Migrate from BarcodeScanning.MAUI
Teams migrating from BarcodeScanning.Native.Maui report these triggers:
Windows MAUI Target Required: BarcodeScanning.Native.Maui wraps iOS and Android native APIs. It has no Windows implementation and none is planned. If your MAUI app targets Windows alongside iOS and Android, you need a library that works on all three targets without platform-specific branching.
File or PDF Input Added to Requirements: BarcodeScanning.Native.Maui only accepts live camera frames. When users need to upload an image from their gallery, or when a server-side endpoint needs to extract barcodes from PDFs, the library has no code path to offer. Any file or PDF barcode scenario requires a different tool.
iOS UPC-A Data Was Wrong in Production: Apple's Vision framework returns 13 digits for UPC-A barcodes (EAN-13 encoding). BarcodeScanning.Native.Maui passes this through uncorrected. If UPC-A codes were being stored with a leading zero, inventory records, point-of-sale lookups, or supply chain integrations may have been silently broken. IronBarcode returns the correct 12-digit UPC-A value without manual normalization.
PDF417 Scanning Was Unreliable: The library's own GitHub issues document PDF417 as "very problematic - most scans never occur." For shipping labels, driver's licenses, and boarding passes, this is a direct blocker.
Generation Was Needed: BarcodeScanning.Native.Maui cannot generate barcodes. IronBarcode generates Code128, QR, DataMatrix, and other formats as image files or byte arrays.
Server-Side Processing Introduced: BarcodeScanning.Native.Maui is a camera UI control - it cannot run in a server process. When server-side barcode reading is required alongside mobile scanning, IronBarcode covers both sides with the same package and the same API.
The Fundamental Problem
BarcodeScanning.Native.Maui ties your barcode reading entirely to the live camera event model. The moment any requirement falls outside that model, the library offers nothing:
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode != null)
ResultLabel.Text = barcode.DisplayValue;
}Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
Dim barcode = e.BarcodeResults.FirstOrDefault()
If barcode IsNot Nothing Then
ResultLabel.Text = barcode.DisplayValue
End If
End SubIronBarcode accepts any data input - camera capture, file, PDF, byte array - and runs on every platform:
using IronBarCode;
private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}Imports IronBarCode
Private Async Sub ScanBarcodeButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
ResultLabel.Text = If(results.FirstOrDefault()?.Value, "No barcode found")
End Using
End Using
End SubIronBarcode vs BarcodeScanning.MAUI: Feature Comparison
| Feature | BarcodeScanning.MAUI | IronBarcode |
|---|---|---|
| Live camera frame reading | Yes - CameraView control | No (use MediaPicker to capture, then read) |
| In-app camera viewfinder | Yes - real-time continuous | No - uses system camera UI via MediaPicker |
| Read from image file | No | Yes - BarcodeReader.Read(path) |
| Read from byte array | No | Yes - BarcodeReader.Read(bytes) |
| Read from stream | No | Yes - BarcodeReader.Read(stream) |
| Read from PDF | No | Yes - BarcodeReader.Read(pdf) |
| Barcode generation | No | Yes - BarcodeWriter + QRCodeWriter |
| Windows MAUI support | No | Yes |
| iOS MAUI support | Yes | Yes |
| Android MAUI support | Yes | Yes |
| macOS MAUI support | Not documented | Yes |
| Server-side / ASP.NET | No | Yes |
| Docker / Azure / AWS Lambda | No | Yes |
| iOS UPC-A accuracy | Returns 13 digits (bug), requires manual normalization | Returns correct 12-digit UPC-A |
| PDF417 reliability | "Most scans never occur" (GitHub issues) | Supported |
| Multi-barcode detection | Yes (multiple per frame via e.BarcodeResults) | Yes (ExpectMultipleBarcodes option) |
| Reading speed control | None | ReadingSpeed.Faster / Balanced / Detailed / ExtremeDetail |
| License | MIT (open source, free) | Commercial - Lite $999, Plus $1,499, Professional $2,399, Unlimited $4,799 |
| .NET Framework support | No (MAUI only) | Yes - .NET Framework 4.6.2+ |
Quick Start: BarcodeScanning.MAUI to IronBarcode Migration
Step 1: Replace NuGet Package
Remove BarcodeScanning.Native.Maui:
dotnet remove package BarcodeScanning.Native.Maui
Install IronBarcode:
dotnet add package IronBarcode
Step 2: Update Namespaces
Remove the BarcodeScanning namespace from all files:
// Remove
using BarcodeScanning;Imports BarcodeScanningAdd the IronBarCode namespace:
// Add
using IronBarCode;Imports IronBarCodeIn XAML files, remove the scanner: XML namespace declaration:
<!-- Remove this line from ContentPage attributes -->
xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"
Step 3: Initialize License
Add license initialization at application startup - in MauiProgram.cs or App.xaml.cs:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"Code Migration Examples
Camera Scanning: CameraView to MediaPicker
The CameraView control provided a real-time viewfinder with continuous frame detection. The IronBarcode replacement uses MAUI's MediaPicker to open the system camera, capture a photo, and process the resulting image.
BarcodeScanning.MAUI Approach - XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
<StackLayout>
<scanner:CameraView x:Name="CameraView"
OnDetectionFinished="OnBarcodeDetected"
CameraEnabled="True"
BarcodeFormats="All"
VerticalOptions="FillAndExpand" />
<Label x:Name="ResultLabel" Text="Waiting for scan..." />
</StackLayout>
</ContentPage>
BarcodeScanning.MAUI Approach - code-behind:
using BarcodeScanning;
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode != null)
MainThread.BeginInvokeOnMainThread(() =>
ResultLabel.Text = barcode.DisplayValue);
}Imports BarcodeScanning
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
Dim barcode = e.BarcodeResults.FirstOrDefault()
If barcode IsNot Nothing Then
MainThread.BeginInvokeOnMainThread(Sub()
ResultLabel.Text = barcode.DisplayValue
End Sub)
End If
End SubIronBarcode Approach - XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
<StackLayout>
<Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
<Label x:Name="ResultLabel" Text="Tap to scan..." />
</StackLayout>
</ContentPage>
IronBarcode Approach - code-behind:
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
ResultLabel.Text = first?.Value ?? "No barcode found";
}Imports IronBarCode
Imports System.IO
Imports System.Linq
Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
Dim first = results.FirstOrDefault()
ResultLabel.Text = If(first?.Value, "No barcode found")
End Using
End Using
End SubThis code runs on iOS, Android, and Windows MAUI without any platform-specific branching. The user experience changes from a live in-app viewfinder to the platform's native camera screen - appropriate for most business applications. The IronBarcode MAUI reading guide covers additional configuration options.
Handling Multiple Barcodes Per Scan
BarcodeScanning.MAUI Approach:
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
foreach (var barcode in e.BarcodeResults)
{
MainThread.BeginInvokeOnMainThread(() =>
Console.WriteLine($"Found: {barcode.DisplayValue}"));
}
}Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
For Each barcode In e.BarcodeResults
MainThread.BeginInvokeOnMainThread(Sub()
Console.WriteLine($"Found: {barcode.DisplayValue}")
End Sub)
Next
End SubIronBarcode Approach:
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read(ms.ToArray(), options);
foreach (var result in results)
Console.WriteLine($"{result.Format}: {result.Value}");
}Imports IronBarCode
Imports System.IO
Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read(ms.ToArray(), options)
For Each result In results
Console.WriteLine($"{result.Format}: {result.Value}")
Next
End Using
End Using
End SubExpectMultipleBarcodes = true tells the reader to continue scanning after finding the first barcode. Without this option, the call returns on the first match, which is faster for single-barcode scenarios.
iOS UPC-A Fix: Remove the Normalization Workaround
If your codebase has the UPC-A leading-zero workaround, remove it entirely. IronBarcode returns the correct 12-digit value without any manual intervention.
BarcodeScanning.MAUI Approach - workaround in place:
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode == null) return;
var value = barcode.DisplayValue;
// Workaround: Apple Vision returns 13 digits for UPC-A
if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
value = value.Substring(1);
ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
Dim barcode = e.BarcodeResults.FirstOrDefault()
If barcode Is Nothing Then Return
Dim value = barcode.DisplayValue
' Workaround: Apple Vision returns 13 digits for UPC-A
If barcode.BarcodeFormat = BarcodeFormats.Upca AndAlso value.Length = 13 Then
value = value.Substring(1)
End If
ProcessBarcode(value, barcode.BarcodeFormat.ToString())
End SubIronBarcode Approach - no workaround needed:
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
if (first == null) return;
// result.Value is the correct 12-digit UPC-A — no normalization needed
ProcessBarcode(first.Value, first.Format.ToString());
}Imports IronBarCode
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks
Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
Dim first = results.FirstOrDefault()
If first Is Nothing Then Return
' result.Value is the correct 12-digit UPC-A — no normalization needed
ProcessBarcode(first.Value, first.Format.ToString())
End Using
End Using
End SubDelete any matches for BarcodeFormats.Upca paired with Substring(1) - that code is dead after migration.
Adding File and PDF Support
BarcodeScanning.Native.Maui has no equivalent for file or PDF input. If this is a new requirement being fulfilled at migration time:
BarcodeScanning.MAUI Approach:
// No equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs' No equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFsIronBarcode Approach:
using IronBarCode;
// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
var file = await FilePicker.PickAsync(new PickOptions
{
PickerTitle = "Select image or PDF"
});
if (file == null) return;
var results = BarcodeReader.Read(file.FullPath);
foreach (var result in results)
ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}
// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
var results = BarcodeReader.Read("shipment-manifest.pdf");
foreach (var result in results)
Console.WriteLine($"{result.Format}: {result.Value}");
}Imports IronBarCode
' Read from a file the user picked with FilePicker
Private Async Sub ReadFileButton_Clicked(sender As Object, e As EventArgs)
Dim file = Await FilePicker.PickAsync(New PickOptions With {
.PickerTitle = "Select image or PDF"
})
If file Is Nothing Then Return
Dim results = BarcodeReader.Read(file.FullPath)
For Each result In results
ResultLabel.Text &= vbCrLf & $"{result.Format}: {result.Value}"
Next
End Sub
' Read barcodes from a PDF directly — no intermediate image step
Private Sub ReadPdfBarcodes()
Dim results = BarcodeReader.Read("shipment-manifest.pdf")
For Each result In results
Console.WriteLine($"{result.Format}: {result.Value}")
Next
End SubThe IronBarcode PDF reading documentation covers multi-page PDF support and page range selection.
Server-Side Barcode Processing
If your application has a backend ASP.NET API that also needs barcode processing, the same BarcodeReader.Read() call runs there without modification. BarcodeScanning.Native.Maui has no server-side equivalent.
BarcodeScanning.MAUI Approach:
// No equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process' No equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
' and cannot run in a server processIronBarcode Approach:
using IronBarCode;
// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
using var ms = new MemoryStream();
await file.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
return Ok(values);
}Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Threading.Tasks
' ASP.NET endpoint — reads barcodes from an uploaded file
<HttpPost("scan")>
Public Async Function ScanBarcode(file As IFormFile) As Task(Of IActionResult)
Using ms As New MemoryStream()
Await file.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
Dim values = results.Select(Function(r) New With {Key .Value = r.Value, Key .Format = r.Format.ToString()})
Return Ok(values)
End Using
End FunctionThe same package, the same API, the same behavior - on mobile and server.
Generating Barcodes
BarcodeScanning.Native.Maui has no generation API. IronBarcode generates multiple formats.
BarcodeScanning.MAUI Approach:
// No equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes' No equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodesIronBarcode Approach:
using IronBarCode;
// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
.SaveAsPng("qr.png");
// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
.ResizeTo(400, 100)
.SaveAsPng("label.png");
// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
.ToPngBinaryData();Imports IronBarCode
' QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500) _
.SaveAsPng("qr.png")
' Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
.ResizeTo(400, 100) _
.SaveAsPng("label.png")
' Get bytes for returning from an API or storing in a database
Dim barcodeBytes As Byte() = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
.ToPngBinaryData()The IronBarcode generation documentation covers all supported formats and styling options.
BarcodeScanning.MAUI API to IronBarcode Mapping Reference
| BarcodeScanning.Native.Maui | IronBarcode |
|---|---|
CameraView XAML control | Remove - use Button + MediaPicker.CapturePhotoAsync() |
OnDetectionFinished event | BarcodeReader.Read(imageBytes) return value |
OnDetectionFinishedEventArg e | IEnumerable result from BarcodeReader.Read() |
e.BarcodeResults | Return value of BarcodeReader.Read() |
e.BarcodeResults.FirstOrDefault() | results.FirstOrDefault() |
barcode.DisplayValue | result.Value |
barcode.BarcodeFormat | result.Format |
BarcodeFormats="All" | Auto-detected - no configuration needed |
CameraEnabled="True" | await MediaPicker.CapturePhotoAsync() |
| iOS + Android only | iOS, Android, Windows, macOS MAUI |
| No file input | BarcodeReader.Read(filePath) |
| No PDF input | BarcodeReader.Read("document.pdf") |
| No generation | BarcodeWriter.CreateBarcode() / QRCodeWriter.CreateQrCode() |
| iOS UPC-A returns 13 digits | Returns correct 12 digits - no normalization needed |
| PDF417 unreliable | Supported |
Common Migration Issues and Solutions
Issue 1: Live Viewfinder Experience Lost
BarcodeScanning.MAUI: The CameraView control embedded a real-time camera preview directly in the MAUI page. Users could see the camera feed and aim at a barcode - detection happened automatically with no button press.
Solution: MediaPicker.CapturePhotoAsync() shows the platform camera screen instead. For most business workflows this is acceptable. For consumer apps that require a continuous live preview, camera frames can be passed directly to BarcodeReader.Read():
using IronBarCode;
// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
var results = BarcodeReader.Read(frameBytes);
if (results.Any())
{
var first = results.First();
MainThread.BeginInvokeOnMainThread(() =>
ResultLabel.Text = first.Value);
}
}Imports IronBarCode
' Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
' (frame capture depends on your MAUI camera frame source)
Private Sub ProcessCameraFrame(frameBytes As Byte())
Dim results = BarcodeReader.Read(frameBytes)
If results.Any() Then
Dim first = results.First()
MainThread.BeginInvokeOnMainThread(Sub()
ResultLabel.Text = first.Value
End Sub)
End If
End SubThis requires wiring up a camera frame source separately from IronBarcode. Evaluate whether a live preview is genuinely required or whether the system camera UI is sufficient before taking this path.
Issue 2: e.BarcodeResults Property Name and Enum Changes
BarcodeScanning.MAUI: barcode.DisplayValue returns the decoded string; barcode.BarcodeFormat returns a BarcodeScanning library enum value.
Solution: Replace DisplayValue with result.Value and barcode.BarcodeFormat with result.Format. The iteration pattern is the same:
// Before
foreach (var barcode in e.BarcodeResults)
Console.WriteLine(barcode.DisplayValue);
// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
Console.WriteLine(result.Value);' Before
For Each barcode In e.BarcodeResults
Console.WriteLine(barcode.DisplayValue)
Next
' After
Dim results = BarcodeReader.Read(imageBytes)
For Each result In results
Console.WriteLine(result.Value)
NextIssue 3: Thread Marshaling for UI Updates
BarcodeScanning.MAUI: OnDetectionFinished fires on a background thread, so all UI updates require MainThread.BeginInvokeOnMainThread().
Solution: With the MediaPicker + async pattern, the continuation after await returns on the calling context - typically the main thread. The MainThread.BeginInvokeOnMainThread() wrappers around result display can generally be removed, simplifying the handler code.
Issue 4: MAUI Camera Permissions
BarcodeScanning.MAUI: The package adds camera permissions to AndroidManifest.xml and Info.plist automatically as part of its setup.
Solution: With IronBarcode using MediaPicker, the standard MAUI camera permissions must be present manually. These are the same permissions any MAUI app needs for MediaPicker.CapturePhotoAsync() and are typically already in place. Verify that android.permission.CAMERA is declared in AndroidManifest.xml and NSCameraUsageDescription is set in Info.plist before testing on device.
BarcodeScanning.MAUI Migration Checklist
Pre-Migration Tasks
Run these searches to find all BarcodeScanning.Native.Maui usage before making any changes:
grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
Document each hit. Note which files contain CameraView XAML usage (require XAML changes) versus which contain only code-behind changes. Identify any UPC-A normalization workarounds that must be deleted after migration.
Code Update Tasks
- Remove
BarcodeScanning.Native.MauiNuGet package - Install
IronBarcodeNuGet package - Add
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";inMauiProgram.csorApp.xaml.cs - Replace
using BarcodeScanning;withusing IronBarCode;in all.csfiles - Remove
xmlns:scanner="..."namespace declarations from all XAML files - Replace
scanner:CameraViewcontrols in XAML with aButtontriggeringMediaPicker.CapturePhotoAsync() - Remove
OnDetectionFinished="..."event wiring from XAML - Replace
OnDetectionFinishedevent handlers withasyncbutton click handlers usingBarcodeReader.Read() - Replace
barcode.DisplayValuewithresult.Valuethroughout - Replace
barcode.BarcodeFormatwithresult.Formatthroughout - Delete all
BarcodeFormats.Upca+Substring(1)normalization workarounds - Add
ExpectMultipleBarcodes = truetoBarcodeReaderOptionswhere multi-barcode detection was previously relying one.BarcodeResultsreturning multiple items - Remove
MainThread.BeginInvokeOnMainThread()wrappers from result display code where the async pattern makes them unnecessary - Verify
AndroidManifest.xmlandInfo.plistcamera permissions are present
Post-Migration Testing
- Verify iOS barcode scanning works and UPC-A values are returned as 12-digit strings without leading zeros
- Verify Android barcode scanning produces correct values for all formats used in the application
- Verify Windows MAUI barcode scanning works if Windows is a build target
- Test PDF417 scanning against real shipping labels, driver's licenses, or boarding passes if these are used
- Test multi-barcode scenarios with
ExpectMultipleBarcodes = trueand confirm all barcodes in an image are returned - Verify file picker scanning (
BarcodeReader.Read(filePath)) works on all MAUI targets - Verify PDF barcode reading if this was a new capability added alongside migration
- Confirm server-side
BarcodeReader.Read()produces correct results if a backend component was added - Run any existing automated tests and compare barcode value outputs to pre-migration baselines
Key Benefits of Migrating to IronBarcode
Full Windows MAUI Support: IronBarcode runs on all four MAUI targets - iOS, Android, Windows, and macOS - using the same code and the same package. No platform-specific barcode implementation is needed for Windows, and no #if WINDOWS blocks are required in application code.
Any Input Source: BarcodeReader.Read() accepts file paths, byte arrays, streams, and PDF documents. Any barcode scenario - camera capture, file upload, gallery image, server-side PDF processing - uses the same static method with the same result type.
Correct UPC-A Values: IronBarcode returns the correct 12-digit UPC-A value on iOS without any normalization code in the application. Historical UPC-A data stored with a leading zero due to BarcodeScanning.Native.Maui's behavior does not affect the accuracy of values read after migration.
Reliable PDF417: PDF417 is fully supported and reads reliably. Shipping labels, driver's licenses, and boarding passes scan without the "most scans never occur" limitation documented in BarcodeScanning.Native.Maui's GitHub issues.
Barcode Generation: BarcodeWriter.CreateBarcode() and QRCodeWriter.CreateQrCode() generate Code128, QR, DataMatrix, and other formats as PNG files or byte arrays. Generation and reading are available from the same package with no additional dependency.
Server-Side Deployment: The same BarcodeReader.Read() call runs in ASP.NET, Azure Functions, Docker containers, and AWS Lambda. Mobile and server barcode logic can share the same API, the same format support, and the same result type without maintaining two separate barcode implementations.

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.