---
name: step-03-generate
description: Generate controller file and DTOs
next_step: steps/step-04-perms.md
---

# Step 3: Generate Controller

## YOUR TASK:

Generate the controller file following SmartStack conventions. Use templates from `templates.md`.

**ULTRA THINK about security and patterns.**

---

## EXECUTION SEQUENCE:

### 1. Load Templates

**Read template file:**

```
Read: templates/templates.md
```

**Select appropriate template based on {controller_type}:**
- CRUD Controller template
- Auth Controller template
- ReadOnly Controller template

### 2. Generate Controller File

**Target path:**
```
src/SmartStack.Api/Controllers/{area}/{module}Controller.cs
```

**Apply template with variables:**

```csharp
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using SmartStack.Application.Common.Authorization;
using SmartStack.Application.Common.Interfaces;
using SmartStack.Domain.Entities;

namespace SmartStack.Api.Controllers.{area};

[ApiController]
[Route("api/{area_lowercase}/[controller]")]
[Authorize]
public class {module}Controller : ControllerBase
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;
    private readonly ILogger<{module}Controller> _logger;

    public {module}Controller(
        IApplicationDbContext context,
        ICurrentUserService currentUser,
        ILogger<{module}Controller> logger)
    {
        _context = context;
        _currentUser = currentUser;
        _logger = logger;
    }

    // Endpoints generated based on plan...
}
```

### 3. Generate Endpoints

**For each planned endpoint, generate with:**

1. **Attributes:**
   - `[HttpGet]`, `[HttpPost]`, etc.
   - `[RequirePermission(Permissions.{module}.View)]`
   - `[ProducesResponseType(typeof(...), StatusCodes.Status200OK)]`
   - `[ProducesResponseType(StatusCodes.Status401Unauthorized)]`
   - `[ProducesResponseType(StatusCodes.Status403Forbidden)]`

2. **Method body:**
   - Parameter validation
   - Entity operation
   - Logging
   - Response mapping

**Example GET endpoint:**

```csharp
[HttpGet]
[RequirePermission(Permissions.{module}.View)]
[ProducesResponseType(typeof(PagedResult<{entity}ResponseDto>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> GetAll(
    [FromQuery] int page = 1,
    [FromQuery] int pageSize = 20,
    CancellationToken ct = default)
{
    var query = _context.{module}
        .AsNoTracking()
        .OrderByDescending(x => x.CreatedAt);

    var total = await query.CountAsync(ct);
    var items = await query
        .Skip((page - 1) * pageSize)
        .Take(pageSize)
        .Select(x => new {entity}ResponseDto(x))
        .ToListAsync(ct);

    return Ok(new PagedResult<{entity}ResponseDto>(items, total, page, pageSize));
}
```

### 4. Generate DTOs (if dto_mode)

**Target paths:**
```
src/SmartStack.Application/DTOs/{module}/{entity}CreateDto.cs
src/SmartStack.Application/DTOs/{module}/{entity}UpdateDto.cs
src/SmartStack.Application/DTOs/{module}/{entity}ResponseDto.cs
```

**CreateDto template:**

```csharp
public record {entity}CreateDto(
    string Name,
    // ... required properties
);
```

**UpdateDto template:**

```csharp
public record {entity}UpdateDto(
    string? Name,
    // ... optional properties
);
```

**ResponseDto template:**

```csharp
public record {entity}ResponseDto(
    Guid Id,
    string Name,
    // ... all public properties
    DateTime CreatedAt,
    DateTime? UpdatedAt
)
{
    public {entity}ResponseDto({entity} entity) : this(
        entity.Id,
        entity.Name,
        // ... mapping
        entity.CreatedAt,
        entity.UpdatedAt
    ) { }
}
```

### 5. Add Security Logging

**Ensure logging for all operations:**

```csharp
// Create
_logger.LogInformation("User {User} created {entity} {Id}",
    _currentUser.Email, entity.Id);

// Update
_logger.LogInformation("User {User} updated {entity} {Id}",
    _currentUser.Email, entity.Id);

// Delete (Warning level)
_logger.LogWarning("User {User} deleted {entity} {Id} ({Name})",
    _currentUser.Email, id, entity.Name);
```

### 6. Protect System Accounts (if applicable)

**Add guard for system entities:**

```csharp
// Before modify/delete operations
if (entity.UserType == UserType.System || entity.UserType == UserType.LocalAdmin)
{
    _logger.LogWarning("Attempt to modify system account {Id} by {User}",
        entity.Id, _currentUser.Email);
    return BadRequest(new { message = "Cannot modify system accounts" });
}
```

---

## OUTPUT FORMAT:

```
Generated Files:

| File | Path | Status |
|------|------|--------|
| Controller | src/.../Controllers/{area}/{module}Controller.cs | ✅ Created |
| CreateDto | src/.../DTOs/{module}/{entity}CreateDto.cs | ✅ Created |
| UpdateDto | src/.../DTOs/{module}/{entity}UpdateDto.cs | ✅ Created |
| ResponseDto | src/.../DTOs/{module}/{entity}ResponseDto.cs | ✅ Created |

-> Synchronizing permissions...
```

---

## NEXT STEP:

After generation complete, proceed to `./step-04-perms.md`
