2

I'm making a simple API in .net core and am trying to realise a post, where i need to handle an enum value.

I'm using a "SaveProfileResource" for that, which is beeing used by AutoMapper in my Controller class.

what i specifically want is making a post request with a body like this:

{
    "FirstName": "Karl",
    "LastName": "Marx",
    "UserName": "MarxDidNothingWrong69",
    "Gender": "Diverse"
}

where Gender is a Enum.

code looks something like this:

public class SaveProfileResource
{
    [Required]
    [MaxLength(60)]
    public string FirstName { get; set; }

    [Required]
    [MaxLength(60)]
    public string LastName {get; set;}

    [Required]
    [MaxLength(60)]
    public string UserName {get; set;}

    [Required]
    public EGender Gender {get; set;}
}

where EGender looks like this:

public enum EGender
{
    [Description("Male")]
    Male = 1,

    [Description("Female")]
    Female = 2,

    [Description("Diverse")]
    Diverse = 3,
}

and the post method in my controller class:

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody] SaveProfileResource resource){
    if(!ModelState.IsValid){
        return BadRequest(ModelState.GetErrorMessages());
    }
    var profile = mapper.Map<SaveProfileResource, Profile>(resource);
    var result = await profileService.SaveAsync(profile);

    if(!result.Success){
        return BadRequest(result.Message);
    }
    var profileResource = mapper.Map<Profile, ProfileResource>(result.Profile); //displaying the result to the user

    return Ok(profileResource);
}

with my current "raw" implementation im getting a

"The JSON value could not be converted to x.y.z.Models.EGender. Path: "

error. My Question is:

what do i need to do for me to be able to send a request containing the Gender Enum Description.

Alan
  • 949
  • 8
  • 26

2 Answers2

3

try this

[JsonConverter(typeof(StringEnumConverter))]
[Required]
public EGender Gender {get; set;}

for this, you need to install the "Newtonsoft.Json" package. You can do that using Visual Studios NuGet Package UI or if coding using shell:

dotnet add package Newtonsoft.Json

and then using them in your class:

using Newtonsoft.Json; //for JsonConverter
using Newtonsoft.Json.Converters; //for StringEnumConverter

Also don't forget to set this config in your startup.cs/program.cs:

public void ConfigureServices(IServiceCollection services)
 {
     services.AddControllers().AddJsonOptions(opt =>
     {
         opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
     });
 }
JeePakaJP
  • 830
  • 7
  • 21
  • Swagger understands it, but the controller responds with: "title": "One or more validation errors occurred.", "status": 400, "errors": { "$.rating": [ "The JSON value could not be converted to EnumRating. Path: $.rating | LineNumber: 3 | BytePositionInLine: 15." ] } – Oleksii Zhyglov Apr 16 '23 at 20:26
  • Solution: You need to set this config in your startup.cs/progran.cs: public void ConfigureServices(IServiceCollection services) { services.AddControllers().AddJsonOptions(opt => { opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); } https://stackoverflow.com/a/69950478/10679183 thanks @yuriDuque – Oleksii Zhyglov Apr 16 '23 at 20:38
0

Another Soltion is to use a Mapping Profile (not sure if this is the right terminology here) for this.

public class ResourceToModelProfile : Profile
{
    public ResourceToModelProfile()
    {
        CreateMap<SaveProfileResource, Profile>()
            .ForMember(src => src.Gender,
                       opt => opt.MapFrom(src => Enum.Parse(typeof(EGender), src.Gender)));
    }
}

Works like a charm, except i need to be using the actual variable names instead of the descriptions (which in this case isnt making a big difference since both match up)

Alan
  • 949
  • 8
  • 26