---
title: "Implementing GraphQL in .NET for a Todo API"  
description: "GraphQL has become a popular alternative to REST APIs because it allows clients to request exactly the data they need—no more, no less. Unlike REST, where multi"  
author: "Anubhav Sharma"  
published: 2026-01-12  
updated: 2026-01-13  
canonical: https://answers.mindstick.com/blog/21/implementing-graphql-in-dot-net-for-a-todo-api  
category: "asp.net"  
tags: ["asp.net", ".net programming"]  
reading_time: 5 minutes  

---

# Implementing GraphQL in .NET for a Todo API

## 1. Introduction

Modern applications—especially SPAs and mobile apps—require APIs that are **flexible, efficient, and scalable**. Traditional REST APIs often return fixed data structures, leading to problems like **over-fetching** (getting more data than needed) or **under-fetching** (requiring multiple API calls).

[**GraphQL**](https://www.mindstick.com/articles/337634/how-to-use-graphql-for-efficient-data-fetching-and-management) solves these problems by allowing clients to request *exactly* the data they need through a single endpoint, guided by a strongly typed schema.

In this article, we will build a **Todo API using GraphQL in .NET**, step by step, using **Hot Chocolate**, one of the most mature [GraphQL](https://www.mindstick.com/articles/337634/how-to-use-graphql-for-efficient-data-fetching-and-management) libraries for .NET.

This guide is intentionally detailed and suitable for:

- Backend .NET developers
- Developers migrating from REST to GraphQL
- Teams building APIs for [Angular](https://training.mindstick.com/courses/202/angular-js-javascript-framework-upcoming7), [React](https://www.mindstick.com/category/forum/react-js), or [mobile apps](https://www.mindstick.com/services/mobile-app-development)

## 2. What is GraphQL?

GraphQL is a **query language for APIs** and a **runtime** for executing those queries using your existing data.

### Key Characteristics

- **Single Endpoint**: Typically `/graphql`
- **Strongly Typed Schema**: Contract between client and server
- **Client-driven Queries**: Client decides the shape of the response
- **Introspection**: APIs are self-documenting

### REST vs GraphQL (Quick Comparison)

| Feature | REST | GraphQL |
| --- | --- | --- |
| Endpoints | Multiple | Single |
| Over-fetching | Common | Eliminated |
| Under-fetching | Common | Eliminated |
| [Versioning](https://www.mindstick.com/interview/34107/how-do-you-implement-file-versioning-when-saving-edits-to-a-document) | Required | Usually not needed |
| Schema | Implicit | Explicit & Typed |

## 3. Why Use GraphQL for a Todo API?

Although a Todo API is simple, it demonstrates real-world GraphQL benefits:

- Query only `id` and `title` when needed
- Fetch a single Todo or all Todos with the same endpoint
- Combine multiple operations in one request
- Clean evolution of API without breaking clients

## 4. Project Setup

### 4.1 Create the Project

```plaintext
dotnet new webapi -n TodoGraphQLApi
cd TodoGraphQLApi
```

Remove sample files like `WeatherForecast.cs` to keep the solution clean.

### 4.2 Install Required NuGet Packages

We will use **Hot Chocolate** for GraphQL support:

```plaintext
dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.Data
dotnet add package HotChocolate.Types
```

Why Hot Chocolate?

- Native .NET experience
- Schema-first and code-first support
- Excellent performance
- Actively maintained

## 5. Designing the Domain Model

### 5.1 Todo Entity

```cs
public class TodoItem
{
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public bool IsCompleted { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
```

This model will later map directly to GraphQL types.

## 6. Data Access Layer (Repository Pattern)

To keep GraphQL resolvers clean and testable, we use a **repository layer**.

### 6.1 Repository Interface

```cs
public interface ITodoRepository
{
    IEnumerable<TodoItem> GetAll();
    TodoItem? GetById(int id);
    TodoItem Add(TodoItem todo);
    TodoItem? Update(int id, bool isCompleted);
    bool Delete(int id);
}
```

### 6.2 In-Memory Repository Implementation

```cs
public class TodoRepository : ITodoRepository
{
    private readonly List<TodoItem> _todos = new();
    private int _idCounter = 1;

    public IEnumerable<TodoItem> GetAll() => _todos;

    public TodoItem? GetById(int id)
        => _todos.FirstOrDefault(t => t.Id == id);

    public TodoItem Add(TodoItem todo)
    {
        todo.Id = _idCounter++;
        _todos.Add(todo);
        return todo;
    }

    public TodoItem? Update(int id, bool isCompleted)
    {
        var todo = GetById(id);
        if (todo == null) return null;
        todo.IsCompleted = isCompleted;
        return todo;
    }

    public bool Delete(int id)
    {
        var todo = GetById(id);
        if (todo == null) return false;
        _todos.Remove(todo);
        return true;
    }
}
```

> In real projects, this can be replaced with [**Entity Framework**](https://www.mindstick.com/forum/159846/entity-framework-get-entity-by-name) **+** [**SQL Server**](https://training.mindstick.com/courses/103/sql-server-upcoming5)**/**[**PostgreSQL**](https://answers.mindstick.com/qa/92847/what-is-postgresql) without changing GraphQL logic.

## 7. GraphQL Schema Concepts

GraphQL APIs are built around:

- **Query** – Read operations
- **Mutation** – Write operations
- **Type System** – Object, Input, Enum, Scalar

Hot Chocolate automatically infers schema from C# classes.

## 8. Implementing GraphQL Queries

Queries fetch data and must be **side-effect free**.

```cs
public class Query
{
    public IEnumerable<TodoItem> GetTodos([Service] ITodoRepository repo)
        => repo.GetAll();

    public TodoItem? GetTodoById(int id, [Service] ITodoRepository repo)
        => repo.GetById(id);
}
```

### Example Query

```cs
query {
  todos {
    id
    title
    isCompleted
  }
}
```

## 9. Implementing GraphQL Mutations

Mutations modify server-side data.

```cs
public class Mutation
{
    public TodoItem AddTodo(string title, [Service] ITodoRepository repo)
    {
        return repo.Add(new TodoItem
        {
            Title = title,
            IsCompleted = false
        });
    }

    public TodoItem? CompleteTodo(int id, [Service] ITodoRepository repo)
    {
        return repo.Update(id, true);
    }

    public bool DeleteTodo(int id, [Service] ITodoRepository repo)
    {
        return repo.Delete(id);
    }
}
```

### Example Mutation

```cs
mutation {
  addTodo(title: "Build GraphQL API") {
    id
    title
    isCompleted
  }
}
```

## 10. Dependency Injection & Configuration

### 10.1 Register Services

```cs
builder.Services.AddSingleton<ITodoRepository, TodoRepository>();

builder.Services
    .AddGraphQLServer()
    .AddQueryType<Query>()
    .AddMutationType<Mutation>();
```

### 10.2 Enable GraphQL Endpoint

```cs
app.MapGraphQL("/graphql");
```

Once the app is running, Hot Chocolate provides a built-in **GraphQL IDE**.

## 11. Testing the API

Navigate to:

```plaintext
https://localhost:{port}/graphql
```

You can:

- Explore schema via documentation panel
- Run queries and mutations
- Validate requests automatically

## 12. Error Handling in GraphQL

GraphQL always returns `200 OK`, but errors are included in the response:

```javascript
{
  "data": null,
  "errors": [
    {
      "message": "Todo not found"
    }
  ]
}
```

This makes client-side handling predictable.

## 13. Security Considerations

In real-world applications:

- Use [**Authorization**](https://www.mindstick.com/interview/34210/what-are-the-common-authentication-methods-in-rest-apis) **directives**
- Limit query depth & complexity
- Validate input using input types
- Enable persisted queries

Hot Chocolate supports all of these features.

## 14. When to Choose GraphQL

GraphQL is ideal when:

- Multiple clients consume the same API
- Frontend requirements change frequently
- You want strong contracts without versioning

Avoid GraphQL when:

- APIs are extremely simple
- Heavy HTTP caching is mandatory

## 15. Conclusion

Implementing GraphQL in .NET using Hot Chocolate provides a **clean, scalable, and modern API architecture**. Even a simple Todo API demonstrates how GraphQL replaces multiple REST endpoints with a single, powerful schema.

From here, you can extend this API by adding:

- [Entity Framework Core](https://www.mindstick.com/interview/34144/what-is-ef-core)
- Pagination & filtering
- Authentication & authorization
- GraphQL subscriptions for real-time updates
- GraphQL is a future-proof choice for modern .NET applications.

## Happy Coding!

---

Original Source: https://answers.mindstick.com/blog/21/implementing-graphql-in-dot-net-for-a-todo-api

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
