# Development Guide ## Quick Start Commands ### Build Solution ```bash dotnet build PowderCoatingApp.sln ``` ### Run Web Application ```bash cd src/PowderCoating.Web dotnet run ``` ### Run API ```bash cd src/PowderCoating.Api dotnet run ``` ### Watch Mode (Auto-reload) ```bash cd src/PowderCoating.Web dotnet watch run ``` ## Entity Framework Core Commands ### Add Migration ```bash cd src/PowderCoating.Web dotnet ef migrations add MigrationName --project ../PowderCoating.Infrastructure ``` ### Update Database ```bash dotnet ef database update --project ../PowderCoating.Infrastructure ``` ### Remove Last Migration ```bash dotnet ef migrations remove --project ../PowderCoating.Infrastructure ``` ### Generate SQL Script ```bash dotnet ef migrations script --project ../PowderCoating.Infrastructure --output migration.sql ``` ### View Migrations ```bash dotnet ef migrations list --project ../PowderCoating.Infrastructure ``` ## Project Management ### Add New NuGet Package ```bash cd src/PowderCoating.Core dotnet add package PackageName ``` ### Restore Packages ```bash dotnet restore ``` ### Clean Solution ```bash dotnet clean ``` ## Creating New Components ### Add New Entity 1. Create entity class in `PowderCoating.Core/Entities/` 2. Inherit from `BaseEntity` 3. Add DbSet to `ApplicationDbContext` 4. Add repository to `IUnitOfWork` and `UnitOfWork` 5. Create migration 6. Update database Example: ```csharp // 1. Create entity public class NewEntity : BaseEntity { public string Name { get; set; } = string.Empty; // ... properties } // 2. Add to DbContext public DbSet NewEntities { get; set; } // 3. Add to IUnitOfWork IRepository NewEntities { get; } // 4. Add to UnitOfWork private IRepository? _newEntities; public IRepository NewEntities => _newEntities ??= new Repository(_context); // 5. Add migration dotnet ef migrations add AddNewEntity --project ../PowderCoating.Infrastructure // 6. Update database dotnet ef database update --project ../PowderCoating.Infrastructure ``` ### Add New Controller (Web) 1. Create in `PowderCoating.Web/Controllers/` 2. Inherit from `Controller` 3. Inject `IUnitOfWork` and `IMapper` 4. Create corresponding views in `Views/[ControllerName]/` Example: ```csharp public class NewController : Controller { private readonly IUnitOfWork _unitOfWork; private readonly IMapper _mapper; public NewController(IUnitOfWork unitOfWork, IMapper mapper) { _unitOfWork = unitOfWork; _mapper = mapper; } public async Task Index() { var items = await _unitOfWork.NewEntities.GetAllAsync(); return View(items); } } ``` ### Add New API Controller 1. Create in `PowderCoating.Api/Controllers/` 2. Add `[ApiController]` and `[Route("api/[controller]")]` attributes 3. Inject dependencies 4. Return appropriate `ActionResult` types Example: ```csharp [ApiController] [Route("api/[controller]")] [Authorize] public class NewApiController : ControllerBase { private readonly IUnitOfWork _unitOfWork; private readonly IMapper _mapper; public NewApiController(IUnitOfWork unitOfWork, IMapper mapper) { _unitOfWork = unitOfWork; _mapper = mapper; } [HttpGet] public async Task>> GetAll() { var items = await _unitOfWork.NewEntities.GetAllAsync(); var dtos = _mapper.Map>(items); return Ok(dtos); } } ``` ### Add New DTO 1. Create in `PowderCoating.Application/DTOs/[Module]/` 2. Create AutoMapper profile Example: ```csharp // DTO public class NewDto { public int Id { get; set; } public string Name { get; set; } = string.Empty; } // AutoMapper Profile public class NewProfile : Profile { public NewProfile() { CreateMap(); CreateMap(); } } ``` ## Best Practices ### Code Style - Follow C# coding conventions - Use meaningful variable and method names - Add XML documentation for public APIs - Keep methods focused (Single Responsibility) - Use async/await for I/O operations ### Entity Framework - Use async methods (`ToListAsync`, `FirstOrDefaultAsync`, etc.) - Include related entities when needed (`Include`, `ThenInclude`) - Use `.AsNoTracking()` for read-only queries - Handle concurrency conflicts - Use transactions for multi-step operations ### API Development - Use appropriate HTTP status codes - Validate input with FluentValidation - Use DTOs, never expose entities directly - Document endpoints with XML comments for Swagger - Implement proper error handling ### Security - Always validate user input - Use parameterized queries (EF Core does this) - Implement authorization on controllers/actions - Don't expose sensitive data in responses - Use HTTPS in production - Store secrets in user secrets or Azure Key Vault ### Performance - Use pagination for large datasets - Implement caching where appropriate - Use projection (Select) to retrieve only needed fields - Profile and optimize slow queries - Use async for I/O-bound operations ## Common Patterns ### Service Pattern ```csharp public interface IJobService { Task GetByIdAsync(int id); Task> GetAllAsync(); Task CreateAsync(CreateJobDto dto); Task UpdateAsync(UpdateJobDto dto); Task DeleteAsync(int id); } public class JobService : IJobService { private readonly IUnitOfWork _unitOfWork; private readonly IMapper _mapper; public JobService(IUnitOfWork unitOfWork, IMapper mapper) { _unitOfWork = unitOfWork; _mapper = mapper; } // Implementation... } ``` ### Repository Pattern (Already Implemented) ```csharp var customers = await _unitOfWork.Customers.FindAsync(c => c.IsActive); var customer = await _unitOfWork.Customers.GetByIdAsync(id); await _unitOfWork.Customers.AddAsync(newCustomer); await _unitOfWork.SaveChangesAsync(); ``` ### Unit of Work with Transaction ```csharp try { await _unitOfWork.BeginTransactionAsync(); // Multiple operations await _unitOfWork.Jobs.AddAsync(job); await _unitOfWork.JobItems.AddRangeAsync(items); await _unitOfWork.CommitTransactionAsync(); } catch { await _unitOfWork.RollbackTransactionAsync(); throw; } ``` ## Debugging Tips ### Enable Sensitive Data Logging In `appsettings.Development.json`: ```json "Logging": { "LogLevel": { "Microsoft.EntityFrameworkCore.Database.Command": "Information" } } ``` In `DbContext` configuration (development only): ```csharp options.UseSqlServer(connectionString) .EnableSensitiveDataLogging() .EnableDetailedErrors(); ``` ### View Generated SQL ```csharp var query = _context.Jobs.Where(j => j.Status == JobStatus.Pending); var sql = query.ToQueryString(); Console.WriteLine(sql); ``` ### Common Issues **Issue**: Migration fails with "object already exists" ```bash # Solution: Remove migration and try again dotnet ef migrations remove --project ../PowderCoating.Infrastructure dotnet ef migrations add NewMigration --project ../PowderCoating.Infrastructure ``` **Issue**: DbContext is disposed ```bash # Solution: Ensure you're using proper DI scoping and not storing DbContext # Use IUnitOfWork which has proper lifetime management ``` **Issue**: Circular reference in JSON ```csharp // Solution: Use DTOs or configure JSON serialization services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; }); ``` ## Testing ### Unit Test Example ```csharp public class CustomerServiceTests { [Fact] public async Task GetByIdAsync_ReturnsCustomer_WhenExists() { // Arrange var mockUnitOfWork = new Mock(); var customer = new Customer { Id = 1, CompanyName = "Test" }; mockUnitOfWork .Setup(x => x.Customers.GetByIdAsync(1)) .ReturnsAsync(customer); var service = new CustomerService(mockUnitOfWork.Object, mapper); // Act var result = await service.GetByIdAsync(1); // Assert Assert.NotNull(result); Assert.Equal("Test", result.CompanyName); } } ``` ## Deployment ### Publish Web Application ```bash cd src/PowderCoating.Web dotnet publish -c Release -o ./publish ``` ### Publish API ```bash cd src/PowderCoating.Api dotnet publish -c Release -o ./publish ``` ### Generate Database Script for Production ```bash cd src/PowderCoating.Web dotnet ef migrations script --project ../PowderCoating.Infrastructure --idempotent --output deploy.sql ``` ## Resources - [ASP.NET Core Documentation](https://docs.microsoft.com/aspnet/core) - [Entity Framework Core Documentation](https://docs.microsoft.com/ef/core) - [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) - [C# Coding Conventions](https://docs.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions)