Hey devs, ustedes saben lo mucho que yo trabajo con REST y que es algo que me gusta, tanto así que hice este artículo y este otro en un blog amigo donde soy redactor técnico como para difundir un REST bien aplicado y entendido, sin embargo eso no significa que sea la panacea, en esta ocasión te traigo una alternativa a REST llamado GraphQL, así que comencemos!
GraphQL es una alternativa moderna a REST que te permite pedir exactamente los datos que necesitas en una sola petición, sin endpoints repetidos ni overfetching.
GraphQL no es un estilo arquitectónico completo como REST, pero sí es una alternativa al uso de REST para APIs de forma estructurada. Son equivalentes solo en el sentido de que ambos definen cómo interactúan los clientes con los datos del servidor, pero no son idénticos ni tienen el mismo alcance arquitectónico.
REST es como seguir una receta de cocina con pasos y reglas estrictas (estilo arquitectónico).
GraphQL es como un menú donde tú pides solo los ingredientes que quieres (lenguaje de consulta y ejecución).
Qué diferencia a REST y GraphQL
| Característica | REST | GRAPHQL |
|---|---|---|
| Datos | Devuelve todo el objeto | Tú defines los campos |
| Endpoints | Muchos endpoints | Sólo uno (/graphql) lo que cambia es el payload |
| Versionado | Por headeres o URL | Promueve evolución sin versionado |
| Frontend | Fetch a URLs específicas | Escribe consultas flexibles |
Tipos raíz en GraphQL: Query, Mutation y Subscription
En GraphQL existen tres tipos raíz que definen cómo los clientes interactúan con los datos. Son equivalentes a los conceptos de operaciones en REST, pero con una estructura más flexible y declarativa.
El cliente escribe sus peticiones en GraphQL (Graph Query Language), un lenguaje propio que se parece visualmente a JSON, pero no lo es.
- Query: Consultas de sólo lectura
Las queries son el equivalente a las peticiones GET en REST. Se usan para leer información sin modificar el estado del sistema.
- Mutation: Operaciones que modifican datos
Las mutations permiten crear, actualizar o eliminar recursos, igual que POST, PUT o DELETE en REST. Se definen explícitamente y pueden recibir argumentos.
- Subscription: Comunicación en tiempo real
Las subscriptions permiten recibir actualizaciones en tiempo real desde el servidor. Se basan en WebSockets en lugar de HTTP tradicional.
En tu backend, Query, Mutation y Subscription se implementan como clases separadas que definen los métodos disponibles para el frontend, sin necesidad de controladores tradicionales como en REST.
Cómo implementar GraphQL paso a paso
Vamos a llegar a esto:

Crea un proyecto de tipo Web API
dotnet new webapi -n Graphql
Ahora instalar la librería HotChocolate.AspNetCore.
HotChocolate es una librería para .NET que te permite crear APIs GraphQL de manera rápida y moderna. Es uno de los frameworks más populares en el ecosistema .NET para implementar servidores GraphQL.
cd graphql
dotnet add package hotchocolate.aspnetcore
Crear modelos
Crear carpeta Models, o podrías hacerlo también en un proyecto nuevo.
Tendremos estos 3 modelos:
public record Category(int Id, string Title);
public record Vendor(int Id, string Name);
public record Product(int Id, string Name, decimal Price, Category Category, Vendor Vendor);
Crear DTOs
En este caso tendrás que crear un DTO para las mutaciones:
public class ProductInput
{
public string Name { get; set; } = default!;
public decimal Price { get; set; }
public int CategoryId { get; set; }
public int VendorId { get; set; }
}
Crear Mutation y Query
En una carpeta llamada GraphQL, añadir estas dos clases:
public class Mutation
{
public Product AddProduct([Service] ProductService service, ProductInput input)
{
return service.Add(input.Name, input.Price, input.CategoryId, input.VendorId);
}
}
public class Query
{
public IEnumerable<Product> GetProducts([Service] ProductService service)
{
return service.GetAll();
}
}
Crear Capa de servicios
En la carpeta Services (o proyecto, como gustes) crea la clase ProductService:
public class ProductService
{
private readonly List<Product> _products = new();
private int _nextId = 1;
public IEnumerable<Product> GetAll() => _products;
public Product Add(string name, decimal price, int categoryId, int vendorId)
{
if (price <= 0)
throw new GraphQLException("El precio debe ser mayor a cero.");
if (_products.Any(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
throw new GraphQLException($"Ya existe un producto con el nombre '{name}'.");
var category = new Category(categoryId, "Instrumentos");
var vendor = new Vendor(vendorId, "Gerson Music Store");
var product = new Product(_nextId++, name, price, category, vendor);
_products.Add(product);
return product;
}
}
Estamos simulando la persistencia de la data guardandola como objetos en memoria por eso inyectaremos ProductService como Singleton, eventualmente podrías utilizar EF y guardar los datos en la base de datos.
Finalmente actualizar Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddSingleton<ProductService>()
.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>();
builder.Services.AddControllers();
var app = builder.Build();
app.MapGraphQL();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Pruebas
Ahora accede a la URL https://localhost:5001/graphql (al puerto que tengas configurado en launchSettings.json) y se abrirá Nitro:

Vamos a ejecutar un query: Crea un documento como este:
{
products {
id
name
price
category {
id
title
}
vendor {
id
name
}
}
}
Ejecuta y te dará los datos, que por el momento no hay ninguno:

Vamos a añadir datos mediante las mutaciones: crea otro documento como este
mutation {
addProduct(input: {
name: "Guitarra",
price: 485.99,
categoryId: 1,
vendorId: 1
}) {
id
name
}
}
Y obtienes:

Añades más, y entonces ahora si ejecutas el query o consulta nuevamente obtienes:

Visita el repo aquí y no te olvides de darle estrella y seguirme!
Si esta entrada te ha gustado, compártela crack! 🐿️🥳
Créditos de imagen de portada: Basado en Foto de Nick Windsor en Unsplash
