# Controller & DTO Code Templates

> Referenced from `steps/step-03-generate.md` — C# templates for controller, DTOs, and security patterns.

---

## Controller Template

**Target path:** `src/SmartStack.Api/Controllers/{ContextShort}/{Application}/{entity}Controller.cs`

> Context mapping: `business` → `Business`, `platform` → `Admin`, `personal` → `User`

```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...
}
```

---

## GET Endpoint Example

```csharp
[HttpGet]
[RequirePermission(Permissions.{module}.View)]
[ProducesResponseType(typeof(PaginatedResult<{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 PaginatedResult<{entity}ResponseDto>(items, total, page, pageSize));
}
```

**Endpoint attributes to include:**
1. `[HttpGet]`, `[HttpPost]`, etc.
2. `[RequirePermission(Permissions.{module}.View)]`
3. `[ProducesResponseType(typeof(...), StatusCodes.Status200OK)]`
4. `[ProducesResponseType(StatusCodes.Status401Unauthorized)]`
5. `[ProducesResponseType(StatusCodes.Status403Forbidden)]`

---

## DTO Templates

**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:**
```csharp
public record {entity}CreateDto(
    string Name,
    // ... required properties
);
```

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

**ResponseDto:**
```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
    ) { }
}
```

---

## Security Logging Templates

```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);
```

---

## System Account Protection

```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" });
}
```
