The MVC framework has to convert JSON to a class for FluentValidation to work.
However, you can configure MVC to validate it first.
To allow the built-in JSON serialiser in any ASP.NET MVC Core app to allow strings to be converted into an enum, you need to add the JsonStringEnumConverter converter in your app startup. This converter also has a parameter you can set to false to disallow integer values. For example:
services
.AddMvc()
.AddJsonOptions(opts =>
{
opts.JsonSerializerOptions.Converters.Add(
new JsonStringEnumConverter(allowIntegerValues: false));
})
Since it seems that '' won't prevent an int being passed in as a string, you can write your own converter. For example, something like this would work:
public class IdentifierTypeConverter : JsonConverter<IdentifierType>{
public override IdentifierType Read(ref Utf8JsonReader reader,
Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();
if(value == null)
{
throw new Exception("No null values thanks!");
}
if(int.TryParse(value, out var _))
{
throw new Exception("No numbers thanks!");
}
return (IdentifierType)Enum.Parse(typeof(IdentifierType), value);
}
public override void Write(Utf8JsonWriter writer, IdentifierType value,
JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
You could make a generic version using a JsonConverterFactory. First make the converter generic:
public class EnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : Enum
{
public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum;
public override TEnum Read(ref Utf8JsonReader reader,
Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();
if (value == null)
{
throw new Exception("No null values thanks!");
}
if (int.TryParse(value, out var _))
{
throw new Exception("No numbers thanks!");
}
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
public override void Write(Utf8JsonWriter writer, TEnum value,
JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
And make your factory:
public class EnumConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum;
public override JsonConverter? CreateConverter(Type typeToConvert,
JsonSerializerOptions options)
{
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(EnumConverter<>).MakeGenericType(typeToConvert))!;
return converter;
}
}
And now add the factory instead:
opts.JsonSerializerOptions.Converters.Add(new EnumConverterFactory());