← Back to Portfolio

Nexus ERP

Scalable Enterprise Resource Planning API

C# / .NET 8 CQRS (MediatR) Entity Framework Core SQL Server

Backend Architecture (Clean Architecture & CQRS)

This project implements a highly scalable Web API using CQRS pattern with MediatR. It isolates domain logic, uses EF Core for infrastructure, and maintains minimal controllers.

📄 OrdersController.cs (API Layer)

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IMediator _mediator;

    public OrdersController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Order>> GetOrder(Guid id)
    {
        var result = await _mediator.Send(new GetOrderQuery { OrderId = id });
        return result == null ? NotFound() : Ok(result);
    }

    [HttpPost]
    public async Task<ActionResult<Guid>> CreateOrder([FromBody] CreateOrderCommand command)
    {
        var orderId = await _mediator.Send(command);
        return CreatedAtAction(nameof(GetOrder), new { id = orderId }, orderId);
    }
}
                    
📄 CreateOrderCommand.cs (Application Layer)

public class CreateOrderCommand : IRequest<Guid>
{
    public string CustomerName { get; set; } = string.Empty;
    public decimal TotalAmount { get; set; }
    public List<string> Items { get; set; } = new();
}

public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, Guid>
{
    private readonly NexusDbContext _context;

    public CreateOrderCommandHandler(NexusDbContext context)
    {
        _context = context;
    }

    public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken token)
    {
        var order = new Order
        {
            Id = Guid.NewGuid(),
            CustomerName = request.CustomerName,
            TotalAmount = request.TotalAmount,
            Status = "Pending",
            CreatedAt = DateTime.UtcNow,
            Items = request.Items
        };

        _context.Orders.Add(order);
        await _context.SaveChangesAsync(token);
        return order.Id;
    }
}
                    
📄 Order.cs (Domain Layer)

public class Order
{
    [Key]
    public Guid Id { get; set; }
    
    [Required]
    [MaxLength(200)]
    public string CustomerName { get; set; } = string.Empty;
    
    [Required]
    public decimal TotalAmount { get; set; }
    
    public string Status { get; set; } = "Pending";
    
    public DateTime CreatedAt { get; set; }
    
    // Dodana lista przedmiotów, aby zgadzała się ze Swaggerem
    public List<string> Items { get; set; } = new();
}
                    
📄 Program.cs (Composition Root)

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Configure CQRS (MediatR)
builder.Services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));

// Configure EF Core (SQL Server)
builder.Services.AddDbContext<NexusDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseAuthorization();
app.MapControllers();
app.Run();
                    

Live API Documentation (Swagger UI)

Below is an interactive mockup of the Swagger UI generated for this API. You can test the endpoints to see how the CQRS commands and queries respond.

localhost:5001/swagger/index.html

Nexus ERP API v1

OpenAPI specification for the Nexus ERP System.

GET /api/Orders/{id} Retrieves a specific order by ID
Parameters
NameDescription
id *
string (uuid)
The ID of the order to retrieve.
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "customerName": "Acme Corporation", "totalAmount": 12500.50, "status": "Processed", "createdAt": "2026-08-07T14:32:00Z" }
POST /api/Orders Creates a new order
Request body
{ "customerName": "TechStart Inc", "totalAmount": 4500.00, "items": ["Laptop", "Monitor"] }
// Response Code: 201 Created // Location: /api/Orders/7b9f3e... "7b9f3ec1-19d2-4467-93eb-5b23d9b43d2c"