jeudi 23 mars 2023

C# Convert.ChangeType() int to enum

With the following model:

class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public WorkingLevel WorkingLevel { get; set; }
    // ...
}

enum WorkingLevel
{
    Unknown,
    Level1,
    Level2,
    Level3
}

and the following view model:

public class PatchResourceVM
{
    public List<PropertyValue> PropertyValues { get; set; } = new();
}

public class PropertyValue
{
    public string PropertyName { get; set; }
    public string? Value { get; set; }
}

I have an ASP.NET controller action like this which is supposed to updated properties of a person resource:

[HttpPatch("{id:int}")]
public async Task<IActionResult> UpdatePerson(int id, PatchResourceVM model)
{
    var person = await _dbContext.Employees.FindAsync(id);

    if (person is null)
    {
        return NotFound();
    }

    foreach (var propVal in model.ProrpertyValues)
    {
        var propertyInfo = person.GetType().GetProperty(propVal.PropertyName);
        if (propertyInfo is null)
        {
            return BadRequest($"Property {propVal.PropertyName} does not exist");
        }

        var oldValue = propertyInfo.GetValue(person, null);

        try
        {
            Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
            object? safeValue = (propVal.Value == null) ? null : Convert.ChangeType(propVal.Value, t);
            propertyInfo.SetValue(person, safeValue, null);
        }
        catch (InvalidCastException)
        {
            return BadRequest($"{propVal.Value} is not a valid value for {propVal.PropertyName}");
        }
        // from this answer: https://stackoverflow.com/a/41466710/19363672

        var changeLog = new PersonChangeLog
        {
            PersonId = id,
            // ...
            PropertyName = propVal.PropertyName,
            OldValue = oldValue?.ToString(),
            NewValue = propVal.Value
        };

        _dbContext.Add(changeLog);
    }

    await _dbContext.SaveChangesAsync();
    return NoContent();
}

When I want to update an enum I get the InvalidCastException exception.

Payload:

{
  "propertyValues": [
    {
      "propertyName": "WorkingLevel",
      "value": "1"
    }
  ]
}

Response: "1 is not a valid value for WorkingLevel"

The code works fine for numeric and string types, but I cannot update the enum properties.

Is there any way to fix this?





Aucun commentaire:

Enregistrer un commentaire