C# 如何在过滤器的帮助下检查客户端是否发送了有效的JSON?

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 (

我有以下要求:

正如您所看到的,它不是一个有效的JSON。即使它不是JSON。这只是一组随机的字母。我想检查一下,客户端不能像以前在我的Web API上那样在屏幕上传递body。如果发生这种情况,我想发送如下邮件:

{
    "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中添加了扩展方法