Section 2 of 6

Your First Web Application

🎯 What You'll Learn

  • Creating an ASP.NET Core Web API project
  • Understanding the generated project structure
  • Running your first web application
  • Testing API endpoints with Swagger
  • Creating your first controller
  • Understanding routing and HTTP methods
  • Building a simple InvenTrack product API
  • Testing with browser and curl

Creating Your First Web API

Let's create a simple Web API for InvenTrack. We'll start with a minimal API that manages products.

Step 1: Create the Project

Terminal Shell
# Navigate to your projects folder
cd C:\Users\YourName\Projects

# Create a new Web API project
dotnet new webapi -n InvenTrack.Api

# Navigate into the project
cd InvenTrack.Api
ℹ️ What Just Happened?

The webapi template created a complete ASP.NET Core Web API project with:
β€’ Project file (.csproj)
β€’ Program.cs (application entry point)
β€’ appsettings.json (configuration)
β€’ A sample WeatherForecast controller
β€’ Swagger/OpenAPI support

Step 2: Explore the Project Structure

Project Structure Text
InvenTrack.Api/
β”œβ”€β”€ Controllers/
β”‚   └── WeatherForecastController.cs  # Sample controller
β”œβ”€β”€ Properties/
β”‚   └── launchSettings.json            # Launch configuration
β”œβ”€β”€ appsettings.json                   # App configuration
β”œβ”€β”€ appsettings.Development.json       # Dev-specific config
β”œβ”€β”€ InvenTrack.Api.csproj              # Project file
β”œβ”€β”€ Program.cs                         # Application entry point
└── WeatherForecast.cs                 # Sample model

Step 3: Run the Application

Terminal Shell
dotnet run

You'll see output like:

Output Text
Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
πŸŽ‰ Success!

Your web API is now running! It's listening on:
β€’ HTTP: http://localhost:5000
β€’ HTTPS: https://localhost:5001
Open your browser and navigate to https://localhost:5001/swagger

Exploring Swagger UI

Swagger (OpenAPI) provides an interactive API documentation interface. When you navigate to https://localhost:5001/swagger, you'll see:

  • All available API endpoints
  • HTTP methods (GET, POST, PUT, DELETE)
  • Request/response models
  • Interactive "Try it out" buttons

Testing the Sample Endpoint

  1. Click on GET /WeatherForecast
  2. Click "Try it out"
  3. Click "Execute"
  4. See the JSON response
Sample Response JSON
[
  {
    "date": "2024-12-10",
    "temperatureC": 25,
    "temperatureF": 76,
    "summary": "Warm"
  },
  {
    "date": "2024-12-11",
    "temperatureC": 18,
    "temperatureF": 64,
    "summary": "Cool"
  }
]

Understanding the Sample Code

WeatherForecast.cs - The Model

WeatherForecast.cs C#
namespace InvenTrack.Api;

public class WeatherForecast
{
    public DateOnly Date { get; set; }

    public int TemperatureC { get; set; }

    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

    public string? Summary { get; set; }
}

This is a simple data model (DTO - Data Transfer Object) representing weather data.

WeatherForecastController.cs - The Controller

Controllers/WeatherForecastController.cs C#
using Microsoft.AspNetCore.Mvc;

namespace InvenTrack.Api.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", 
        "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

Key Attributes Explained

Attribute Purpose
[ApiController] Enables API-specific behaviors (auto model validation, etc.)
[Route("[controller]")] Sets base route to controller name (e.g., /WeatherForecast)
[HttpGet] Maps method to HTTP GET requests

Creating Your First InvenTrack Endpoint

Let's create a simple Products API for InvenTrack. We'll build it step by step.

Step 1: Create the Product Model

Create a new file Product.cs in the project root:

Product.cs C#
namespace InvenTrack.Api;

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Sku { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int QuantityInStock { get; set; }
    public string? Category { get; set; }
}

Step 2: Create the Products Controller

Create a new file ProductsController.cs in the Controllers folder:

Controllers/ProductsController.cs C#
using Microsoft.AspNetCore.Mvc;

