Implementing a REST API Endpoint for Dish Creation

Share

Summary

This article details the process of structuring a REST API endpoint for creating new dishes within a given restaurant, covering controller setup, command and handler implementation, validation, and repository integration.

Implementing a REST API Endpoint for Dish Creation

Highlights

Setting up the DishesController

The process begins by creating a new 'DishesController' to conform to REST architecture. This controller will have a route attribute '/api/restaurant/{restaurantId}/dishes' and will inherit from the controller base class, similar to the existing 'RestaurantsController'. It will also have the 'ApiController' attribute applied.

Defining the Create Dish Endpoint

A public async task of 'IActionResult' named 'CreateDish' is implemented. This method will accept two primary pieces of information: the 'restaurantId' from the route parameters and a 'CreateDishCommand' from the request body, which will represent the new dish entity. The 'HttpPost' attribute is applied to this endpoint.

Implementing the CreateDishCommand

The 'CreateDishCommand' is defined as a class within the application module, mimicking the structure of other commands. It inherits from the 'IRequest' interface from MediatR and includes properties like 'Name', 'Description', 'Price', and 'Kilocalories' to capture dish details. The 'restaurantId' is later added to this command for associating the dish with the correct restaurant.

Validation for CreateDishCommand

A validator, 'CreateDishCommandValidator', is created for the 'CreateDishCommand' using FluentValidation. This validator ensures that properties like 'Price' and 'Kilocalories' are non-negative numbers, with custom error messages defined for invalid inputs.

Creating the CreateDishCommandHandler

The 'CreateDishCommandHandler' implements 'IRequestHandler<CreateDishCommand>'. It first logs the creation request. It then checks for the existence of the specified restaurant in the database using 'IRestaurantRepository'. If the restaurant is not found, a 'NotFoundException' is thrown. If found, the command is mapped to a 'Dish' entity, and the new dish is added to the database.

Introducing IDishesRepository

To maintain good practice and separate repository concerns, a new interface, 'IDishesRepository', is introduced. This interface defines a 'Create' method for adding 'Dish' entities. A concrete implementation, 'DishesRepository', is created in the infrastructure layer, using 'RestaurantsDbContext' to persist the dish data.

Mapping and Dependency Injection

The 'IMapper' interface is injected into the 'CreateDishCommandHandler' to map the 'CreateDishCommand' to a 'Dish' entity. A mapping profile is added to AutoMapper to facilitate this conversion. Crucially, the 'IDishesRepository' is registered with the dependency injection container in the 'ServiceCollectionExtensions' to ensure its proper resolution.

Testing and Refinements

Before running the application, it's identified that the 'restaurantId' from the route needs to be manually assigned to the 'CreateDishCommand' as it's not automatically bound. Testing with an API client demonstrates the validation effectively, returning errors for missing or invalid data. The process also includes testing with existing and non-existent restaurant IDs to confirm proper error handling.

Recently Summarized Articles

Loading...