GraphQL vs REST in C#: What to Choose for Your API in 2024

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

GraphQL vs REST in C#: Battle of the Titans or Choosing the Right Tool for the Job?

\n\n

Hello, colleagues! If you write in C# and create APIs, the question "REST or GraphQL?" has surely come up more than once. It's like arguing about what's better: a hammer or a screwdriver. Both are tools, but for different tasks. In this article, we won't fanatically defend one technology, but will soberly, with C# code examples, analyze when GraphQL wins and when good old REST remains king.

\n\n

We are the PythonLib team, and although the name includes "Python," we love the .NET and C# ecosystem. Today we'll dive into the world of C# APIs and figure out how not to make a mistake with your choice. Let's go!

\n\n

Quick Primer: REST and GraphQL for the C# Developer

\n\n

REST (Representational State Transfer) is an architectural style we all know and love. In C#, you're most likely using ASP.NET Core Web API. You create controllers, endpoints, and each endpoint returns a fixed data structure. Want to get a user? Go to /api/users/1. Want their orders? Go to /api/users/1/orders. Simple, predictable, but often leads to over-fetching (getting unnecessary data) or under-fetching (needing to make multiple requests).

\n\n

GraphQL is a query language developed by Facebook. In the C# world, it's implemented through libraries like Hot Chocolate (the most popular) or GraphQL.NET. You have one endpoint (usually /graphql), and the client decides which fields it needs. Want the user's name and only the first order? Please! No over-fetching.

\n\n

Practical Comparison: C# Code

\n\n

Let's move from theory to code. Imagine we have a simple model: User and Order.

\n\n
// Data Models\npublic class User\n{\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public string Email { get; set; }\n    public string Phone { get; set; }\n    public List<Order> Orders { get; set; }\n}\n\npublic class Order\n{\n    public int Id { get; set; }\n    public string ProductName { get; set; }\n    public decimal Price { get; set; }\n    public DateTime CreatedAt { get; set; }\n}\n
\n\n

REST API Example on ASP.NET Core

\n\n
[ApiController]\n[Route("api/[controller]")]\npublic class UsersController : ControllerBase\n{\n    [HttpGet("{id}")]\n    public async Task<ActionResult<User>> GetUser(int id)\n    {\n        // Assume data comes from the database\n        var user = await _dbContext.Users.FindAsync(id);\n        if (user == null) return NotFound();\n        return Ok(user); // Returns ALL fields: Id, Name, Email, Phone, Orders\n    }\n}\n
\n\n

The problem? If the client only needs the name and email, it still gets Phone and Orders. And if orders are needed, a separate request to /api/users/1/orders must be made.

\n\n

GraphQL API Example on Hot Chocolate

\n\n
public class Query\n{\n    public async Task<User> GetUser(int id, [Service] AppDbContext dbContext)\n    {\n        return await dbContext.Users.FindAsync(id);\n    }\n}\n\n// Registration in Program.cs\nbuilder.Services\n    .AddGraphQLServer()\n    .AddQueryType<Query>();\n
\n\n

Now the client can request exactly what is needed:

\n\n
// GraphQL query\n{\n  user(id: 1) {\n    name\n    email\n    orders {\n      productName\n      price\n    }\n  }\n}\n
\n\n

The response will contain only name, email, and an array of orders with the fields productName and price. No junk. Beautiful!

\n\n

When REST in C# Wins (and That's Okay)

\n\n

1. Simplicity and Caching. REST APIs are easy to cache at the HTTP level (CDN, proxies). A GET request to /api/products can be cached, and everything is fine.

Blogs

Book Recommendations