Web API Fundamentals

Back

Loading concept...

🍕 Web API Fundamentals: The Pizza Delivery Service Story

Imagine you’re running a pizza delivery service. Customers call in orders, you prepare the pizza, and deliver it exactly how they want it. That’s exactly what a Web API does—it takes requests, processes them, and delivers data back in the format the customer wants!


🌟 What is a Web API?

Think of a Web API as a pizza shop phone line:

  • Customers (apps, websites) call in to order
  • The shop (your API) listens, takes the order, makes the pizza
  • Delivers the pizza (data) back to the customer
// A simple pizza order API
[ApiController]
[Route("api/[controller]")]
public class PizzaController : ControllerBase
{
    [HttpGet]
    public IActionResult GetMenu()
    {
        return Ok(new[] { "Margherita", "Pepperoni" });
    }
}

Real Life Examples:

  • Weather app getting temperature → calls Weather API
  • Your phone showing Instagram → calls Instagram API
  • Uber showing your driver → calls Location API

🎮 API Controllers: The Order Takers

An API Controller is like the person answering the phone at the pizza shop. They:

  • Listen for incoming orders (HTTP requests)
  • Know all the menu items (endpoints)
  • Send back what you asked for (responses)

Regular Controller vs API Controller

Regular Controller API Controller
Returns web pages (HTML) Returns data (JSON/XML)
For websites For apps & services
Like a dine-in restaurant Like delivery-only kitchen
// API Controller - returns data
public class OrdersController : ControllerBase
{
    [HttpGet("{id}")]
    public Order GetOrder(int id)
    {
        return _orderService.Find(id);
    }
}

🏷️ The [ApiController] Attribute: Your Magic Badge

The [ApiController] attribute is like a special badge that gives your controller superpowers!

What This Magic Badge Does:

graph TD A["ApiController Badge"] --> B["Auto Model Validation"] A --> C["Auto 400 Bad Request"] A --> D["Binding Source Inference"] A --> E["Problem Details Responses"]

Without the badge:

// You must check everything manually
if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

With the badge:

[ApiController]  // Magic badge!
[Route("api/[controller]")]
public class PizzaController : ControllerBase
{
    // Validation happens automatically!
    [HttpPost]
    public IActionResult Create(Pizza pizza)
    {
        // If pizza data is bad, 400 returned auto
        return Ok(pizza);
    }
}

🔄 Content Negotiation: Speaking the Customer’s Language

Imagine a customer calls and says: “I want my order details in Spanish!”

Content Negotiation means your API can return data in whatever format the customer asks for—JSON, XML, or others!

How It Works:

graph TD A["Customer Request"] --> B{Accept Header?} B -->|application/json| C["Return JSON 📋"] B -->|application/xml| D["Return XML 📄"] B -->|No preference| E["Return Default JSON"]

The Customer Says What They Want:

GET /api/orders/1
Accept: application/json

Your API Delivers:

{
  "orderId": 1,
  "pizza": "Pepperoni",
  "status": "Delivered"
}

Or if they want XML:

<Order>
  <OrderId>1</OrderId>
  <Pizza>Pepperoni</Pizza>
</Order>

📦 Formatters: The Packaging Department

Formatters are like the packaging team at your pizza shop. They take the pizza (data) and put it in the right box (format)!

Types of Formatters:

Formatter What It Does Like…
JSON Converts to JSON Square box
XML Converts to XML Round container
Custom Your own format Special packaging
// Adding formatters in Program.cs
builder.Services.AddControllers()
    .AddJsonOptions(opt =>
    {
        opt.JsonSerializerOptions
           .PropertyNamingPolicy = null;
    })
    .AddXmlSerializerFormatters();

Input Formatters: Read data coming IN (like reading the order) Output Formatters: Package data going OUT (like boxing the pizza)


📬 Data Transfer Objects (DTOs): The Order Slip

A DTO is like the order slip the cashier writes. It only contains what’s needed—not the entire recipe book!

Why Use DTOs?

Imagine sending your entire pizza recipe to a customer who just wants to know their order status. That’s silly! DTOs help you send only what’s needed.

