You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:40:17