ASP.NET Core 7 Web API:如何用System.Text.Json拒绝未知JSON属性?
在ASP.NET Core 7 Web API中拒绝含未定义属性的JSON请求
要实现拦截包含模型未定义属性的PUT/POST请求并返回400错误,有两种常用方案,以下是具体实现:
方案一:全局配置(推荐)
通过配置System.Text.Json的序列化选项,让框架在反序列化时自动拒绝含未知属性的JSON并抛出异常,再通过异常处理返回标准化的400错误。
1. 配置JSON序列化选项
在Program.cs中添加控制器时,设置AllowUnknownFields为false,同时保持属性名大小写不敏感匹配(适配示例中请求的name与模型的Name):
var builder = WebApplication.CreateBuilder(args); // 配置控制器及JSON序列化规则 builder.Services.AddControllers() .AddJsonOptions(options => { // 允许大小写不敏感匹配属性 options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; // 拒绝包含未知属性的JSON负载 options.JsonSerializerOptions.AllowUnknownFields = false; }); var app = builder.Build();
2. 配置自定义异常处理(可选)
为了返回更友好的错误信息,添加异常处理中间件捕获JsonException并返回标准化响应:
// 配置异常处理中间件 app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { context.Response.StatusCode = StatusCodes.Status400BadRequest; context.Response.ContentType = "application/json"; var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>(); if (exceptionFeature?.Error is JsonException jsonEx) { await context.Response.WriteAsJsonAsync(new { Message = "请求包含未定义的属性", Detail = jsonEx.Message }); } else { await context.Response.WriteAsJsonAsync(new { Message = "无效的请求内容" }); } }); }); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 模型与控制器示例
模型保持你的定义:
public class Person { public string Name { get; set; } }
控制器示例:
[ApiController] [Route("api/[controller]")] public class PersonsController : ControllerBase { [HttpPost] public IActionResult CreatePerson(Person person) { // 业务逻辑处理 return Ok(person); } }
当请求发送含lastname的JSON时,反序列化会抛出JsonException,中间件捕获后返回400错误及对应提示。
方案二:自定义Action过滤器(针对特定接口)
如果不需要全局生效,仅针对特定接口检查未知属性,可以自定义Action过滤器实现:
1. 实现自定义过滤器
public class RejectUnknownPropertiesAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { var jsonOptions = context.HttpContext.RequestServices.GetRequiredService<IOptions<JsonOptions>>().Value; var request = context.HttpContext.Request; // 仅处理JSON类型的请求 if (!request.ContentType?.Contains("application/json") ?? true) { base.OnActionExecuting(context); return; } // 重置请求流位置,确保能读取 request.Body.Position = 0; var jsonDoc = JsonDocument.Parse(request.Body, new JsonDocumentOptions { AllowTrailingCommas = jsonOptions.JsonSerializerOptions.AllowTrailingCommas }); // 获取当前Action的模型类型 var model = context.ActionArguments.Values.FirstOrDefault(); if (model == null) { base.OnActionExecuting(context); return; } // 收集模型的所有属性名(适配JSON命名策略) var modelProps = model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) .Select(p => jsonOptions.JsonSerializerOptions.PropertyNamingPolicy?.ConvertName(p.Name) ?? p.Name) .ToHashSet(StringComparer.OrdinalIgnoreCase); // 找出JSON中未定义的属性 var unknownProps = jsonDoc.RootElement.EnumerateObject() .Where(prop => !modelProps.Contains(prop.Name)) .Select(prop => prop.Name) .ToList(); if (unknownProps.Any()) { context.ModelState.AddModelError("UnknownProperties", $"请求包含未定义属性:{string.Join(", ", unknownProps)}"); context.Result = new BadRequestObjectResult(context.ModelState); } base.OnActionExecuting(context); } }
2. 在接口上应用过滤器
在需要检查的Action或控制器上添加该特性:
[ApiController] [Route("api/[controller]")] public class PersonsController : ControllerBase { [HttpPost] [RejectUnknownProperties] public IActionResult CreatePerson(Person person) { // 业务逻辑处理 return Ok(person); } }
这样,只有标记了[RejectUnknownProperties]的接口会检查未知属性,不符合要求时返回400错误。
内容的提问来源于stack exchange,提问作者silent
相关产品推荐
相关产品推荐