namespace InvenTrack.Api.Controllers;

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    // In-memory product list (temporary - we'll use a database later)
    private static readonly List<Product> Products = new()
    {
        new Product 
        { 
            Id = 1, 
            Name = "Laptop - Dell XPS 15", 
            Sku = "LAP-DELL-XPS15",
            Price = 1299.99m,
            QuantityInStock = 15,
            Category = "Electronics"
        },
        new Product 
        { 
            Id = 2, 
            Name = "Wireless Mouse", 
            Sku = "ACC-MOUSE-001",
            Price = 29.99m,
            QuantityInStock = 150,
            Category = "Accessories"
        },
        new Product 
        { 
            Id = 3, 
            Name = "USB-C Cable", 
            Sku = "CAB-USBC-2M",
            Price = 12.99m,
            QuantityInStock = 300,
            Category = "Cables"
        }
    };

    // GET: api/products
    [HttpGet]
    public ActionResult<IEnumerable<Product>> GetProducts()
    {
        return Ok(Products);
    }

    // GET: api/products/1
    [HttpGet("{id}")]
    public ActionResult<Product> GetProduct(int id)
    {
        var product = Products.FirstOrDefault(p => p.Id == id);
        
        if (product == null)
        {
            return NotFound(new { message = $"Product with ID {id} not found" });
        }

        return Ok(product);
    }

    // POST: api/products
    [HttpPost]
    public ActionResult<Product> CreateProduct(Product product)
    {
        // Generate new ID
        product.Id = Products.Max(p => p.Id) + 1;
        
        Products.Add(product);

        return CreatedAtAction(
            nameof(GetProduct), 
            new { id = product.Id }, 
            product
        );
    }

    // PUT: api/products/1
    [HttpPut("{id}")]
    public IActionResult UpdateProduct(int id, Product product)
    {
        var existingProduct = Products.FirstOrDefault(p => p.Id == id);
        
        if (existingProduct == null)
        {
            return NotFound();
        }

        existingProduct.Name = product.Name;
        existingProduct.Sku = product.Sku;
        existingProduct.Price = product.Price;
        existingProduct.QuantityInStock = product.QuantityInStock;
        existingProduct.Category = product.Category;

        return NoContent();
    }

    // DELETE: api/products/1
    [HttpDelete("{id}")]
    public IActionResult DeleteProduct(int id)
    {
        var product = Products.FirstOrDefault(p => p.Id == id);
        
        if (product == null)
        {
            return NotFound();
        }

        Products.Remove(product);

        return NoContent();
    }
}
πŸ’‘ What We Just Built

This is a complete CRUD API (Create, Read, Update, Delete) for products:
β€’ GET /api/products - List all products
β€’ GET /api/products/{id} - Get single product
β€’ POST /api/products - Create new product
β€’ PUT /api/products/{id} - Update product
β€’ DELETE /api/products/{id} - Delete product

Testing Your API

Method 1: Using Swagger

  1. Run the app: dotnet run
  2. Navigate to https://localhost:5001/swagger
  3. You'll see your Products endpoints listed
  4. Try each endpoint:
    • GET /api/products - See all products
    • GET /api/products/1 - Get product with ID 1
    • POST /api/products - Create a new product

Method 2: Using curl

Terminal Shell
# Get all products
curl https://localhost:5001/api/products

# Get single product
curl https://localhost:5001/api/products/1

# Create new product
curl -X POST https://localhost:5001/api/products \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mechanical Keyboard",
    "sku": "KEY-MECH-001",
    "price": 89.99,
    "quantityInStock": 50,
    "category": "Accessories"
  }'

Method 3: Using Browser

For GET requests, simply navigate to:

  • https://localhost:5001/api/products
  • https://localhost:5001/api/products/1

Understanding HTTP Status Codes

Your API returns different status codes based on the result:

Status Code Method Meaning
200 OK Ok() Request succeeded, returning data
201 Created CreatedAtAction() Resource created successfully
204 No Content NoContent() Request succeeded, no data to return
404 Not Found NotFound() Resource doesn't exist
400 Bad Request BadRequest() Invalid request data

Understanding Routing

Route Templates

Routing Examples C#
// Controller-level route
[Route("api/[controller]")]
// Becomes: /api/products

// Action-level route with parameter
[HttpGet("{id}")]
// Becomes: /api/products/{id}

// Custom route
[HttpGet("search/{term}")]
// Becomes: /api/products/search/{term}

Route Constraints

Route Constraints C#
// ID must be an integer
[HttpGet("{id:int}")]

// ID must be a GUID
[HttpGet("{id:guid}")]

// Multiple constraints
[HttpGet("{id:int:min(1)}")]

Key Takeaways

  • Create Web APIs with dotnet new webapi
  • Controllers handle HTTP requests and return responses
  • [ApiController] enables API-specific behaviors
  • [Route] defines URL patterns
  • HTTP method attributes: [HttpGet], [HttpPost], [HttpPut], [HttpDelete]
  • ActionResult<T> allows returning both data and status codes
  • Ok(), NotFound(), CreatedAtAction() return appropriate status codes
  • Swagger provides interactive API documentation
  • Route parameters like {id} are automatically bound to method parameters
  • ASP.NET Core automatically serializes objects to JSON
🎯 Next Steps

You've built your first working Web API! In the next section, we'll do a deep dive into Program.csβ€”understanding how ASP.NET Core applications start up, the middleware pipeline, dependency injection configuration, and how everything comes together.