简体   繁体   中英

ASP.Net Core Put FromBody request validation - json request contains only one bool field

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.

[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:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM