Utilizing Sitecore Experience Edge GraphQL and BFF architecture

Santosh Kumar
4 min readOct 13, 2024

--

In a Sitecore project utilizing Sitecore Experience Edge GraphQL and the Backend For Frontend (BFF) architecture, the BFF layer serves as a critical component to streamline and optimize data flow between the frontend and backend services.

Why Use BFF in a Sitecore + GraphQL Context?

  • Optimized Data Fetching: Experience Edge GraphQL APIs might return more data than needed for certain frontend components. BFF can fetch the required data from GraphQL queries and restructure it before sending it to the frontend, optimizing performance.
  • Custom Business Logic: Any business logic or user-specific operations (like authorization, personalization) can be handled in the BFF layer without overloading the frontend with logic-heavy operations.
  • Aggregation of Multiple Services: BFF can call Experience Edge, other APIs (like CRM, payment gateways, etc.), and combine responses into a single tailored response for frontend components.
  • Security & Abstraction: BFF hides the complexity of Experience Edge or other backend APIs, exposing a simple, secure API to the frontend. It also provides a layer of security, handling API keys and tokens within the backend rather than exposing them on the client side.

Sitecore Experience Edge GraphQL Use with BFF

Sitecore Experience Edge exposes GraphQL APIs to retrieve content from Sitecore in a headless environment. The BFF layer can interact with these GraphQL APIs in the following way:

  • GraphQL Query Restructuring: BFF can simplify complex GraphQL queries that the frontend would otherwise need to manage. For example, instead of the frontend querying multiple content types, the BFF layer can handle all the GraphQL queries and return a pre-formatted response.
  • Caching: BFF can cache responses from Sitecore Experience Edge to reduce the load on the GraphQL API and improve performance, especially for static or semi-static content.
  • Query and Mutation Logic: If you need to work with mutations (e.g., submitting forms or updating data), BFF can combine the mutation logic with other systems, such as an external database or API.

Example Flow

  • Frontend requests a specific page or component.
  • BFF queries Sitecore Experience Edge for the relevant content using GraphQL.
  • BFF also queries any other backend service if necessary.
  • BFF formats the response and sends a simplified payload to the Frontend.

Designing a Backend for Frontend (BFF) architecture using .NET

Designing a Backend for Frontend (BFF) architecture using .NET involves building a backend service that sits between your frontend application and multiple backend services, including APIs like Sitecore Experience Edge or other external systems.

Technology Stack for BFF in .NET

  • ASP.NET Core Web API: This will serve as the BFF layer.
  • HttpClient: For making HTTP requests to backend services (e.g., Sitecore Experience Edge, external APIs).
  • GraphQL Client : For details on interacting with Sitecore Experience Edge GraphQL APIs, check out my other blog where I explain how to implement the GraphQL.NET Client to consume Sitecore Experience Edge GraphQL APIs.
  • Caching (optional): Use caching mechanisms like MemoryCache or Redis for improving performance.

Steps to Design a .NET BFF

Step 1: Set Up ASP.NET Core Web API

  • Start by creating an ASP.NET Core Web API project using dotnet CLI or Visual Studio.
  • Create the necessary controllers or endpoints that the frontend application will interact with.

Install Required NuGet Packages:

  • Install packages to handle GraphQL queries and HTTP requests.
dotnet add package GraphQL.Client
dotnet add package GraphQL.Client.Serializer.Newtonsoft

Create DTO Classes

Using Data Transfer Objects (DTOs) helps ensure that the data returned from the BFF is decoupled from the internal data structure of the Sitecore Experience Edge GraphQL API. Let’s create DTOs to represent the structure of the data you want to expose from the BFF.

public class ItemDTO
{
public string Name { get; set; }
public List<FieldDTO> Fields { get; set; }
}

public class FieldDTO
{
public string Name { get; set; }
public string Value { get; set; }
}

Define a Service to Call Sitecore Experience Edge GraphQL API

In the BFF, create a service that communicates with Sitecore Experience Edge.

using GraphQL;
using GraphQL.Client.Http;
using GraphQL.Client.Serializer.Newtonsoft;
using System.Linq;
using System.Threading.Tasks;

public class ExperienceEdgeService
{
private readonly GraphQLHttpClient _client;

public ExperienceEdgeService(string apiUrl, string apiKey)
{
_client = new GraphQLHttpClient(apiUrl, new NewtonsoftJsonSerializer());
_client.HttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
}

public async Task<ItemDTO> FetchItemData(string path)
{
var query = @"
query($path: String!) {
item(path: $path) {
name
fields {
name
value
}
}
}";

var request = new GraphQLRequest
{
Query = query,
Variables = new { path }
};

var response = await _client.SendQueryAsync<dynamic>(request);

// Map the response to ItemDTO
var itemData = response.Data.item;

var itemDto = new ItemDTO
{
Name = itemData.name,
Fields = ((IEnumerable<dynamic>)itemData.fields)
.Select(f => new FieldDTO
{
Name = f.name,
Value = f.value
}).ToList()
};

return itemDto;
}
}

Use the Service in a Controller

Create a controller in the BFF that will expose an endpoint for the frontend to consume. This controller will fetch data from Sitecore Experience Edge using the service.

using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

[ApiController]
[Route("api/[controller]")]
public class SitecoreController : ControllerBase
{
private readonly ExperienceEdgeService _experienceEdgeService;

public SitecoreController(ExperienceEdgeService experienceEdgeService)
{
_experienceEdgeService = experienceEdgeService;
}

[HttpGet("content")]
public async Task<IActionResult> GetContent()
{
string path = "/sitecore/content/Home"; // Example content path
var itemData = await _experienceEdgeService.FetchItemData(path);

return Ok(itemData);
}
}

Configure the Service in Startup

In the Startup.cs or Program.cs (for .NET 6+), configure dependency injection for the ExperienceEdgeService

var builder = WebApplication.CreateBuilder(args);

// Add services
builder.Services.AddSingleton<ExperienceEdgeService>(sp =>
new ExperienceEdgeService("https://edge.sitecorecloud.io/api/graphql/v1", "YOUR_API_KEY"));

builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();

app.Run();

Testing the BFF

  1. Run the API: dotnet run
  2. Call the BFF API: Use Postman or cURL to test the API
curl http://localhost:5000/api/sitecore/content

Frontend Integration

Now that you have a .NET BFF in place, the frontend can call the BFF endpoints instead of directly calling the Sitecore Experience Edge API. This pattern improves security, performance, and developer experience.

You can find my other blogs here.

Thank you!

--

--

Santosh Kumar
Santosh Kumar

Written by Santosh Kumar

Software Architect at EPAM Systems. Extensive expertise in Sitecore | XM Cloud | OrderCloud | Content Hub |.Net Core | Azure | AWS | Docker & MACH architecture.

No responses yet