I'm trying to implement an HttpPost method in an ASP.NET Core Web API project with a [FromBody]
view model and enums. In the past, binding view models with the [FromBody]
attribute worked well.
In my particular scenario, I want to offer a JSON endpoint where I convert a given value into a C# enum with different names. This example should explain what I want to achieve:
public enum WeatherEnum { [EnumMember(Value = "good")] Good, [EnumMember(Value = "bad")] Bad }
Internally, I want to use WeatherEnum.Good
and WeatherEnum.Bad
and the consumer of my endpoint wants to use lowercase values. Therefore, I'm trying to map the values which will be passed in the JSON body to my Enum representation.
I've read about the EnumMember
attribute and StringEnumConverter
. I've created a minimal example from the new ASP.NET Core Web API 3.0 template (You need to add these NuGet packages Microsoft.Extensions.DependencyInjection
, Microsoft.AspNetCore.Mvc.NewtonsoftJson
, and Newtonsoft.Json
)
ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
}).SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddNewtonsoftJson(json =>
{
json.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
services.AddControllers();
}
WheatherForecastController:
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;
namespace WebAPITestEnum.Controllers
{
[ApiController]
[Produces("application/json")]
[Consumes("application/json")]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpPost]
[Route("method")]
public ActionResult<QueryResponseClass> TestMethod([FromBody] QueryRequestClass request)
{
// do something with the request ...
return new QueryResponseClass()
{
Foo = "bar"
};
}
}
public class QueryRequestClass
{
public WeatherEnum Weather { get; set; }
}
public class QueryResponseClass
{
public string Foo { get; set; }
}
[JsonConverter(typeof(StringEnumConverter))]
public enum WeatherEnum
{
[EnumMember(Value = "good")]
Good,
[EnumMember(Value = "bad")]
Bad
}
}
My endpoint is being called from Postman with the following body
{
"Weather": "good"
}
which results in this error:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|245d862e-4ab01d3956be5f60.",
"errors": {
"$.Weather": [
"The JSON value could not be converted to WebAPITestEnum.Controllers.WeatherEnum. Path: $.Weather | LineNumber: 1 | BytePositionInLine: 18."
]
}
}
It feels like I'm only missing one line somewhere. It is possible to use Enums in view models with the FromBody
attribute?