Build an ASP.NET Core API using StrawberryShake (recommended)
Learn how to build an ASP.NET Core Web API that retrieves content from Optimizely Graph using StrawberryShake for strongly typed queries and automatic client generation.
This guide shows how to build an ASP.NET Core Web API that connects to Optimizely Graph using StrawberryShake, a strongly typed GraphQL client with automatic code generation. Use this approach when you want compile-time query validation and generated models that keep the C# code in sync with the Optimizely Graph schema.
Optimizely recommends this approach for most production applications because StrawberryShake does the following:
- Validates queries at build time.
- Generates strongly typed models automatically.
- Provides IntelliSense support.
- Reduces manual serialization and mapping code.
For a lightweight manual client instead, see Build an ASP.NET Core API (manual GraphQL client).
Create an ASP.NET Core project
Scaffold the Web API project that hosts the StrawberryShake-generated client and the controllers in the rest of the guide.
dotnet new webapi -n MyOptimizelyApp
cd MyOptimizelyAppInstall StrawberryShake tools
Add the StrawberryShake CLI tools to the local manifest so the project can download schemas and generate the typed client.
dotnet new tool-manifest
dotnet tool install StrawberryShake.ToolsInstall StrawberryShake packages
Add the runtime and code-generation packages that the generated client depends on.
dotnet add package StrawberryShake.AspNetCore
dotnet add package StrawberryShake.CodeGeneration.CSharp.AnalyzersConfigure the project
Register .graphql files as inputs to the source generator so StrawberryShake picks up the query documents during build.
Update MyOptimizelyApp.csproj.
<ItemGroup>
<GraphQL Include="**/*.graphql" />
</ItemGroup>Download the schema
Pull the Optimizely Graph schema into the project so StrawberryShake validates queries against the live shape of the service.
dotnet graphql download https://cg.optimizely.com/content/v2?auth=YOUR_KEY -f schema.graphqlCreate GraphQL queries
Define the queries StrawberryShake compiles into strongly typed methods on the generated client.
Create Queries/ArticleQueries.graphql.
query GetArticles($limit: Int = 10, $skip: Int = 0) {
ArticlePage(orderBy: { _modified: DESC }, limit: $limit, skip: $skip) {
items {
ContentLink { Id }
Name
RelativePath
TeaserText
PageImage { Url }
MainBody
}
total
}
}
query GetArticleById($id: String!) {
ArticlePage(where: { ContentLink: { Id: { eq: $id } } }) {
items {
ContentLink { Id }
Name
RelativePath
TeaserText
PageImage { Url }
MainBody
_modified
}
}
}Configure StrawberryShake
Point StrawberryShake at the downloaded schema and the query folder, and name the generated client and namespace.
Create .graphqlrc.json.
{
"schema": "schema.graphql",
"documents": "Queries/**/*.graphql",
"extensions": {
"strawberryShake": {
"name": "OptimizelyGraphClient",
"namespace": "MyOptimizelyApp.GraphQL",
"url": "https://cg.optimizely.com/content/v2?auth=YOUR_KEY"
}
}
}Register the generated client
Wire the StrawberryShake client into dependency injection so controllers receive IOptimizelyGraphClient through the constructor.
Update Program.cs.
using MyOptimizelyApp.GraphQL;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddOptimizelyGraphClient()
.ConfigureHttpClient(client =>
{
client.BaseAddress =
new Uri("https://cg.optimizely.com/content/v2?auth=YOUR_KEY");
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseRouting();
app.MapControllers();
app.Run();
Generate the client
Run dotnet build to generate strongly typed classes in MyOptimizelyApp.GraphQL.
Create a controller
Expose the generated GraphQL operations through REST endpoints that the front end consumes.
using Microsoft.AspNetCore.Mvc;
using MyOptimizelyApp.GraphQL;
[ApiController]
[Route("api/[controller]")]
public class ArticlesController : ControllerBase
{
private readonly IOptimizelyGraphClient _graphQLClient;
public ArticlesController(IOptimizelyGraphClient graphQLClient)
{
_graphQLClient = graphQLClient;
}
[HttpGet]
public async Task<ActionResult> GetArticles(int limit = 10, int skip = 0)
{
var result = await _graphQLClient.GetArticles.ExecuteAsync(limit, skip);
if (result.IsErrorResult())
{
return BadRequest(result.Errors);
}
return Ok(result.Data?.ArticlePage);
}
[HttpGet("{id}")]
public async Task<ActionResult> GetArticleById(string id)
{
var result = await _graphQLClient.GetArticleById.ExecuteAsync(id);
if (result.IsErrorResult())
{
return BadRequest(result.Errors);
}
var article = result.Data?.ArticlePage?.Items?.FirstOrDefault();
if (article == null)
{
return NotFound();
}
return Ok(article);
}
}Run and test
Build and run the API to confirm the generated client resolves correctly and the endpoints return content from Optimizely Graph.
dotnet build
dotnet runOpen the following endpoints in a browser or API tool.
https://localhost:7000/api/articles– Retrieves all articles from Optimizely Graph.https://localhost:7000/api/articles/{ID}– Retrieves a specific article by its content ID. Replace{ID}with an actual article ID.
Updated 10 days ago
