---
title: Build an ASP.NET Core API using StrawberryShake (recommended)
slug: graph/docs/build-an-asp-net-core-api-using-strawberryshake-recommended
docTags: 
createdAt: 2026-07-30T20:30:18.888Z
---

This guide shows how to build an ASP.NET Core Web API that connects to Optimizely Graph using [StrawberryShake](https://strawberry.rocks/docs), 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](https://code.visualstudio.com/docs/editing/intellisense) support.
- Reduces manual serialization and mapping code.

For a lightweight manual client instead, see [Build an ASP.NET Core API (manual GraphQL client)](docId\:z0ZIvji4vgfsusDhaIG3T).

## 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.

```bash
dotnet new webapi -n MyOptimizelyApp
cd MyOptimizelyApp
```

## Install StrawberryShake tools

Add the StrawberryShake CLI tools to the local manifest so the project can download schemas and generate the typed client.

```bash
dotnet new tool-manifest
dotnet tool install StrawberryShake.Tools
```

## Install StrawberryShake packages

Add the runtime and code-generation packages that the generated client depends on.

```bash
dotnet add package StrawberryShake.AspNetCore
dotnet add package StrawberryShake.CodeGeneration.CSharp.Analyzers
```

## Configure the project

Register `.graphql` files as inputs to the source generator so StrawberryShake picks up the query documents during build.

Update `MyOptimizelyApp.csproj`.

```xml
<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.

```bash
dotnet graphql download https://cg.optimizely.com/content/v2?auth=YOUR_KEY -f schema.graphql
```

## Create GraphQL queries

Define the queries StrawberryShake compiles into strongly typed methods on the generated client.

Create `Queries/ArticleQueries.graphql`.

```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`.

```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`.

```csharp
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.

```csharp
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.

```bash
dotnet build
dotnet run
```

Open 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.
