gpt4 book ai didi

c# - 如何在 asp.net core 中将 json 请求正文验证为有效的 json

转载 作者:太空宇宙 更新时间:2023-11-03 20:51:10 25 4
gpt4 key购买 nike

在asp.net core 2.1中,当一个controller action设置为:

    [HttpPost]
public JsonResult GetAnswer(SampleModel question)
{
return Json(question.Answer);
}

其中 SampleModel 定义为:

public class SampleModel
{
[Required]
public string Question { get; set; }

public string Answer { get; set; }
}

这仍然被认为是有效的请求:

{
"question": "some question",
"question": "some question 2",
"answer": "some answer"
}

在 Controller 中我可以看到第二个问题是模型的值并且模型是有效的。

问题是如何在模型绑定(bind)之前将请求正文验证为有效的 JSON?

最佳答案

根据 Timothy Shields's answer ,如果我们有重复的属性键,很难说这将是一个无效的 json。

当使用 ASP.NET Core 2.1 时,它根本不会抛出。

截至 12.0.1 , Newtonsoft.Json有一个DuplicatePropertyNameHandling settings 。如果我们设置 DuplicatePropertyNameHandling.Error 它将抛出并传递一个重复的属性。所以我想出的最简单的方法是创建一个自定义模型 Binder 。我们可以反序列化 JSON 并在它抛出时更改 ModelState。

首先,安装最新的Newtonsoft.Json :

  <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
</ItemGroup>

然后注册一个JsonLoadSettings选项作为单例服务供以后重用:

services.AddSingleton<JsonLoadSettings>(sp =>{
return new JsonLoadSettings {
DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error,
};
});

现在我们可以创建一个自定义模型绑定(bind)器来处理重复的属性:

public class XJsonModelBinder: IModelBinder
{
private JsonLoadSettings _loadSettings;
public XJsonModelBinder(JsonLoadSettings loadSettings)
{
this._loadSettings = loadSettings;
}

public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); }
var modelName = bindingContext.BinderModelName?? "XJson";
var modelType = bindingContext.ModelType;

// create a JsonTextReader
var req = bindingContext.HttpContext.Request;
var raw= req.Body;
if(raw == null){
bindingContext.ModelState.AddModelError(modelName,"invalid request body stream");
return Task.CompletedTask;
}
JsonTextReader reader = new JsonTextReader(new StreamReader(raw));

// binding
try{
var json= (JObject) JToken.Load(reader,this._loadSettings);
var o = json.ToObject(modelType);
bindingContext.Result = ModelBindingResult.Success(o);
}catch(Exception e){
bindingContext.ModelState.AddModelError(modelName,e.ToString()); // you might want to custom the error info
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}

启用读取Request.Body多次,我们还可以创建一个虚拟 Filter :

public class EnableRewindResourceFilterAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Request.EnableRewind();
}
public void OnResourceExecuted(ResourceExecutedContext context) { }
}

最后,用[ModelBinder(typeof(XJsonModelBinder))]修饰action方法和 EnableRewindResourceFilter :

    [HttpPost]
[EnableRewindResourceFilter]
public JsonResult GetAnswer([ModelBinder(typeof(XJsonModelBinder))]SampleModel question)
{
if(ModelState.IsValid){
return Json(question.Answer);
}
else{
// ... deal with invalid state
}
}

演示:

enter image description here

关于c# - 如何在 asp.net core 中将 json 请求正文验证为有效的 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55154252/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com