Skip to content

[BACKEND] Fix Non-Nullable Property Initialization Warnings (CS8618) #491

@Andreawingardh

Description

@Andreawingardh

Fix Non-Nullable Property Initialization Warnings (CS8618)

Issue Type

  • Technical Debt
  • Code Quality
  • Bug
  • Feature

Priority

🟡 Medium - Should fix when convenient (prevents potential null reference exceptions)


Description

Multiple classes have non-nullable properties that don't have initial values, causing compiler warning CS8618. This indicates potential null reference issues at runtime, even though Entity Framework and ASP.NET model binding may handle these cases correctly.

Compiler Warning:

warning CS8618: Non-nullable property 'PropertyName' must contain a non-null value when exiting constructor. 
Consider adding the 'required' modifier or declaring the property as nullable.

Affected Files and Properties

1. RequestScreenshotUrlsDto.cs

Location: backend/Atelje/DTOs/R2/RequestScreenshotUrlsDto.cs

Properties:

  • Line 9: FullFileName
  • Line 13: ThumbnailFileName
public class RequestScreenshotUrlsDto
{
    public string FullFileName { get; set; }      // ⚠️ Warning
    public string ThumbnailFileName { get; set; }  // ⚠️ Warning
}

2. Design.cs (Entity Model)

Location: backend/Atelje/Models/Design.cs

Properties:

  • Line 6: Name
  • Line 9: UserId
  • Line 10: User
  • Line 12: DesignData
public class Design
{
    public int Id { get; set; }
    public string Name { get; set; }           // ⚠️ Warning
    public DateTime CreatedAt { get; set; }
    public DateTime UpdatedAt { get; set; }
    public string UserId { get; set; }         // ⚠️ Warning
    public User User { get; set; }             // ⚠️ Warning
    // ... other properties
    public string DesignData { get; set; }     // ⚠️ Warning
}

Implementation Strategy

For each property, choose the appropriate fix based on domain rules:

Option 1: Add required Modifier (C# 11+)

Use when: The property MUST always have a value and should be set during object initialization.

public required string Name { get; set; }

Benefits:

  • Compiler enforces that property is set during initialization
  • Most explicit about domain requirements
  • Best for DTOs that come from API requests

Option 2: Make Nullable

Use when: The property CAN legitimately be null in your domain.

public string? Name { get; set; }

Benefits:

  • Honest about nullable semantics
  • Enables null-conditional operators (?.)
  • Compiler helps track null handling

Option 3: Provide Default Value

Use when: There's a sensible default value.

public string Name { get; set; } = string.Empty;

Benefits:

  • No warnings
  • Never actually null
  • Good for properties that default to empty

Recommended Fixes

RequestScreenshotUrlsDto

public class RequestScreenshotUrlsDto
{
    // These MUST be provided by the client
    public required string FullFileName { get; set; }
    public required string ThumbnailFileName { get; set; }
}

Rationale: These are request DTOs - the API requires these values from the client.

Design Model

Domain Questions to Answer:

  1. Can a Design exist without a Name? → Probably NO
  2. Can a Design exist without a UserId? → Definitely NO (ownership)
  3. Can a Design exist without User navigation property? → YES (lazy loading)
  4. Can a Design exist without DesignData? → Probably NO (it's the core data)

Recommended:

public class Design
{
    public int Id { get; set; }
    
    // Required - every design must have a name
    public required string Name { get; set; }
    
    public DateTime CreatedAt { get; set; }
    public DateTime UpdatedAt { get; set; }
    
    // Required - every design must have an owner
    public required string UserId { get; set; }
    
    // Nullable - EF Core navigation property (lazy loaded)
    public User? User { get; set; }
    
    // Additional properties...
    
    // Required - every design must have data
    public required string DesignData { get; set; }
}

Implementation Steps

Phase 1: RequestScreenshotUrlsDto (5 min)

  • Open backend/Atelje/DTOs/R2/RequestScreenshotUrlsDto.cs
  • Add required modifier to both properties
  • Build project to verify no warnings
  • Run tests to ensure API binding still works

Phase 2: Design Model (15 min)

  • Open backend/Atelje/Models/Design.cs
  • Add required to: Name, UserId, DesignData
  • Make User nullable: public User? User { get; set; }
  • Build project
  • Check for compilation errors in places that create Design objects
  • Update any Design instantiation code to use object initializer syntax

Phase 3: Update Design Creation Code (10 min)

You may need to update code that creates Design objects:

Before:

var design = new Design();
design.Name = dto.Name;
design.UserId = userId;

After (required properties force this pattern):

var design = new Design
{
    Name = dto.Name,
    UserId = userId,
    DesignData = dto.DesignData,
    // ... other properties
};

Phase 4: Testing (10 min)

  • Run unit tests
  • Test design creation via API
  • Test design updates via API
  • Verify no null reference exceptions
  • Check that Entity Framework migrations work

Potential Breaking Changes

Design Model Changes

If you add required to Design properties, any code that creates Design instances without object initializers will break:

Search for:

# In your backend directory
grep -r "new Design()" .

Common locations:

  • DesignController
  • Unit tests (DesignControllerTests, DesignServiceTests)
  • Database seeding code

Testing Checklist

  • All unit tests pass
  • POST /api/designs creates new design
  • PUT /api/designs/{id} updates existing design
  • Screenshot upload flow works
  • No null reference exceptions in logs
  • Entity Framework migrations still apply

Alternative Approach: Suppress Warnings (Not Recommended)

If you're very short on time, you can suppress these warnings:

#pragma warning disable CS8618
public string Name { get; set; }
#pragma warning restore CS8618

Why this is not recommended:

  • Hides potential runtime issues
  • Doesn't improve code quality
  • Makes future maintenance harder

Expected Outcome

Before:

warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor.
warning CS8618: Non-nullable property 'UserId' must contain a non-null value when exiting constructor.
... (6 more warnings)

After:

Build succeeded. 0 Warning(s)

Estimated Time

  • RequestScreenshotUrlsDto: 5 minutes
  • Design Model: 15 minutes
  • Update creation code: 10 minutes
  • Testing: 10 minutes
  • Total: 40 minutes

Risk: Low-Medium (may require updating object creation patterns)


Success Criteria

  • No CS8618 warnings in build output
  • All existing tests pass
  • Design CRUD operations work correctly
  • Screenshot upload functionality works
  • No new null reference exceptions

Notes

  • The required modifier was introduced in C# 11 (.NET 7+)
  • Your project uses .NET 9, so required is available
  • Entity Framework Core works well with required properties
  • Navigation properties (like User) should typically be nullable

References


Labels

code-quality medium-priority nullable-warnings cs8618 dto entity-model

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions