Skip to content

Operations with enums in request models should not accept integers as valid input #975

Description

@hggutvik

Description of the bug

We tag enums with [JsonConverter(typeof(JsonStringEnumConverter))] to get them stringified on serialization to JSON. While this does work as intended, it seems that the JsonStringEnumConverter doesn't automatically correct or invalidate integers on deserialization. Its default setting is to allow int values.
Here are the operations that use JsonStringEnumConverter for deserializing request data:

POST .../verification/verify (AddressType)
POST .../verification/send (AddressType)
PUT .../users/current/profilesettings (Language)
PATCH .../users/current/profilesettings (Language)

Steps To Reproduce

In any of the API operations listed above, pass an integer value to JSON fields that internally maps to enum.

Expected behavior: 400 Bad data as response
Actual behavior: successful response or internal server error because the integer was treated as valid input

Solution considerations

Current codebase state

We currently have two groups of enums in the codebase:

Group 1 — enums that already serialize as string

Language, AddressType (verification), VerificationType, ProfileType

Group 2 — currently serialized as integers:

UserType (UserType.cs) has no attribute and explicit numeric values 0–6. It's serialized in UserProfile.UserType (UserProfile.cs:59), which is returned by all the GET user endpoints, the internal lookup, contact-point lookups, etc. Today consumers get "userType": 1.
PartyTypeName (third-party contract, from Altinn.Register.Contracts), also in UserProfile, also serializes as an integer today ("partyTypeName": 1)

Key questions to consider:

1. what should be the default for a new enum?

  • Serialize to int when converting C# -> JSON, and accept int values when deserializing from JSON -> C# request model
    vs
  • Serialize to string when converting C# -> JSON, and reject int values when deserializing from JSON -> C# request model

2. Where do we want to define the enum behavior?

  • Config located centrally/globally in Program.cs AddJsonOptions
    vs
  • Config scattered, targeted per-enum as annotations/tags (example: VerificationType)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status
    🌥 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions