我正在尝试进行 PATCH 操作,如果请求正文包含合同中未指定的字段,则应失败。例如,如果我调用此方法:
[HttpPatch("{id}")]
public async Task<ActionResult> PatchResource(
[FromRoute][Required] Guid id,
[FromBody][Required] PatchRequest request) {/* whatever */}
PatchRequest
在哪里
public class PatchRequest
{
public string Name { get; }
public string Address { get; }
public PatchRequest(string name, string address) { Name = name; Address = address; }
}
我想返回400 (Bad Request)
,如果我得到这样的请求正文,可能会有解释
{
"name": "Adam",
"address" "NY City",
"additional": true
}
我想回来
400(错误要求( - 没想到物业"额外">
我知道,如果我在PatchRequest
上设置自定义序列化程序并将MissingMemberHandling
设置为Error
在这种情况下,我可以通过抛出异常轻松获得500 (Internal Server Error)
,但这没有意义,因为这里是请求,而不是服务器。
在PatchRequest
模型中,添加一个 JsonExtensionsData 属性
public class PatchRequest
{
public string Name { get; }
public string Address { get; }
public PatchRequest(string name, string address) { Name = name; Address = address; }
// extra fields
[JsonExtensionData]
private IDictionary<string, JToken> _extraStuff;
}
然后在控制器中,如果_extraStuff不为空,则会收到其他字段。
以下功能将准确返回哪些属性与FromBody
中定义的对象不同
创建一个类,例如ValidationBase
在类中,创建一个方法来验证您的对象,例如ValidateModel()
ValidateModel()
- 包含验证的整个逻辑
控制器:(终结点(
[HttpPatch("{id}")]
public async Task<ActionResult> PatchResource([FromRoute][Required] Guid id,
[FromBody][Required] PatchRequest request)
{
string body;
using (var reader = new StreamReader(Request.Body))
{
body = reader.ReadToEnd();
}
validator = new ValidationBase();
string resultValidation = validator.ValidateObject(body, new PatchRequest());
if (resultValidation.Length != 0)
{
return BadRequest(new { error_message = resultValidation });
}
// Content endpoint
return Json(response);
}
验证库:
public class ValidationBase
{
public string ValidateObject(string json, object obj)
{
var dictJSON = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
var listParameterInJSON = dictJSON.Keys.ToHashSet<string>();
listParameterInJSON.ToList().ForEach(x => x = x.ToLower());
var jsonObj = JsonConvert.SerializeObject(obj);
var dictObj = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonObj);
var listParameterInObj = dictObj.Keys.ToList();
listParameterInObj = listParameterInObj.ConvertAll(d => d.ToLower());
listParameterInObj.ToHashSet<string>();
var fields = listParameterInJSON.Except(listParameterInObj);
if (fields.ToList().Count == 0) return "";
var result = "Didn't expect property ";
foreach (var item in fields)
{
result += "'" + item + "'" + " ";
}
return result;
}
}