json - ASP.Net Core Put FromBody 请求验证 - json 请求仅包含一个 bool 字段
问题描述
我必须确保为 PUT 端点提交的请求包含一个也是唯一一个 bool 类型的元素。请求是 Json 格式,如下所示,可能值为真或假。
{
"canRegister": true
}
下面是Controller中的C#请求对象和对应的方法(端点)。公共类 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)
虽然当请求包含“canRegister”时这完全符合我的预期,但我面临的问题是当请求不包含“canRegister”时,C# 的默认序列化仍然导致请求对象包含“canRegister”且为 false价值。
谁能告诉我如何确保这种不正确的 Json 转换不会发生?我尝试使用自定义 ActionFilter 并意识到在调用 OnActionExecuting 方法时发生了不正确的转换。
解决方案
[JsonProperty(Required = Required.Always)]
在 Json.Net 中使用。并且从 asp.net core 3.0 开始已经从 ASP.NET Core 共享框架中移除。
为了满足您的要求,您可以添加 NewtonSoft 支持:
1.安装Microsoft.AspNetCore.Mvc.NewtonsoftJson
包。
2.更新Startup.ConfigureServices
调用AddNewtonsoftJson
。
services.AddControllers()
.AddNewtonsoftJson();
3.更新你的模型:
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; }
}
结果:
如果您仍然想使用System.Text.Json
,您可以自定义 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());
}
}
模型:
[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; }
}
结果:
推荐阅读
- junit5 - junit5中有JunitPlatform.class的替代品吗?
- python - 如何在 Pandas DataFrame 中创建一个新列,该列将基于其他列取值?
- hyperledger-fabric - 频道:我的频道收到发现错误:访问被拒绝
- python - 如何使用额外字段扩展架构 SQLAlchemy
- python - Fedora 33 ROS Noetic 'Could not find Boost (missing:python) (found version "1.73.0")' 错误
- r - 从一个创建多个data.frames - 基于选择向量
- video - 使用 gstreamer 压缩视频文件大小
- count - 选择与另一个值不同的计数不起作用
- javascript - 减少java脚本中的对象数组
- mongodb - 具有多个集合的mongo db事务不起作用