Skip to content

renanzitoo/external-api-consumer

Repository files navigation

🌐 API Consumer - ZIP Code Lookup

.NET C# MySQL License

Educational project demonstrating best practices for consuming external APIs without compromising your application's stability.


📋 About the Project

This project implements a ZIP code lookup service that consumes the public ViaCEP API, demonstrating resilience techniques, caching, auditing, and error handling when integrating with external APIs.

🎯 Objective

Show how to build a resilient API that:

  • Doesn't break when the external API is offline
  • Doesn't freeze when the external API is slow
  • Reduces costs with intelligent caching
  • Audits all external calls
  • Returns standardized and informative errors

🚀 Features

  • 🔍 ZIP Code Lookup via ViaCEP API
  • 💾 Local cache in MySQL to reduce external calls
  • ⏱️ Configurable timeout (10s) to prevent freezing
  • 📊 Complete auditing of all external calls (success and failure)
  • ✔️ Robust input validation (8-digit ZIP code)
  • 📦 Standardized responses with ApiResponse<T> and ApiErrorResponse
  • 🔄 AutoMapper for entity conversion
  • 📖 Swagger/OpenAPI for interactive documentation

🛠️ Technologies Used

  • .NET 8.0 - Modern web framework
  • ASP.NET Core Web API - RESTful API construction
  • Entity Framework Core 8.0 - ORM for data access
  • MySQL 8.0 - Relational database
  • AutoMapper 12.0 - Object-to-object mapping
  • Polly 10.0 - Resilience policies (retry, timeout)
  • Swagger/OpenAPI - API documentation

📁 Project Structure

ApiConsumer/
├── Controllers/
│   └── CepController.cs          # HTTP Endpoints
├── Services/
│   └── CepService.cs              # Business logic and API consumption
├── Context/
│   ├── AppDbContext.cs            # EF Core configuration
│   └── AppDbContextFactory.cs     # Factory for migrations
├── Entities/
│   ├── Cep.cs                     # ZIP Code model
│   └── ExternalApiCall.cs         # Call auditing
├── DTOs/
│   ├── Responses/
│   │   ├── CepResponseDTO.cs      # Response DTO
│   │   ├── ApiResponse.cs         # Response wrapper
│   │   └── ApiErrorResponse.cs    # Error model
│   └── External/
│       └── ViaCepResponseDTO.cs   # ViaCEP API DTO
├── Mappings/
│   └── CepProfile.cs              # AutoMapper profiles
└── Migrations/                    # EF Core migrations

💻 Requirements

Before starting, make sure you have:

  • .NET SDK 8 or higher
  • MySQL 8.0 or Docker
  • Git
  • IDE: JetBrains Rider, Visual Studio 2022, or VS Code

🚀 Running the Project

1️⃣ Clone the repository

git clone https://github.com/renanzitoo/ApiConsumer.git
cd ApiConsumer

2️⃣ Configure the database

Option A: Local MySQL

Edit appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Port=3306;Database=apiconsumer;User=root;Password=your-password;"
  }
}

Option B: MySQL via Docker

docker run --name mysql-apiconsumer -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=apiconsumer -p 3306:3306 -d mysql:8.0

3️⃣ Run the migrations

dotnet ef database update

4️⃣ Restore and run

dotnet restore
dotnet run

API available at: https://localhost:5001 or http://localhost:5000


📌 API Endpoints

🔍 Lookup ZIP Code

GET /api/cep/{cep}

Looks up a ZIP code and returns address data.


✅ Example: 200 OK - ZIP Code found

Request:

GET /api/cep/01001000

Response:

{
  "success": true,
  "data": {
    "cepCode": "01001000",
    "street": "Praça da Sé",
    "neighborhood": "",
    "city": "São Paulo",
    "state": "SP",
    "uf": "SP"
  },
  "error": null
}

❌ Example: 400 Bad Request - Invalid ZIP Code

Request:

GET /api/cep/123

Response:

{
  "success": false,
  "data": null,
  "error": {
    "code": "INVALID_CEP",
    "message": "Invalid ZIP code. Please provide 8 digits."
  }
}

❌ Example: 404 Not Found

Request:

GET /api/cep/99999999

Response:

{
  "success": false,
  "data": null,
  "error": {
    "code": "CEP_NOT_FOUND",
    "message": "ZIP code not found."
  }
}

❌ Example: 503 Service Unavailable

Response:

{
  "success": false,
  "data": null,
  "error": {
    "code": "CEP_SERVICE_UNAVAILABLE",
    "message": "ZIP code service unavailable at the moment."
  }
}

🧪 Testing the API

Via Swagger UI

https://localhost:5001/swagger

Via cURL

curl -X GET "https://localhost:5001/api/cep/01001000" -H "accept: application/json"

Via PowerShell

Invoke-RestMethod -Uri "https://localhost:5001/api/cep/01001000" -Method Get

Via JavaScript

fetch('https://localhost:5001/api/cep/01001000')
  .then(response => response.json())
  .then(data => console.log(data));

🏗️ Architecture

Implemented Patterns

  1. Repository Pattern - Data access via AppDbContext
  2. DTO Pattern - Separation of entities and models
  3. Dependency Injection - Native ASP.NET Core DI
  4. Exception Handling - Error-specific exceptions
  5. Cache-Aside Pattern - Cache checked before API
  6. Audit Log Pattern - External call logging

Resilience Techniques

  • ⏱️ 10-second timeout - Prevents freezing
  • 💾 Local cache - Reduces external API dependency
  • 📝 Isolated auditing - Log failures don't break the flow
  • ✔️ Data validation - Prevents invalid data in the database
  • 🔄 Retry Policy (Polly) - Automatically retries on failures

🗄️ Database

Ceps Table

Column Type
Id GUID
CepCode VARCHAR(8)
Street VARCHAR(200)
Neighborhood VARCHAR(100)
City VARCHAR(100)
State VARCHAR(2)
UF VARCHAR(2)

ExternalApiCalls Table

Column Type
Id GUID
Provider VARCHAR(50)
Endpoint VARCHAR(500)
RequestKey VARCHAR(100)
Success BOOLEAN
ResponseStatusCode INT
ResponseContent TEXT
ResponseTimeInMilliseconds INT
RequestedAt DATETIME

🧠 Concepts Practiced

  • ✅ External API consumption with HttpClient
  • ✅ Resilience and error handling
  • ✅ Local caching for optimization
  • ✅ Async/Await patterns
  • ✅ Entity Framework Core with MySQL
  • ✅ AutoMapper for DTOs
  • ✅ Data validation
  • ✅ Call auditing
  • ✅ RESTful patterns
  • ✅ Dependency injection

📝 Future Improvements

  • Add ILogger for structured observability
  • Implement Circuit Breaker with Polly
  • Create unit tests (xUnit)
  • Integration tests
  • Health checks
  • Metrics (Prometheus)
  • Containerize the application
  • CI/CD with GitHub Actions
  • Rate limiting

👨‍💻 Author

Renan Costa
GitHub: renanzitoo


⭐ If this project was useful to you, consider giving it a star!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages