### OrderModel Initialization Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrderModel.md Example demonstrating how to create and initialize an OrderModel instance. This includes setting properties like OrderId, Customer, and Products. ```csharp var orderModel = new OrderModel(); orderModel.OrderId = 1; orderModel.Customer = "Customer 1"; orderModel.Products = new List(); ``` -------------------------------- ### Example GET Request for Order Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrdersController.md Demonstrates how to make a GET request to retrieve order details and shows a sample response structure. ```http // GET /api/orders?orderId=1 var response = await client.GetAsync("/api/orders?orderId=1"); // Response body: // { // "result": { // "orderId": 1, // "customer": "Customer 1", // "products": [ // { "productId": 2, "name": "Product 2" }, // { "productId": 5, "name": "Product 5" } // ] // } // } ``` -------------------------------- ### GET /api/products Request Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductsController.md Example of a GET request to retrieve a product by its ID using the query string. ```http GET /api/products?productId=1 ``` -------------------------------- ### GetProduct API Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductsController.md Demonstrates how to call the GetProduct endpoint using an HTTP client and shows an example of the expected JSON response body for a successful request. ```http // GET /api/products?productId=1 var response = await client.GetAsync("/api/products?productId=1"); // Response body: // { // "result": { // "productId": 1, // "name": "Product 1" // } // } ``` -------------------------------- ### Get All Products Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Retrieves all products from the database. Assumes a context object is available. ```csharp var allProducts = context.Products.ToList(); ``` -------------------------------- ### Registering GetOrderRequestProcessor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrdersController.md Example of how to register the GetOrderRequestProcessor for dependency injection in Startup.cs or Program.cs. ```csharp // In Startup.cs or Program.cs services.AddTransient(); ``` -------------------------------- ### GET /api/orders Success Response Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Example of a successful response when an order is found. ```json { "result": { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 2, "name": "Product 2" }, { "productId": 5, "name": "Product 5" }, { "productId": 8, "name": "Product 8" } ] } } ``` -------------------------------- ### API Response Example for GetProductResponse Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md An example of a successful (200 OK) API response for GetProduct, showing the ProductModel nested within the result property. ```json { "result": { "productId": 1, "name": "Product 1" } } ``` -------------------------------- ### GET /api/orders Response Body Example (Success) Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrdersController.md Example JSON response body for a successful retrieval of order details. Includes order ID, customer name, and a list of products with their IDs and names. ```json { "result": { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 3, "name": "Product 3" }, { "productId": 7, "name": "Product 7" } ] } } ``` -------------------------------- ### ProductModel JSON Serialization Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Illustrates the default JSON output for a ProductModel instance, showing camelCase property names and inclusion of all properties. ```json { "productId": 1, "name": "Laptop" } ``` -------------------------------- ### GetProductResponse with Product Data Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductResponse.md Example of creating a GetProductResponse and setting its Result property with a ProductModel. ```csharp var response = new GetProductResponse { Result = new ProductModel { ProductId = 1, Name = "Product 1" } }; ``` -------------------------------- ### GET /api/orders Request Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrdersController.md Example of a GET request to retrieve a single order by its ID. The order ID is passed as a query parameter. ```http GET /api/orders?orderId=1 ``` -------------------------------- ### Registering GetProductRequestProcessor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductsController.md Example of how to register the GetProductRequestProcessor with the dependency injection container in Program.cs. ```csharp // In Program.cs services.AddTransient(); ``` -------------------------------- ### Handle Product Retrieval Request Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequestProcessor.md Shows how to asynchronously handle a product retrieval request using the GetProductRequestProcessor. This example includes seeding data, creating the processor, making the request, and handling the response. ```csharp using var context = new DemoDbContext(); DemoDbContext.SeedData(); var processor = new GetProductRequestProcessor(context); var request = new GetProductRequest { ProductId = 1 }; var response = await processor.HandleAsync(request, CancellationToken.None); if (response.Result != null) { Console.WriteLine($"Product ID: {response.Result.ProductId}"); Console.WriteLine($"Name: {response.Result.Name}"); } else { Console.WriteLine("Product not found"); } ``` -------------------------------- ### Default Constructor for GetProductResponse Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductResponse.md Example of creating a GetProductResponse using its default parameterless constructor and then assigning a ProductModel to its Result property. ```csharp var response = new GetProductResponse(); response.Result = productModel; ``` -------------------------------- ### Run Application via CLI Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/configuration.md Starts the application using the dotnet CLI. This command is environment-agnostic and relies on the environment variable being set beforehand. ```bash dotnet run ``` -------------------------------- ### Retrieve Product via HTTP Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Use this command to retrieve product details via an HTTP GET request. Ensure the API is running on the specified local host and port. ```bash curl https://localhost:7001/api/products?productId=1 ``` -------------------------------- ### Example JSON Structure Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/types.md Shows a typical JSON structure for an order response, demonstrating the camelCase naming convention for properties. ```json { "result": { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 1, "name": "Product 1" } ] } } ``` -------------------------------- ### Get Product API Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Retrieves product details using the product ID. ```APIDOC ## GET /api/products ### Description Retrieves product details based on the provided product ID. ### Method GET ### Endpoint /api/products ### Parameters #### Query Parameters - **productId** (string) - Required - The ID of the product to retrieve. ``` -------------------------------- ### HTTP Request to GetProductRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Shows how an HTTP GET request with a productId query parameter is translated into a GetProductRequest object. ```text HTTP Request: GET /api/products?productId=1 ↓ GetProductRequest { ProductId = 1 } ``` -------------------------------- ### Seed Data Generation for Orders Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Order.md Example of how to generate and seed initial order data using C# and EF Core. This snippet creates 10 orders with random products. ```csharp var orders = Enumerable.Range(1, 10).Select(i => new Order() { OrderId = i, Customer = $"Customer {i}", Products = context.Products.OrderBy(_ => rnd.Next()).Take(5).ToList() }); context.Orders.AddRangeAsync(orders); ``` -------------------------------- ### HTTP Response for Order Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Example JSON response structure when retrieving order details via HTTP. ```json { "result": { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 2, "name": "Product 2" }, { "productId": 5, "name": "Product 5" } ] } } ``` -------------------------------- ### Extensible GetOrderRequest Class Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequest.md An example of how the GetOrderRequest class could be extended in the future with additional optional properties like IncludeProducts and AsOfDate. ```csharp // Example future extension public class GetOrderRequest { public int OrderId { get; set; } public bool? IncludeProducts { get; set; } public DateTime? AsOfDate { get; set; } } ``` -------------------------------- ### GetProduct Method Signature Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductsController.md Defines the HTTP GET endpoint for retrieving a product by its ID. It returns an ActionResult containing GetProductResponse. ```csharp public async Task> GetProduct(int productId, CancellationToken cancellationToken) ``` -------------------------------- ### Testing Endpoints with cURL Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Use cURL to send GET requests to retrieve order or product data. Specify the order ID or product ID in the query parameters. ```bash # Get order 1 curl -X GET "https://localhost:7001/api/orders?orderId=1" # Get product 1 curl -X GET "https://localhost:7001/api/products?productId=1" ``` -------------------------------- ### Retrieve Order via HTTP Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Use this command to retrieve order details via an HTTP GET request. Ensure the API is running on the specified local host and port. ```bash curl https://localhost:7001/api/orders?orderId=1 ``` -------------------------------- ### Seed Data Creation for Products Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Demonstrates how to create and add 10 sample products to the database context using C# and LINQ. This is typically done during application startup. ```csharp var products = Enumerable.Range(1, 10).Select(i => new Product() { Name = $"Product {i}", ProductId = i }); context.Products.AddRangeAsync(products); ``` -------------------------------- ### GET /api/orders Error Response Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Example of an error response for an invalid request, such as an invalid orderId. ```json { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "..." } ``` -------------------------------- ### Create ProductModel Instance with Name Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Demonstrates how to create a ProductModel instance and set its Name property. ```csharp var productModel = new ProductModel { Name = "Laptop" }; ``` -------------------------------- ### Initialize ProductModel using Default Constructor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Shows how to instantiate ProductModel using its default constructor and then set its properties. ```csharp var productModel = new ProductModel(); productModel.ProductId = 1; productModel.Name = "Laptop"; ``` -------------------------------- ### Initialize GetProductRequestProcessor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequestProcessor.md Demonstrates how to initialize a new instance of the GetProductRequestProcessor. Requires a DemoDbContext instance. ```csharp var dbContext = new DemoDbContext(); var processor = new GetProductRequestProcessor(dbContext); ``` -------------------------------- ### Instantiate DemoDbContext Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/DemoDbContext.md Demonstrates how to create a new instance of the DemoDbContext. ```csharp public DemoDbContext() ``` -------------------------------- ### Create ProductModel Instance with ProductId Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Demonstrates how to create a ProductModel instance and set its ProductId property. ```csharp var productModel = new ProductModel { ProductId = 1 }; ``` -------------------------------- ### Constructing GetProductResponse Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductResponse.md Demonstrates programmatic creation of GetProductResponse instances for both successful product retrieval and 'not found' scenarios. ```csharp // Success case var response = new GetProductResponse { Result = new ProductModel { ProductId = 1, Name = "Product 1" } }; // Not found case var notFoundResponse = new GetProductResponse { Result = null }; ``` -------------------------------- ### OnConfiguring Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/DemoDbContext.md Configures the database options for the context, specifically setting up an in-memory database named "DemoDb". This method is automatically called during context initialization. ```APIDOC ## OnConfiguring(DbContextOptionsBuilder optionsBuilder) ### Description Configures the database options for the context. Sets up an in-memory database named "DemoDb". ### Method Signature ```csharp protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) ``` ### Parameters #### Parameters - **optionsBuilder** (DbContextOptionsBuilder) - Required - Builder for configuring database options ### Returns void ### Database Configuration Uses `UseInMemoryDatabase` with database name "DemoDb" ### Example ```csharp var options = new DbContextOptionsBuilder(); // OnConfiguring is called automatically during context initialization ``` ``` -------------------------------- ### Get Order API Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Retrieves order details using the order ID. ```APIDOC ## GET /api/orders ### Description Retrieves order details based on the provided order ID. ### Method GET ### Endpoint /api/orders ### Parameters #### Query Parameters - **orderId** (string) - Required - The ID of the order to retrieve. ``` -------------------------------- ### Create Order Instance with Customer Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Order.md Instantiate an Order object and set the customer name. ```csharp var order = new Order { Customer = "John Smith" }; ``` -------------------------------- ### Project Structure Overview Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Directory and file structure for the Ports and Adapters Pattern Demo project, illustrating the separation of concerns. ```text PortsAndAdaptersPatternDemo/ ├── PortsAndAdaptersPatternDemo.Api/ │ ├── Program.cs (dependency configuration) │ ├── Controllers/ │ │ ├── OrdersController.cs (HTTP endpoint) │ │ └── ProductsController.cs (HTTP endpoint) │ └── appsettings.json │ ├── PortsAndAdaptersPatternDemo.Data/ │ ├── DemoDbContext.cs (database context) │ ├── Order.cs (entity) │ └── Product.cs (entity) │ ├── PortsAndAdaptersPatternDemo.Models/ │ ├── OrderModel.cs (DTO) │ └── ProductModel.cs (DTO) │ ├── PortsAndAdaptersPatternDemo.RequestProcessing/ │ └── Features/ │ ├── GetOrder/ │ │ ├── GetOrderRequest.cs (request DTO) │ │ ├── GetOrderResponse.cs (response DTO) │ │ └── GetOrderRequestProcessor.cs (business logic) │ └── GetProduct/ │ ├── GetProductRequest.cs (request DTO) │ ├── GetProductResponse.cs (response DTO) │ └── GetProductRequestProcessor.cs (business logic) │ └── PortsAndAdaptersPatternDemo.ConsoleApp/ ├── Program.cs (CLI setup) ├── GetOrderCommand.cs (console command) ├── GetProductCommand.cs (console command) └── TypeRegistrar.cs (DI adapter) ``` -------------------------------- ### GetOrder Method Signature Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrdersController.md Defines the HTTP GET endpoint for retrieving order details by ID. ```csharp public async Task> GetOrder(int orderId, CancellationToken cancellationToken) ``` -------------------------------- ### Create Product with Name Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Instantiate a Product object and set its Name. This is useful for creating new product records or updating product information. ```csharp var product = new Product { Name = "Laptop" }; ``` -------------------------------- ### GET /api/products Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Retrieves a product by its ID. This endpoint is part of the ASP.NET Core HTTP controller for product-related operations. ```APIDOC ## GET /api/products ### Description Retrieve product by ID. ### Method GET ### Endpoint /api/products ### Parameters #### Query Parameters - **productId** (int) - Required - The ID of the product to retrieve. ### Response #### Success Response (200) - **Result** (GetProductResponse) - The product details, or null if not found. #### Response Example { "result": { "productId": 1, "name": "string" } } ERROR HANDLING: - Status codes: 200 OK for success and not-found, 400 Bad Request for invalid input. ``` -------------------------------- ### Initialize DemoDbContext Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/DemoDbContext.md Shows the basic usage for initializing a DemoDbContext instance. ```csharp using var context = new DemoDbContext(); ``` -------------------------------- ### Create OrderModel with Products Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrderModel.md Instantiate an OrderModel and populate its Products collection. This demonstrates how to add multiple ProductModel instances to an order. ```csharp var orderModel = new OrderModel { Products = new List { new ProductModel { ProductId = 1, Name = "Product 1" }, new ProductModel { ProductId = 2, Name = "Product 2" } } }; ``` -------------------------------- ### Create Product with Orders Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Instantiate a Product object and populate its Orders collection. This demonstrates how to associate multiple orders with a product, reflecting a many-to-many relationship. ```csharp var product = new Product { ProductId = 1, Name = "Product 1", Orders = new List { new Order { OrderId = 1, Customer = "Customer 1" }, new Order { OrderId = 2, Customer = "Customer 2" } } }; ``` -------------------------------- ### OrdersController C# Implementation Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Controller implementation for handling GET /api/orders requests. It processes the request and returns the order details. ```csharp [Route("api/[controller]")] [ApiController] public class OrdersController : ControllerBase { private readonly GetOrderRequestProcessor _getOrderRequestProcessor; public OrdersController(GetOrderRequestProcessor getOrderRequestProcessor) { _getOrderRequestProcessor = getOrderRequestProcessor; } public async Task> GetOrder(int orderId, CancellationToken cancellationToken) { return await _getOrderRequestProcessor.HandleAsync(new GetOrderRequest() { OrderId = orderId }, cancellationToken); } } ``` -------------------------------- ### HTTP Request to GetOrderRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequest.md Illustrates how an HTTP GET request with an order ID query parameter is translated into a GetOrderRequest object. ```text HTTP Request: GET /api/orders?orderId=1 ↓ GetOrderRequest { OrderId = 1 } ``` -------------------------------- ### Create Order Instance with Products Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Order.md Instantiate an Order object and populate its Products collection. This demonstrates a many-to-many relationship with the Product entity. ```csharp var order = new Order { OrderId = 1, Customer = "Customer 1", Products = new List { new Product { ProductId = 1, Name = "Product 1" }, new Product { ProductId = 2, Name = "Product 2" } } }; ``` -------------------------------- ### GET /api/products Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductsController.md Retrieves a single product by its unique identifier. This endpoint allows clients to fetch detailed information about a specific product. ```APIDOC ## GET /api/products ### Description Retrieves a single product by ID. This endpoint allows clients to fetch detailed information about a specific product. ### Method GET ### Endpoint /api/products ### Parameters #### Query Parameters - **productId** (int) - Required - Product identifier ### Response #### Success Response (200) - **result** (ProductModel) - Product details #### Response Example ```json { "result": { "productId": 1, "name": "Product 1" } } ``` #### Error Response (204) Product not found ``` -------------------------------- ### Retrieve Product via Console Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Execute this command to retrieve product details using the console application. Specify the 'GetProduct' command and the product ID. ```bash dotnet run --project PortsAndAdaptersPatternDemo.ConsoleApp GetProduct 1 ``` -------------------------------- ### Get Order by ID Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrdersController.md Retrieves a single order by its unique identifier. This endpoint is useful for fetching detailed information about a specific order. ```APIDOC ## GET /api/orders ### Description Retrieves a single order by ID. ### Method GET ### Endpoint /api/orders ### Parameters #### Query Parameters - **orderId** (int) - Required - Order identifier ### Response #### Success Response (200) - **result** (OrderModel) - Order details including products #### Response Example ```json { "result": { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 3, "name": "Product 3" }, { "productId": 7, "name": "Product 7" } ] } } ``` #### Error Response - **204 No Content** - Order not found ``` -------------------------------- ### Construct OrderModel Programmatically Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrderModel.md Demonstrates how to create an instance of OrderModel with associated products. ```csharp var orderModel = new OrderModel { OrderId = 1, Customer = "Customer 1", Products = new List { new ProductModel { ProductId = 1, Name = "Product 1" }, new ProductModel { ProductId = 2, Name = "Product 2" }, new ProductModel { ProductId = 3, Name = "Product 3" } } }; ``` -------------------------------- ### ProductsController Constructor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductsController.md Initializes the ProductsController using dependency injection for the GetProductRequestProcessor. Ensure GetProductRequestProcessor is registered in the service collection. ```csharp public ProductsController(GetProductRequestProcessor getProductRequestProcessor) ``` -------------------------------- ### GET /api/orders Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/README.md Retrieves an order by its ID, including associated products. This endpoint is part of the ASP.NET Core HTTP controller for order-related operations. ```APIDOC ## GET /api/orders ### Description Retrieve order by ID with associated products. ### Method GET ### Endpoint /api/orders ### Parameters #### Query Parameters - **orderId** (int) - Required - The ID of the order to retrieve. ### Response #### Success Response (200) - **Result** (GetOrderResponse) - The order details including associated products, or null if not found. #### Response Example { "result": { "orderId": 1, "customer": "string", "products": [ { "productId": 1, "name": "string" } ] } } ERROR HANDLING: - Status codes: 200 OK for success and not-found, 400 Bad Request for invalid input. ``` -------------------------------- ### Seed Database with Sample Data Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/DemoDbContext.md Seeds the DemoDbContext with sample data, creating 10 products and 10 orders, with each order assigned 5 random products. This method ensures the database is created and populated. ```csharp public static void SeedData() { using var context = new DemoDbContext(); // Ensure database is created context.Database.EnsureCreated(); // Create products var products = new List(); for (int i = 1; i <= 10; i++) { products.Add(new Product { Name = $"Product {i}" }); } context.Products.AddRange(products); context.SaveChanges(); // Create orders and assign random products var orders = new List(); var random = new Random(); for (int i = 1; i <= 10; i++) { var order = new Order { CustomerName = $"Customer {i}" }; var orderProducts = products.OrderBy(p => random.Next()).Take(5).ToList(); order.Products = orderProducts; orders.Add(order); } context.Orders.AddRange(orders); context.SaveChanges(); } ``` ```csharp DemoDbContext.SeedData(); // Database now contains 10 products and 10 orders with relationships using var context = new DemoDbContext(); var orderCount = context.Orders.Count(); // Returns 10 var productCount = context.Products.Count(); // Returns 10 ``` -------------------------------- ### Get Product by ID Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Retrieves a single product using its unique identifier. The product can either be found or not found, both returning a 200 OK status. ```APIDOC ## GET /api/products ### Description Retrieves a single product by ID. ### Method GET ### Endpoint /api/products ### Parameters #### Query Parameters - **productId** (int) - Required - The ID of the product to retrieve ### Request Example ``` GET /api/products?productId=1 ``` ### Response #### Success Response (200) - **result** (ProductModel | null) - The retrieved product, or null if not found **ProductModel Structure**: - **productId** (int) - Product identifier - **name** (string | null) - Product name #### Response Example (Product Found) ```json { "result": { "productId": 1, "name": "Product 1" } } ``` #### Response Example (Product Not Found) ```json { "result": null } ``` #### Error Response Example (400 Bad Request) ```json { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "..." } ``` ``` -------------------------------- ### ASP.NET Core Middleware Pipeline Configuration Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/configuration.md Configures the HTTP request pipeline for the ASP.NET Core application. Includes conditional setup for development and production environments. ```csharp // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Entity Framework Order-Product Relationship Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Order.md Configures a many-to-many relationship between Order and Product entities in Entity Framework Core. This setup uses a junction table implicitly. ```csharp modelBuilder.Entity() .HasMany(e => e.Products) .WithMany(e => e.Orders); ``` -------------------------------- ### CLI Command to GetProductRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Illustrates how a CLI command with a product ID argument is converted into a GetProductRequest object. ```text CLI Command: dotnet app.dll GetProduct 1 ↓ GetProductRequest { ProductId = 1 } ``` -------------------------------- ### Construct ProductModel Programmatically Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Instantiate a ProductModel object with its essential properties. ```csharp var productModel = new ProductModel { ProductId = 1, Name = "Laptop" }; ``` -------------------------------- ### Model Validation Error Response Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Example of a 400 Bad Request response when a query parameter fails model validation. The response body details the specific validation errors. ```http Status: 400 Bad Request Content-Type: application/json { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "errors": { "orderId": ["The value 'abc' is not valid for Int32."] }, "traceId": "0HN1234567:00000001" } ``` -------------------------------- ### Create GetProductRequest Instance Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Instantiate GetProductRequest and set the ProductId property. ```csharp var request = new GetProductRequest { ProductId = 1 }; ``` -------------------------------- ### ProductsController Implementation Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md C# controller implementation for handling product-related API requests. It uses a request processor to handle the business logic. ```csharp using Microsoft.AspNetCore.Mvc; using System.Threading; using System.Threading.Tasks; [Route("api/[controller]")] [ApiController] public class ProductsController : ControllerBase { private readonly GetProductRequestProcessor _getProductRequestProcessor; public ProductsController(GetProductRequestProcessor getProductRequestProcessor) { _getProductRequestProcessor = getProductRequestProcessor; } public async Task> GetProduct(int productId, CancellationToken cancellationToken) { return await _getProductRequestProcessor.HandleAsync(new GetProductRequest() { ProductId = productId }, cancellationToken); } } ``` -------------------------------- ### Programmatic Usage of GetProductRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Illustrates direct programmatic usage of GetProductRequest with a processor instance. ```csharp var processor = new GetProductRequestProcessor(dbContext); var request = new GetProductRequest { ProductId = 1 }; var response = await processor.HandleAsync(request, CancellationToken.None); ``` -------------------------------- ### OrderModel JSON Serialization Example Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/OrderModel.md Illustrates the JSON structure of an OrderModel when serialized by ASP.NET Core. Property names are converted to camelCase by default, and all properties, including null values, are included. ```json { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 1, "name": "Product 1" }, { "productId": 2, "name": "Product 2" } ] } ``` -------------------------------- ### Create Product with ProductId Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Instantiate a Product object and set its ProductId. This is useful for creating new product records or referencing existing ones. ```csharp var product = new Product { ProductId = 1 }; ``` -------------------------------- ### Testing Endpoints with HTTP Client in C# Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Utilize the HttpClient class in C# to make asynchronous GET requests to the API. The response content can be read and deserialized into the appropriate data contract. ```csharp using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:7001"); // Get order var response = await client.GetAsync("/api/orders?orderId=1"); var content = await response.Content.ReadAsStringAsync(); // Deserialize response var orderResponse = JsonSerializer.Deserialize(content); ``` -------------------------------- ### Instantiate GetOrderResponse with Default Constructor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderResponse.md Shows how to create a default instance of GetOrderResponse using its parameterless constructor and then assign an OrderModel. ```csharp var response = new GetOrderResponse(); response.Result = orderModel; ``` -------------------------------- ### Direct API Testing with PowerShell Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/configuration.md Uses PowerShell's Invoke-WebRequest to send an HTTP GET request to the orders API endpoint and retrieve order details. Assumes the API is running on localhost:7001. ```powershell (Invoke-WebRequest -Uri https://localhost:7001/api/orders?orderId=1).Content ``` -------------------------------- ### GET /api/orders Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/endpoints.md Retrieves a single order by ID, including all associated products. The orderId is provided as a query string parameter. The response includes the order details or null if the order is not found. Error responses are returned for invalid requests. ```APIDOC ## GET /api/orders ### Description Retrieves a single order by ID, including all associated products. ### Method GET ### Endpoint /api/orders ### Parameters #### Query Parameters - **orderId** (int) - Required - The ID of the order to retrieve ### Request Example ``` GET /api/orders?orderId=1 ``` ### Response #### Success Response (200) - **result** (OrderModel | null) - The retrieved order, or null if not found **OrderModel Structure**: - **orderId** (int) - Order identifier - **customer** (string | null) - Customer name - **products** (Array | null) - List of products in the order **ProductModel Structure**: - **productId** (int) - Product identifier - **name** (string | null) - Product name #### Response Example (200 OK - Order Found) ```json { "result": { "orderId": 1, "customer": "Customer 1", "products": [ { "productId": 2, "name": "Product 2" }, { "productId": 5, "name": "Product 5" }, { "productId": 8, "name": "Product 8" } ] } } ``` #### Response Example (200 OK - Order Not Found) ```json { "result": null } ``` #### Error Response Example (400 Bad Request) ```json { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "..." } ``` ``` -------------------------------- ### ProductModel Data Transformation in GetProductRequestProcessor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Shows how ProductModel is created from a Product entity using LINQ projection within the GetProductRequestProcessor. ```csharp var result = await _demoDbContext.Products .Where(p => p.ProductId == request.ProductId) .Select(o => new ProductModel() { Name = o.Name, ProductId = o.ProductId }) .FirstOrDefaultAsync(cancellationToken); ``` -------------------------------- ### Handle Null ProductModel and Name Property Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Demonstrates scenarios where a ProductModel might be null or have a null Name property, particularly when a product is not found or when data is incomplete. ```csharp // When product is not found var response = new GetProductResponse { Result = null }; // ProductModel with null name var product = new ProductModel { ProductId = 1, Name = null }; ``` -------------------------------- ### Create Order Instance with OrderId Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Order.md Instantiate an Order object and set its primary key. ```csharp var order = new Order { OrderId = 1 }; ``` -------------------------------- ### SeedData Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/DemoDbContext.md Static method that creates the database and populates it with sample data, including products and orders with relationships. ```APIDOC ## SeedData() ### Description Static method that creates the database and populates it with sample data. Creates 10 products and 10 orders, each order assigned 5 random products. ### Method Signature ```csharp public static void SeedData() ``` ### Parameters None ### Returns void ### Behavior - Ensures database is created - Generates 10 products with names "Product 1" through "Product 10" - Generates 10 orders with customer names "Customer 1" through "Customer 10" - Each order receives 5 randomly selected products from the product set - All data is persisted to the database ### Example ```csharp DemoDbContext.SeedData(); // Database now contains 10 products and 10 orders with relationships using var context = new DemoDbContext(); var orderCount = context.Orders.Count(); // Returns 10 var productCount = context.Products.Count(); // Returns 10 ``` ``` -------------------------------- ### Instantiate GetOrderRequest using Default Constructor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequest.md Shows how to use the default constructor and then set the OrderId property. ```csharp var request = new GetOrderRequest(); request.OrderId = 1; ``` -------------------------------- ### Retrieve a Product by ID Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Retrieves a single product from the database using its ProductId. Requires instantiation of DemoDbContext. ```csharp using var context = new DemoDbContext(); var product = await context.Products .FirstOrDefaultAsync(p => p.ProductId == 1); ``` -------------------------------- ### Instantiate GetOrderRequest with OrderId Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequest.md Demonstrates how to create an instance of GetOrderRequest and set the OrderId property. ```csharp var request = new GetOrderRequest { OrderId = 1 }; ``` -------------------------------- ### Access Product Entities Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/DemoDbContext.md Retrieves all Product entities from the database using the Products DbSet. ```csharp var products = context.Products.ToList(); ``` -------------------------------- ### Use ProductModel as a Standalone Response Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/ProductModel.md Shows how to use ProductModel as the result of a single product retrieval operation. ```csharp // Single product retrieval var response = new GetProductResponse { Result = new ProductModel { ProductId = 1, Name = "Product 1" } }; ``` -------------------------------- ### Default Constructor for GetProductRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Use the default parameterless constructor to create a new instance of GetProductRequest, then set the ProductId. ```csharp var request = new GetProductRequest(); request.ProductId = 1; ``` -------------------------------- ### Instantiate GetOrderResponse with OrderModel Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderResponse.md Demonstrates how to create an instance of GetOrderResponse and assign an OrderModel to its Result property. ```csharp var response = new GetOrderResponse { Result = new OrderModel { OrderId = 1, Customer = "Customer 1" } }; ``` -------------------------------- ### Configure Console App Services Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/configuration.md Sets up services for the console application, registering request processors and the database context. A TypeRegistrar is used for integrating with Spectre.Console.Cli. ```csharp var services = new ServiceCollection(); services.AddTransient(); services.AddTransient(); services.AddDbContext(); // Create a type registrar and register any dependencies. var registrar = new TypeRegistrar(services); DemoDbContext.SeedData(); var app = new CommandApp(); app.Configure(config => { config.AddCommand("GetOrder"); config.AddCommand("GetProduct"); }); return app.Run(args); ``` -------------------------------- ### GetOrderRequestProcessor Constructor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequestProcessor.md Initializes a new instance of the GetOrderRequestProcessor. Requires an Entity Framework Core database context for accessing order and product data. ```csharp public GetOrderRequestProcessor(DemoDbContext demoDbContext) ``` ```csharp var dbContext = new DemoDbContext(); var processor = new GetOrderRequestProcessor(dbContext); ``` -------------------------------- ### Product Class Definition Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/Product.md Defines the Product entity with its properties and navigation to Orders. Includes necessary using directives and namespace. ```csharp using System.ComponentModel.DataAnnotations; namespace PortsAndAdaptersPatternDemo.Data; public class Product { [Key] public int ProductId { get; set; } public string Name { get; set; } public List Orders { get; set; } } ``` -------------------------------- ### CLI Command to GetOrderRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequest.md Shows how a command-line interface command with an order ID argument is converted into a GetOrderRequest object. ```text CLI Command: dotnet app.dll GetOrder 1 ↓ GetOrderRequest { OrderId = 1 } ``` -------------------------------- ### Programmatic Usage of GetOrderRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequest.md Demonstrates direct programmatic usage of GetOrderRequest with a processor instance. ```csharp var processor = new GetOrderRequestProcessor(dbContext); var request = new GetOrderRequest { OrderId = 1 }; var response = await processor.HandleAsync(request, CancellationToken.None); ``` -------------------------------- ### GetOrderRequestProcessor Constructor Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetOrderRequestProcessor.md Initializes a new instance of the GetOrderRequestProcessor with the required database context dependency. ```APIDOC ## GetOrderRequestProcessor(DemoDbContext demoDbContext) ### Description Initializes a new instance of the GetOrderRequestProcessor with the required database context dependency. ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Constructor Signature ```csharp public GetOrderRequestProcessor(DemoDbContext demoDbContext) ``` ### Parameters - **demoDbContext** (DemoDbContext) - Required - Entity Framework Core database context for accessing order and product data ### Returns New instance of GetOrderRequestProcessor ### Example ```csharp var dbContext = new DemoDbContext(); var processor = new GetOrderRequestProcessor(dbContext); ``` ``` -------------------------------- ### API Controller Usage of GetProductRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Demonstrates how to create and pass a GetProductRequest from an API controller action to the GetProductRequestProcessor. ```csharp // In ProductsController.GetProduct public async Task> GetProduct(int productId, CancellationToken cancellationToken) { return await _getProductRequestProcessor.HandleAsync(new GetProductRequest() { ProductId = productId }, cancellationToken); } ``` -------------------------------- ### Project File Structure Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/INDEX.md Illustrates the organization of markdown files within the project for documentation purposes. ```markdown /workspace/home/output/ ├── README.md (Main entry point) ├── INDEX.md (This file) ├── endpoints.md (HTTP endpoint specs) ├── types.md (Type definitions) ├── configuration.md (Configuration options) └── api-reference/ (Individual class docs) ├── DemoDbContext.md ├── OrdersController.md ├── ProductsController.md ├── GetOrderRequestProcessor.md ├── GetProductRequestProcessor.md ├── Order.md ├── Product.md ├── OrderModel.md ├── ProductModel.md ├── GetOrderRequest.md ├── GetOrderResponse.md ├── GetProductRequest.md └── GetProductResponse.md ``` -------------------------------- ### Console Application Response Handling Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductResponse.md Shows how a console application processes the GetProductResponse, deserializes it, and pretty-prints the formatted JSON output. ```csharp public override int Execute(CommandContext context, Settings settings) { var result = _getProductRequestProcessor.HandleAsync(new GetProductRequest() { ProductId = settings.ProductId }, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); Console.WriteLine(JsonSerializer.Serialize(result, new JsonSerializerOptions() { WriteIndented = true })); return 0; } ``` -------------------------------- ### Console Application Usage of GetProductRequest Source: https://github.com/dasiths/portsandadapterspatterndemo/blob/master/_autodocs/api-reference/GetProductRequest.md Shows how to use GetProductRequest within a console application command, passing it to the HandleAsync method. ```csharp // In GetProductCommand.Execute var result = _getProductRequestProcessor.HandleAsync(new GetProductRequest() { ProductId = settings.ProductId }, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); ```