Reputation: 55
I have to ensure that a request submitted for a PUT endpoint contains one and only element which is of bool type. Request is in Json format, will look as below, with either true or false possible values.
{
"canRegister": true
}
Below is the C# request object and the corresponding method (end-point) in Controller. public class RegistrationRequestViewModel
{
[Required]
[JsonPropertyName("canRegister")]
[JsonProperty(Required = Required.Always)]
[Range(typeof(bool), "false", "true", ErrorMessage = "false or true are only allowed values")]
public bool CanRegister { get; set; }
}
public IActionResult Put([FromBody]RegistrationRequestViewModel request)
While this works exactly as I expect when the request contains the 'canRegister', the problem that I'm facing is when the request does not contain the 'canRegister' C#'s default serialization is still resulting in the request object containing 'canRegister' with false value.
Could anyone please let me know how I can ensure this incorrect Json conversion does not take place? I tried with a custom ActionFilter and realized that the incorrect conversion is happening by the time OnActionExecuting method is invoked.
Upvotes: 1
Views: 1482
Reputation: 36635
[JsonProperty(Required = Required.Always)]
is used in Json.Net.And it has been removed from the ASP.NET Core shared framework since asp.net core 3.0.
To meet your requirement,you could add NewtonSoft support:
1.Install the Microsoft.AspNetCore.Mvc.NewtonsoftJson
package.
2.Update Startup.ConfigureServices
to call AddNewtonsoftJson
.
services.AddControllers()
.AddNewtonsoftJson();
3.Update your model:
public class RegistrationRequestViewModel
{
[Required]
//[JsonPropertyName("canRegister")]
[Newtonsoft.Json.JsonProperty(Required = Newtonsoft.Json.Required.Always,PropertyName = "canRegister")]
[Range(typeof(bool), "false", "true", ErrorMessage = "false or true are only allowed values")]
public bool CanRegister { get; set; }
public string Title { get; set; }
}
Result:
If you still want to use System.Text.Json
,you could custom JsonConverter:
public class RegistrationRequestViewModelJsonConverter : JsonConverter<RegistrationRequestViewModel>
{
public override bool CanConvert(Type typeToConvert)
{
return base.CanConvert(typeToConvert);
}
public override RegistrationRequestViewModel Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
var flag = false;
var model = new RegistrationRequestViewModel();
List<string> list = new List<string>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString();
list.Add(propertyName);
reader.Read();
switch (propertyName)
{
//canRegister and title is the key name you post in json
case "canRegister":
bool canRegister = reader.GetBoolean();
model.CanRegister = canRegister;
flag = true;
break;
case "title":
string title = reader.GetString();
model.Title = title;
flag = true;
break;
}
}
}
if (!list.Contains("canRegister"))
{
throw new JsonException("CanRegister field must be provided");
}
return model;
}
public override void Write(
Utf8JsonWriter writer,
RegistrationRequestViewModel value,
JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
Model:
[JsonConverter(typeof(RegistrationRequestViewModelJsonConverter))]
public class RegistrationRequestViewModel
{
[Required]
[JsonPropertyName("canRegister")]
// [JsonProperty(Required = Required.Always)]
[Range(typeof(bool), "false", "true", ErrorMessage = "false or true are only allowed values")]
public bool CanRegister { get; set; }
public string Title { get; set; }
}
Result:
Upvotes: 1