Display Images in Bootstrap Carousel using Razor Pages and Entity Framework

This short article shows how to display images stored in a database in a Razor Pages application using the Bootstrap Carousel and Entity Framework Core.

Images can be stored in a database in two ways: you can either save the file to the server's file system and store the name and/or path of the image file, or you can store the file itself in binary format. Each approach has its pros and cons. Rather than get into the debate about which storage method is better, I'll show how to work with the Carousel using both approaches.

The carousel transitions through a series of content which can include images and text. A huge number of carousel components are available, ranging widely in terms of their features and complexity. The Bootstrap carousel benefits from not requiring any additional components and from its simplicity. It caters for the majority of use cases, supporting cycling content from right to left, fade transitions and simple replacement of content. It also supports controls, indicators and captions.

The key elements of a Bootstrap carousel are an element with the carousel class applied to it, and a number of elements with the carousel-item class applied to them within an element with carousel-inner applied to it.

<div class="carousel">
    <div class="carousel-inner">
        <div class="carousel-item active>...</div>
        <div class="carousel-item>...</div>
        <div class="carousel-item>...</div>
    </div>
</div>

The content to be displayed is placed within the carousel-item elements, one of which needs to have the active class added to make the carousel visible.

The carousel supports a number of options which can be applied declaratively via CSS classes or data-* attributes, or they can be specified in client-side code. At the moment, the carousel simply replaces one set of content with the next without any transition between them. The slide class causes content to slide in from right to left. The default interval between transitions is 5 seconds. You can use the data-interval attribute to specify a different interval in milliseconds. The data-ride option is used to specify whether the carousel should auto play. A value of carousel results in the carousel auto-playing on load. Using these options, the following set up will result in a carousel that slides content from right to left every 2 seconds and auto plays:

<div class="carousel slide" data-ride="carousel" data-interval="2000">
    <div class="carousel-inner">
        <div class="carousel-item active>...</div>
        <div class="carousel-item>...</div>
        <div class="carousel-item>...</div>
    </div>
</div>

First, I'll look at images stored in the file system. I'm using the Northwind sample database for the demo and will display employees' photos in the carousel. The Employee entity has a property named PhotoPath, which is a string. In my version, the value stored in the corresponding database column is just the file name of the employee's photo. The image files are located in wwwroot/images:

images

I have an EmployeeService class responsible for obtaining data using Entity Framework Core. It has one method that gets all employee data:

public class EmployeeService : IEmployeeService
{
    private readonly NorthwindContext context;
    public EmployeeService(NorthwindContext context) => this.context = context;
    public async Task<List<Employee>> GetEmployees() => await context.Employees.ToListAsync();
}

The GetEmployees method is called in the PageModel class and the data assigned to a public property:

public class CarouselModel : PageModel
{
    private readonly IEmployeeService employeeService;
    public CarouselModel(IEmployeeService employeeService) =>  this.employeeService = employeeService;
    public List<Employee> Employees { getset; }
    public async Task OnGetAsync()
    {
        Employees = await employeeService.GetEmployees();
    }
}

In the content page, the PhotoPath property is used to build a relative URL to each image as each employee is iterated and a corresponding carousel-item element is rendered:

<div class="carousel slide" data-ride="carousel" data-interval="2000" style="width:192px;">
    <div class="carousel-inner">
        @foreach (var employee in Model.Employees)
        {
        <div class="carousel-item @(employee == Model.Employees.First() ? "active" : "")">
            <img src="~/images/@employee.PhotoPath" alt="@employee.FirstName @employee.LastName">
        </div>
        }
    </div>
</div>

Note that the width of the carousel has been constrained to the width of the images. Also see that the active class is applied to the carousel-item element generated for the first employee entity in the sequence to ensure the carousel appears. The first and last name of the employee is used to generate a suitable alt attribute value.

So how do you get binary images into a carousel? Probably the easiest way is to use data URIs. Using this approach, you embed the binary data encoded as a Base 64 string and assign it to the src attribute of an img element.

The .NET data taype that maps to the database varbinary or BLOB types is a byte array. The Employee entity has a property named Photo that maps to the appropriate database column:

public byte[] Photo { getset; }

This is how the code that generates the carousel-item elements is modified to make use of data URIs:

@foreach (var employee in Model.Employees)
{
<div class="carousel-item @(employee == Model.Employees.First() ? "active" : "")">
    <img src="data:image/jpg;base64,@Convert.ToBase64String(employee.Photo)" alt="@employee.FirstName @employee.LastName">
</div>
}

The format of the data URI is the scheme data folowed by a colon, then the mime type, in this case image/jpg, although just image will do. This is followed by a semi-colon, and then the encoding. A number of encodings are supported, but Base64 encoding is used for binary data. This is followed by a required comma, and then the actual data, encoded using the suitable .NET method.

What about including a caption? This is achieved by adding the carousel-caption class to an element within each carousel-item:

@foreach (var employee in Model.Employees)
{
<div class="carousel-item @(employee == Model.Employees.First() ? "active" : "")">
    <img src="data:image/jpg;base64,@Convert.ToBase64String(employee.Photo)" alt="@employee.FirstName @employee.LastName">
    <div class="carousel-caption">
        <p class="mb-0">@employee.FirstName @employee.LastName</p>
    </div>
</div>
}

Summary

Whether you store images in the file system or as binary data, it is pretty easy to display them using the Bootstrap carousel in Razor Pages.