0

I have a .NET Web API and one of my API methods take a 'Status' param.

In my code, I have an enum (MyStatusEnum) with various status values, however, I don't want the user of our API to provide any of those values. Instead, I want them to provide a simpler status value, which ultimately gets mapped to one (or more) of our underlying status enum values.

For example, the user of my API must provide a status value of either 'InProgress' or 'Completed', but I would like model-binding to map 'InProgress' to an array of MyStatusEnum, where the values are considered to be 'InProgress', and likewise for 'Completed'.

public enum MyStatusEnum
{
  StartedStepA = 1, // InProgress
  StartedStepB = 2, // InProgress
  StartedStepC = 3, // InProgress
  FinishedStepA = 4, // Completed
  FinishedStepB = 5, // Completed
  FinishedStepC = 6 // Completed
}

public class ApiInputModel
{
    public MyStatusEnum[] Status {get; set;}
}

So in this example, if they provided a status value of Completed, I'd want my model's MyStatsEnum (array) property to contain FinishedStepA, FinishedStepB & FinishedStepC.

1
  • 1
    Did you take a look at this answer? The solution is to make your serializer map the string value to your enum property. Just attribute your Status property. Commented Jul 12, 2019 at 8:49

2 Answers 2

0

One way you can do this using DTO pattern DTO Pattern and AutoMapper to do the mapping after deserialization. I will sketch the code.

public class ApiInputModel
{
    public MyStatusEnum[] Status {get; set;}
}

public class ApiInputModelDTO
{
    // May be better to add an enum here to validate that the user is only inputting "InProgress" and "Completed".
    public string Status {get; set;}
}

Now create a mapping profile between these two types using AutoMapper (you can do this without AutoMapper, but this library just makes it easier to do):

public class MappingProfile : Profile
{
   this.CreateMap<ApiInputModelDTO, ApiInputModel>().ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status == "Completed" ? new[] { /* your array elements for "Completed" */ } : new[] { /* your array element for "InProgress" */ }))
}

Now in your controller, you can do the mapping:

public class MyController
{
    private readonly IMapper mapper;

    public MyController(IMapper mapper)
    {
       this.mapper = mapper;
    }

    public IActionResult MyMethod(ApiInputModelDTO input)
    {
       var inputModel = this.mapper.Map<ApiInputModel>(input);
       // Do what you want with it...
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0
public class ApiInputModel
{
  public MyStatusEnum Status {get; set;}
 }


[HttpPost]
 public IActionResult Test([FromBody] ApiInputModel model)
 {
        var statuses = Enum.GetNames(typeof(MyStatusEnum)).ToList();

        if (model.Status == MyStatusEnum.FinishedStepC)
        return Ok(statuses.Where(x => x.Contains("FinishedStep")));
        else
         return Ok();
  }

So when tested on Swagger

enter image description here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.