Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Build an ASP.NET Core API (manual GraphQL client)

Learn how to build an ASP.NET Core Web API that retrieves content from Optimizely Graph using a lightweight manual GraphQL client.

This guide shows how to build an ASP.NET Core Web API that connects to Optimizely Graph, queries content with GraphQL, and exposes the results through REST endpoints. Use the manual GraphQL client approach when you want a lightweight integration and full control over query strings and response models.

The manual client approach fits the following scenarios:

  • Small or experimental projects.
  • Learning how GraphQL requests and responses work.
  • Projects that need full control over queries and models.

For automatic code generation, strong typing, and compile-time validation, see Build an ASP.NET Core API with StrawberryShake instead.

Create an ASP.NET Core project

Scaffold a Web API project that hosts the controllers and GraphQL client wiring used throughout this guide.

dotnet new webapi -n MyOptimizelyApp
cd MyOptimizelyApp

Install dependencies

Add the GraphQL HTTP client packages that send queries to Optimizely Graph and deserialize the JSON responses.

dotnet add package GraphQL.Client
dotnet add package GraphQL.Client.Serializer.Newtonsoft
dotnet add package Microsoft.Extensions.Options.ConfigurationExtensions

Create GraphQL schema and queries

Download the schema and author the queries the controller sends to Optimizely Graph. The examples below target the Alloy template content types.

# Download schema
dotnet graphql download https://cg.optimizely.com/content/v2?auth=YOUR_ACCESS_KEY -f schema.graphql

Use the following query to retrieve a list of articles from the database.

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 the GraphQL client

Configure the GraphQL client so the controller can resolve a typed HTTP client at runtime and send queries to Optimizely Graph.

Create a .graphqlrc.json configuration file.

{
   "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 GraphQL client in Program.cs.

using GraphQL.Client.Http;
using GraphQL.Client.Serializer.Newtonsoft;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<GraphQLHttpClient>(provider =>
{
    return new GraphQLHttpClient(
        "https://cg.optimizely.com/content/v2?auth=YOUR_KEY",
        new NewtonsoftJsonSerializer()
    );
});

builder.Services.AddControllers();

var app = builder.Build();

app.UseRouting();
app.MapControllers();
app.Run();

Store the endpoint in configuration (optional)

Move the Optimizely Graph endpoint out of code into appsettings.json so environments override the value without recompiling.

{
  "OptimizelyGraph": {
    "Endpoint": "https://cg.optimizely.com/content/v2?auth=YOUR_KEY"
  }
}

Create the response model

Define C# classes that mirror the GraphQL response shape so the deserializer maps fields onto strongly typed objects.

public class Article
{
    public ContentLink ContentLink { get; set; }
    public string Name { get; set; }
    public string RelativePath { get; set; }
    public string TeaserText { get; set; }
    public MediaReference PageImage { get; set; }
    public string MainBody { get; set; }
}

public class ContentLink { public string Id { get; set; } }

public class MediaReference { public string Url { get; set; } }

public class ContentResponse
{
    public List<Article> Items { get; set; } = new();
    public int Total { get; set; }
}

public class GraphQLResponse<T>
{
    public T ArticlePage { get; set; }
}

Create a controller

Expose the Optimizely Graph data through an ASP.NET Core controller that sends GraphQL queries with the manual client and returns the results from REST endpoints.

Create Controllers/ArticlesController.cs.

using GraphQL;
using GraphQL.Client.Http;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ArticlesController : ControllerBase
{
    private readonly GraphQLHttpClient _graphQLClient;

    public ArticlesController(GraphQLHttpClient graphQLClient)
    {
        _graphQLClient = graphQLClient;
    }

    [HttpGet]
    public async Task<ActionResult> GetArticles()
    {
        var query = @"
        query {
            ArticlePage(orderBy: { _modified: DESC }, limit: 10) {
                items {
                    ContentLink { Id }
                    Name
                    RelativePath
                    TeaserText
                    PageImage { Url }
                    MainBody
                }
                total
            }
        }";

        var request = new GraphQLRequest { Query = query };
        var response =
            await _graphQLClient.SendQueryAsync<GraphQLResponse<ContentResponse>>(request);

        if (response.Errors?.Any() == true)
        {
            return BadRequest(response.Errors);
        }

        return Ok(response.Data.ArticlePage);
    }
}

Run and test the API

Build and run the application to confirm the controller resolves the GraphQL client and returns content from Optimizely Graph.

dotnet build
dotnet run

Test the API endpoint

Send a request to the controller route to verify the round trip between the API, the manual GraphQL client, and Optimizely Graph.

Use the https://localhost:7000/api/articles endpoint to test the API and confirm it returns content from Optimizely Graph.