TL;DR: Learn how to load, edit, and save images in a Blazor application using the Blazor Image Editor, a Web API endpoint, and SQL Server for persistent storage. This guide walks through database setup, EF Core modeling, API integration, and using the Image Editor to round‑trip images between the UI and backend.
Many Blazor applications need to store and manage user‑uploaded images such as profile photos, documents, gallery items, product pictures, and more. Developers often struggle with:
- Converting images to database-friendly formats.
- Moving image bytes between a Web API and the UI.
- Persisting edited images.
- Reopening images in a client-side editor.
- Handling base64, byte arrays, and stream conversions.
This article shows how to store images as binary data in SQL Server LocalDB, retrieve them with C# and EF Core, and load them into the Syncfusion® Blazor Image Editor for editing. The Syncfusion Blazor Image Editor provides built‑in tools for rotating, flipping, zooming, cropping, and annotating images with text, drawings, and shapes. It also includes filters, fine-tuning controls, keyboard shortcuts, and touch-optimized interactions, making it a complete image-editing component for Blazor.
For storage, SQL Server supports BLOB data through types like VARBINARY(MAX), the recommended option since the older IMAGE type is deprecated.
Let’s get started!
Creating a Blazor application
First, create a Blazor WebApp project and install the following NuGet packages in the project, as these packages are prerequisites for connecting to the database:
- EntityFramework
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.SqlServer
Creating a database in SQL LocalDB
To create the database for the application, follow these steps:
-
Open SQL Server Object Explorer: In Visual Studio, go to the
Viewmenu and selectSQL Server Object Explorer. -
Create a new database: In
SQL Server Object Explorer, locate theLocalDBserver (you may need to expand the node). Right-click onDatabasesand selectAdd New Database. Name the new databaseImageDBand clickOK. -
Create a new table in ImageDB: Expand the
ImageDBdatabase. Right-click onTablesand selectAdd New Table. -
Define the table schema: Add a new table named
ImageCollectionswith:
| Column | Type | Notes |
|---|---|---|
| Id | NVARCHAR(50) | Primary identifier |
| Name | NVARCHAR(50) | Original file name |
| ImageData | VARBINARY(MAX) | Image bytes |
- Save the table using the Update button. This structure stores both metadata and the full image content.

Connecting the database to the application
The ImageCollections table in the ImageDB database stores our image records. To connect the Blazor application to this database, copy the connection string from the ImageDB database properties and add it to the appsettings.json file.
Here’s how you can do it in code:
{
"AllowedHosts": "*",
"ConnectionStrings": {
"ImageDbContext": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=ImageDB;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
}
}
Next, create a model class named CustomImageData in the Shared project to represent image data. The class should include properties such as Id for a unique identifier, Name for the image name, Description for a brief description, and ImageData as a byte array to store the image data.
Add this class definition to your project:
public class CustomImageData
{
public string Id { get; set; }
public string Name { get; set; }
public byte[] ImageData { get; set; }
}
Create a DbContext class named ImageDbContext in the Data folder of the Server project. This class should include a DbSet property named ImageCollections that corresponds to the table name in the database, as shown in the code example below.
public class ImageDbContext : DbContext
{
public ImageDbContext(DbContextOptions<ImageDbContext> options)
: base(options)
{
}
public DbSet<CustomImageData> ImageCollections { get; set; }
}
At last, register the ImageDbContext in the Program.cs file of the Server project.
// ….
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext<ImageDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")
)
);
// ….
Creating an API Controller
To access and update image data in the database, create an API controller in the Controllers folder of the Server project. Add a new controller class named ImagesController.
This controller exposes two endpoints for managing image data.
- The
GETendpoint (api/Images/{id}) retrieves an image from theImageCollectionstable using its unique identifier and returns aNotFoundresponse if the record does not exist. - The
PUTendpoint uses the same route to update an existing image with the data provided in the request body. If a matching record is found and the IDs match, the image data is updated and saved; otherwise, a new record is added to the database.
Try this in your project:
using Microsoft.AspNetCore.Mvc;
using BlazorAppDB.Data;
namespace BlazorAppDB.Controller;
{
[Route("api/[controller]")]
[ApiController]
public class ImageController : ControllerBase
{
private readonly ImageDbContext _dbContext;
public ImageController(ImageDbContext dbContext)
{
_dbContext = dbContext;
}
[HttpPost]
public IActionResult SaveImage([FromForm] string id, [FromForm] IFormFile imageFile)
{
if (string.IsNullOrEmpty(id) || imageFile == null || imageFile.Length == 0)
{
return BadRequest("Invalid input");
}
using (var memoryStream = new MemoryStream())
{
// Copy the uploaded file's content into the memory stream
imageFile.CopyTo(memoryStream);
// Convert the memory stream into a byte array
byte[] imageBytes = memoryStream.ToArray();
// Check if the image already exists
var existingImage = _dbContext.ImageCollections.FirstOrDefault(i => i.Id == id);
if (existingImage != null)
{
// Update existing image
existingImage.Name = imageFile.FileName;
existingImage.ImageData = imageBytes;
}
else
{
// Add new image
var imageRecord = new CustomImageData
{
Id = id,
Name = imageFile.FileName,
ImageData = imageBytes
};
_dbContext.ImageCollections.Add(imageRecord);
}
_dbContext.SaveChanges();
return Ok("Image saved successfully");
}
}
[HttpGet("{id}")]
public IActionResult LoadImage(string id)
{
var image = _dbContext.ImageCollections.FirstOrDefault(i => i.Id == id);
if (image == null)
{
return NotFound("Image not found");
}
// Convert the byte array to a Base64 string
var base64Image = Convert.ToBase64String(image.ImageData);
return Ok(base64Image);
}
}
}
To work with the API controller, set up the configuration below in the Program.cs file.
// ……
builder.Services.AddControllers();
builder.Services.AddControllersWithViews();
builder.Services.AddServerSideBlazor()
.AddHubOptions(o =>
{
o.MaximumReceiveMessageSize = 102400000;
});
// …..
app.UseRouting();
app.UseAntiforgery();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
This article was originally published at Syncfusion.com.

Top comments (0)