graph LR A["Full Pizza Entity"] --> B["DTO Filter"] B --> C["Clean Order Info"] style A fill:#ff6b6b style C fill:#51cf66

Your Database Model (Too Much Info!):

public class Pizza
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string SecretRecipe { get; set; }  // Private!
    public decimal Cost { get; set; }         // Internal!
    public decimal Price { get; set; }
}

Your DTO (Just Right!):

public class PizzaDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    // No secrets exposed!
}

🗺️ AutoMapper: The Automatic Translator

Copying data from one object to another is boring! AutoMapper does it automatically—like a translator who instantly converts your pizza order from the kitchen’s format to the customer’s format.

Before AutoMapper (Boring Manual Work):

var dto = new PizzaDto
{
    Id = pizza.Id,
    Name = pizza.Name,
    Price = pizza.Price
};
// Imagine doing this 100 times! 😫

After AutoMapper (Magic!):

// One-time setup
public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Pizza, PizzaDto>();
    }
}

// Usage - just one line!
var dto = _mapper.Map<PizzaDto>(pizza);

Setting Up AutoMapper:

// In Program.cs
builder.Services.AddAutoMapper(
    typeof(MappingProfile));

// In your controller
public class PizzaController : ControllerBase
{
    private readonly IMapper _mapper;

    public PizzaController(IMapper mapper)
    {
        _mapper = mapper;
    }
}

✅ FluentValidation: The Quality Inspector

Before a pizza goes out, someone checks it’s made correctly. FluentValidation is your quality inspector for incoming data!

Why FluentValidation?

Regular validation is clunky:

// Old way - messy!
[Required]
[StringLength(50)]
[RegularExpression(@"^[a-zA-Z]+quot;)]
public string Name { get; set; }

FluentValidation is clean and readable:

public class PizzaValidator
    : AbstractValidator<CreatePizzaDto>
{
    public PizzaValidator()
    {
        RuleFor(p => p.Name)
            .NotEmpty()
            .WithMessage("Pizza needs a name!")
            .MaximumLength(50)
            .WithMessage("Name too long!");

        RuleFor(p => p.Price)
            .GreaterThan(0)
            .WithMessage("Price must be positive!");
    }
}

Setting It Up:

// Install: FluentValidation.AspNetCore

// In Program.cs
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblyContaining
    <PizzaValidator>();

Validation in Action:

graph TD A["Customer Order"] --> B{FluentValidation} B -->|Valid ✅| C["Process Order"] B -->|Invalid ❌| D["Return Errors"] D --> E["Name is required!"]

🎯 Putting It All Together

Here’s how all the pieces work together in a real API:

[ApiController]
[Route("api/[controller]")]
public class PizzaController : ControllerBase
{
    private readonly IMapper _mapper;
    private readonly IPizzaService _service;

    [HttpPost]
    public async Task<ActionResult<PizzaDto>> Create(
        CreatePizzaDto dto)  // DTO for input
    {
        // FluentValidation runs automatically!

        // AutoMapper converts DTO to entity
        var pizza = _mapper.Map<Pizza>(dto);

        await _service.AddAsync(pizza);

        // AutoMapper converts back to DTO
        var result = _mapper.Map<PizzaDto>(pizza);

        // Content negotiation handles format
        return CreatedAtAction(
            nameof(Get),
            new { id = pizza.Id },
            result);
    }
}

🏆 Quick Recap

Concept What It Does Pizza Shop Analogy
Web API Handles requests & responses The phone line
API Controller Routes to actions Order taker
[ApiController] Adds magic features Special badge
Content Negotiation Returns preferred format Speaking customer’s language
Formatters Convert data formats Packaging team
DTOs Clean data transfer Order slips
AutoMapper Auto-copies objects Automatic translator
FluentValidation Validates input Quality inspector

🚀 You Did It!

You now understand how ASP.NET Web APIs work! Like a well-run pizza shop, your API can:

  • ✅ Take orders (receive requests)
  • ✅ Validate them (FluentValidation)
  • ✅ Process them (Controllers)
  • ✅ Package them right (Formatters & DTOs)
  • ✅ Deliver in any format (Content Negotiation)

Go build something amazing! 🍕✨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.