Task Management API with GraphQL in ASP.NET Core

Introduction

Creating a complete CRUD (Create, Read, Update, Delete) operation using GraphQL in an ASP.NET Core Web API can be quite extensive, so I'll provide you with a simplified example using a "Task Management" application as a real-world use case. In this example, we'll manage tasks with GraphQL.

Step 1. Set Up Your ASP.NET Core Web API Project

Create a new ASP.NET Core Web API project in Visual Studio or using the command-line tools.

dotnet new webapi -n TaskManagementApi
cd TaskManagementApi

Install the necessary NuGet packages.

dotnet add package GraphQL.Server.Transports.AspNetCore
dotnet add package GraphQL.Server.Ui.Playground
dotnet add package HotChocolate
dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.AspNetCore.Playground

Create a Task model and a TaskRepository class for data management.

public class Task
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public DateTime DueDate { get; set; }
    public bool IsCompleted { get; set; }
}

public class TaskRepository
{
    private readonly List<Task> _tasks = new List<Task>();
    private int _nextId = 1;

    public Task AddTask(Task task)
    {
        task.Id = _nextId++;
        _tasks.Add(task);
        return task;
    }

    public Task GetTask(int id)
    {
        return _tasks.FirstOrDefault(t => t.Id == id);
    }

    public List<Task> GetAllTasks()
    {
        return _tasks;
    }

    public Task UpdateTask(int id, Task updatedTask)
    {
        var existingTask = _tasks.FirstOrDefault(t => t.Id == id);
        if (existingTask != null)
        {
            existingTask.Title = updatedTask.Title;
            existingTask.Description = updatedTask.Description;
            existingTask.DueDate = updatedTask.DueDate;
            existingTask.IsCompleted = updatedTask.IsCompleted;
        }
        return existingTask;
    }

    public bool DeleteTask(int id)
    {
        var taskToRemove = _tasks.FirstOrDefault(t => t.Id == id);
        if (taskToRemove != null)
        {
            _tasks.Remove(taskToRemove);
            return true;
        }
        return false;
    }
}

Step 2. Create GraphQL Types and Resolvers

Create GraphQL types and resolvers to define the schema and how data is fetched.

public class TaskType : ObjectType<Task>
{
    protected override void Configure(IObjectTypeDescriptor<Task> descriptor)
    {
        descriptor.Field(t => t.Id).Type<NonNullType<IntType>>();
        descriptor.Field(t => t.Title);
        descriptor.Field(t => t.Description);
        descriptor.Field(t => t.DueDate);
        descriptor.Field(t => t.IsCompleted);
    }
}


public class Query
{
    [UseDbContext(typeof(TaskRepository))]
    public IEnumerable<Task> GetTasks([ScopedService] TaskRepository taskRepository)
    {
        return taskRepository.GetAllTasks();
    }

    [UseDbContext(typeof(TaskRepository))]
    public Task GetTask(int id, [ScopedService] TaskRepository taskRepository)
    {
        return taskRepository.GetTask(id);
    }
}

// Mutation.cs
public class Mutation
{
    [UseDbContext(typeof(TaskRepository))]
    public Task CreateTask(Task task, [ScopedService] TaskRepository taskRepository)
    {
        return taskRepository.AddTask(task);
    }

    [UseDbContext(typeof(TaskRepository))]
    public Task UpdateTask(int id, Task updatedTask, [ScopedService] TaskRepository taskRepository)
    {
        return taskRepository.UpdateTask(id, updatedTask);
    }

    [UseDbContext(typeof(TaskRepository))]
    public bool DeleteTask(int id, [ScopedService] TaskRepository taskRepository)
    {
        return taskRepository.DeleteTask(id);
    }
}

Step 3. Configure GraphQL

Configure GraphQL in your Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddSingleton<TaskRepository>();

    services.AddGraphQLServer()
        .AddQueryType<Query>()
        .AddMutationType<Mutation>()
        .AddType<TaskType>()
        .AddFiltering()
        .AddSorting();

    services.AddGraphQLServer()
        .AddQueryType<Query>()
        .AddMutationType<Mutation>()
        .AddType<TaskType>()
        .AddFiltering()
        .AddSorting();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGraphQL();
    });
}

Step 4. Test Your GraphQL API

You can now run your ASP.NET Core Web API and test your GraphQL API using tools like GraphQL Playground or Postman. Your API will have the following CRUD operations.

  • Create a task
  • Read all tasks
  • Read a task by ID
  • Update a task 

These are the operations we have performed in this example.

Conclusion

This example demonstrates how to create a complete CRUD Create, Read, Update, Delete) operation using GraphQL in an ASP.NET Core Web API. We used a simplified "Task Management" application as a real-world use case to illustrate the key steps involved. Here are the key takeaways.

  1. Set Up Your ASP.NET Core Web API: Create a new ASP.NET Core Web API project and install the necessary NuGet packages for GraphQL.
  2. Create Models and Data Management: Define your data models e.g. Task, and create a repository class e.g., TaskRepository, to manage data operations.
  3. Create GraphQL Types and Resolvers: Define GraphQL types e.g. TaskType, and create resolvers e.g., Query and Mutation, to specify how data is fetched, created, updated, and deleted.
  4. Configure GraphQL: Configure GraphQL in your Startup. cs file by adding GraphQL services and specifying the schema using the defined types and resolvers.
  5. Test Your GraphQL API: Run your ASP.NET Core Web API and use GraphQL Playground or Postman tools to test the CRUD operations.

In a real-world application, you would likely enhance this example by adding authentication and authorization mechanisms, handling validation and error responses, and integrating more complex business logic. Nonetheless, this example provides a foundation for building GraphQL-based APIs in ASP.NET Core, allowing you to efficiently manage and interact with your data.