How to Load and Save Images in Blazor Image Editor with SQL Server

Summarize this blog post with:

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:

  1. Open SQL Server Object Explorer: In Visual Studio, go to the View menu and select SQL Server Object Explorer.
  2. Create a new database: In SQL Server Object Explorer, locate the LocalDB server (you may need to expand the node). Right-click on Databases and select Add New Database. Name the new database ImageDB and click OK.
  3. Create a new table in ImageDB: Expand the ImageDB database. Right-click on Tables and select Add New Table.
  4. Define the table schema: Add a new table named ImageCollections with:
    ColumnTypeNotes
    IdNVARCHAR(50)Primary identifier
    NameNVARCHAR(50)Original file name
    ImageDataVARBINARY(MAX)Image bytes
  5. Save the table using the Update button. This structure stores both metadata and the full image content.
ImageCollections table schema
ImageCollections table schema
Sample data stored inside the table
Sample data stored inside the table

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 GET endpoint (api/Images/{id}) retrieves an image from the ImageCollections table using its unique identifier and returns a NotFound response if the record does not exist.
  • The PUT endpoint 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();
});

Designing the user interface

After setting up the backend, configure the user interface to load and save images using the Image Editor and SQL Server LocalDB. Ensure the correct port number from launchSettings.json in the Client project is used in the GetAsync and PutAsync methods.

You can now render the Image Editor component on the page and enable loading and saving images to the database. For detailed information about the Image Editor component, you can refer to the getting started page. Once the Image Editor is rendered, define two asynchronous methods, LoadImageFromDB and SaveImageToDB, to manage image data with a web API.

  • The LoadImageFromDB method fetches image data from an API endpoint using an HTTP GET request, deserializes the response into a CustomImageData object, and opens the image in an Image Editor component using a base64 string if the image data is present.
  • The SaveImageToDB method retrieves image data from the Image Editor through the GetImageDataAsync method, which returns a byte array. This byte array is then used to create a CustomImageData object. The object is serialized to JSON and sent to the API using an HTTP PUT request to update the image data in the database. This setup allows for loading an image from the database and saving edited image data back to the database.

You can now load any image into the image editor, make modifications, and click the Save Image to DB button to save the edited image to the database. The saved, modified image can then be reloaded into the image editor by clicking the “Load Image from DB” button.

Below is the code you need:

@page "/"
@using Newtonsoft.Json
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.ImageEditor
@using System.Text;
@using System.Net.Http
@using System.Net.Http.Headers
@using System.Threading.Tasks
@inject HttpClient HttpClient

<SfImageEditor @ref="imageEditor" Height="550px" />
<SfButton @onclick="SaveImageToDB">Save Image to DB</SfButton>
<SfButton @onclick="LoadImageFromDB">Load Image from DB</SfButton>

@code {
    private SfImageEditor imageEditor;

    // Method to load image from the database
    public async Task LoadImageFromDB()
    {
        var response = await HttpClient.GetAsync("https://localhost:7127/api/image/1");
        if (response.IsSuccessStatusCode)
        {
            var base64Image = await response.Content.ReadAsStringAsync();
            if (!string.IsNullOrEmpty(base64Image))
            {
                await imageEditor.OpenAsync($"data:image/png;base64,{base64Image}");
            }
        }
    }

    // Method to save the image to the database
    public async Task SaveImageToDB()
    {
        if (imageEditor != null)
        {
            var imageBytes = await imageEditor.GetImageDataAsync();
            if (imageBytes != null)
            {
                var formData = new MultipartFormDataContent();
                var imageContent = new ByteArrayContent(imageBytes);
                imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
                formData.Add(imageContent, "imageFile", "image.png");
                formData.Add(new StringContent("1"), "id"); // ID for the image

                var response = await HttpClient.PostAsync("https://localhost:7127/api/image", formData);
                if (response.IsSuccessStatusCode)
                {
                    Console.WriteLine("Image saved successfully");
                }
                else
                {
                    Console.WriteLine($"Error saving image: {response.ReasonPhrase}");
                }
            }
        }
    }
}

To work with the Syncfusion Blazor component, set up the configuration in the Program.cs file as shown below,

using Syncfusion.Blazor
// ……

builder.Services.AddSyncfusionBlazor();

// ……

The GIF below demonstrates image editing, saving, and loading from the database.

Loading, editing and saving images from SQL server in the Blazor Image Editor
Loading, editing, and saving images from SQL server in the Blazor Image Editor

GitHub reference

For more insights, check out the Load and Save Images in Blazor Image Editor from Database sample on the GitHub.

Frequently Asked Questions

How can I load an image from a database into a Blazor Image Editor?

You can load an image by retrieving it from the database as a byte array (byte[]) or Base64 string, then converting it into an image source that the Blazor Image Editor supports (such as a Base64 data URL). The image is then assigned to the editor’s source property during component initialization or via an API call.

What image format should be stored in the database for use with Blazor Image Editor?

It’s recommended to store images as byte arrays (VARBINARY) in the database. This approach is efficient, secure, and allows easy conversion to Base64 when loading the image into the Blazor Image Editor.

How do I save the edited image back to the database?

After editing, you can export the image from the Blazor Image Editor as a Base64 string or byte array. This output can then be converted as needed and saved back to the database using your backend service or API.

Can I load images dynamically without refreshing the page?

Yes. Blazor supports dynamic data binding, so you can load or replace images in the Image Editor at runtime, such as when selecting different records, without reloading the page. This works seamlessly in both Blazor Server and Blazor WebAssembly.

Syncfusion Blazor components can be transformed into stunning and efficient web apps.

Conclusion

Thank you for reading! A complete image-editing workflow in Blazor becomes far simpler with the Syncfusion Blazor Image Editor. With SQL Server as the backend and a clean Web API layer, you can load, edit, and persist images reliably, without hand‑coding complex UI behavior.

This approach improves maintainability, reduces UI bugs, and gives developers a production-grade workflow for handling image content in modern Blazor apps. If you’re exploring robust UI components for Blazor projects, the Image Editor is a strong option worth evaluating.

If you’re a Syncfusion user, you can download the setup from the license and downloads page. Otherwise, you can download a free 30-day trial.

You can also contact us through our support forumsupport portal, or feedback portal for queries. We are always happy to assist you!

Be the first to get updates

Satheeskumar SSatheeskumar S profile icon

Meet the Author

Satheeskumar S

Satheeskumar works as a product manager at Syncfusion, where he specializes in the development of web components with cutting-edge technologies. He is interested in the latest web technologies and provides solutions for great products.

Leave a comment