C# 如何在过滤器的帮助下检查客户端是否发送了有效的JSON?
我有以下要求: 正如您所看到的,它不是一个有效的JSON。即使它不是JSON。这只是一组随机的字母。我想检查一下,客户端不能像以前在我的Web API上那样在屏幕上传递body。如果发生这种情况,我想发送如下邮件:C# 如何在过滤器的帮助下检查客户端是否发送了有效的JSON?,c#,asp.net-mvc,asp.net-core,.net-core,C#,Asp.net Mvc,Asp.net Core,.net Core,我有以下要求: 正如您所看到的,它不是一个有效的JSON。即使它不是JSON。这只是一组随机的字母。我想检查一下,客户端不能像以前在我的Web API上那样在屏幕上传递body。如果发生这种情况,我想发送如下邮件: { "status": "error", "description": "Invalid JSON" } { "status": "error", "description": "Your JSON is invalid, we are sorry (
{
"status": "error",
"description": "Invalid JSON"
}
{
"status": "error",
"description": "Your JSON is invalid, we are sorry ((("
}
因此,我有以下过滤器:
public class MyValidateJson : ActionFilterAttribute
{
public override async void OnActionExecuting(ActionExecutingContext context)
{
// check if json is valid
using StreamReader reader = new StreamReader(context.HttpContext.Request.Body, Encoding.UTF8);
var body = await reader.ReadToEndAsync();
try
{
JToken.Parse(body);
}
catch (JsonReaderException ex)
{
context.Result = new BadRequestObjectResult(new
{
status = "error",
description = "Invalid JSON input"
});
base.OnActionExecuting(context);
}
但我看不懂身体。我总是有空字符串。因此,我总是使用无效的JSON。如何改进过滤器
更新
也许我对这个问题的解释不清楚,我会设法解决的。因此,我想避免这种情况:
正如您所看到的,{”“:[“解析布尔值时出错。路径“”,第1行,位置1。”]}
-是。。。这是给我的客户的什么?对于客户机,它必须类似于:
{
"status": "error",
"description": "Invalid JSON"
}
{
"status": "error",
"description": "Your JSON is invalid, we are sorry ((("
}
但不是{“”:[“分析布尔值时出错。路径“”,第1行,位置1.”}
我有以下控制器:
[Route("/api/v1.0/startup")]
[HttpPost]
public async Task<IActionResult> Update([FromBody] CustomerChangeViewModel viewModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
...
我怎么会有这种行为?我的意思是回答得很好(不是异常文本)。您可以使用
DTO
(数据传输对象)类通过System.ComponentModel.DataAnnotations
接收并验证所需的JSON。
在我的情况下,它是用于帐户注册的:
public class AccountRegisterDTO
{
[Required] // This property is obligatory, it MUST exist in JSON
[MinLength(6, ErrorMessage = "Username must be at least 6 characters long")] // Must be minimum 6 characters long
[RegularExpression(@"^\d*[a-zA-Z][a-zA-Z\d]*$", ErrorMessage = "Username can contain only letters and numbers")] // Must Match the RegEx
public string Username { get; set; }
[Required]
[MinLength(8, ErrorMessage = "Password must be at least 8 characters long")]
[RegularExpression(@"^(?=.*[A-Z])(?=.*[a-z])(?=.*[\d])((?=.*[^\w\s])|(?=.*[ ])).*$", ErrorMessage = "Password don't meet passwords policy")]
public string Password { get; set; }
[Required]
[EmailAddress(ErrorMessage = "Email address is not valid")] // Automatically validate if e-mail address is correct
public string EmailAddress { get; set; }
}
用法非常简单,如下所示:
[HttpPost("Register")]
public async Task<IActionResult> Register([FromBody] AccountRegisterDTO registerAccount)
{
// Code will not even reach this point if JSON is not valid according to DataAnnotations Attributes
}
[HttpPost(“寄存器”)]
公共异步任务寄存器([FromBody]AccountRegisterTo registerAccount)
{
//根据DataAnnotations属性,如果JSON无效,代码甚至不会达到这一点
}
对于传递的参数:
返回的错误如下所示:
[HttpPost("Register")]
public async Task<IActionResult> Register([FromBody] AccountRegisterDTO registerAccount)
{
// Code will not even reach this point if JSON is not valid according to DataAnnotations Attributes
}
问题在于,您没有在操作筛选器中获取请求主体,因此在筛选器中,它没有正确检查Json解析并返回自定义错误。您可以尝试使用以下代码来获取
OnActionExecuting
中的请求正文:
var bodyStr = "";
var req = context.HttpContext.Request;
req.EnableRewind();
req.Body.Position = 0;
using (var stream = new StreamReader(req.Body))
{
bodyStr = stream.ReadToEnd();
}
您应该使用DTO类,将其作为控制器端点中的参数接收。您可以使用DataAnnotations属性自动验证每个属性,并自动返回正确的信息。如果没有人回答,我会在几分钟后发布我的答案。是的,我可以,但是。。。但它只有在传递有效的JSON对象时才起作用。如果我传递了无效的JSON(例如,仅随机字符串),我会将其作为回答异常文本,而不是关于无效JSON的可理解信息。@Genypek我不需要检查过滤器中的字段是否有效。我只想检查JSON是否有效。是的。查看您的更新,我无法提供正确的答案,抱歉。没关系)我也认为DTO(视图模型)和默认验证可以保护我,但它不起作用。我认为,过滤器是个好主意。我说得对吗?还是有办法?谢谢你的回答!但是您的解决方案导致以下异常
System.TypeLoadException:无法加载类型“Microsoft.AspNetCore.Http.Internal.BufferingHelper”
。我尝试了req.enablebuffer()
改为EnableRewind
但它又给了我一个空的正文(你的.net核心版本是什么?//对于ASP.net 2.1,使用context.HttpContext.Request.EnableRewind();//对于ASP.net 3.1,使用context.HttpContext.Request.enablebuffer();@NanYu很幸运,我找到了你的帖子,它回答了我上周的问题。谢谢!=)如果你愿意,请在我的问题中发布你的ASp.NET Core 3.1解决方案,我可以接受你的回答well@NanYu我刚刚注意到,您根本不需要.EnableRewind()
或.enablebuffer()
。可以忽略这一点line@citronas好啊我猜您在startup.cs中添加了扩展方法