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

.NET 9 OpenAPI组件抛出System.FormatException问题咨询

问题原因

触发System.FormatException的核心原因是:.NET 9内置OpenAPI组件在处理[Range(1, double.MaxValue)]特性时,错误地将double.MaxValue对应的科学计数法字符串"1.7976931348623157E+308"传入Decimal.Parse方法——而decimal类型的默认解析逻辑不支持科学计数法格式,因此抛出格式错误。

你的Price字段是decimal类型,但Range特性的上限使用了double.MaxValue。当OpenAPI组件生成Schema时,会尝试将Range的上下限转换为与属性类型匹配的数值,这里它把double.MaxValue转成字符串后直接调用Decimal.Parse,最终引发异常。

解决方案

针对你无法使用decimal.MaxValue的限制,提供三种可行方案:

方案1:自定义decimal专属范围验证特性

自己实现一个验证特性,跳过OpenAPI组件的错误类型转换逻辑:

using System.ComponentModel.DataAnnotations;

public class DecimalMinRangeAttribute : ValidationAttribute
{
    private readonly decimal _min;

    public DecimalMinRangeAttribute(int min)
    {
        _min = min;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value is not decimal price)
            return new ValidationResult("Price must be a valid decimal number");

        if (price < _min)
            return new ValidationResult($"Price cannot be less than {_min}");

        // decimal的最大值远小于double.MaxValue,实际业务中不可能超出,无需验证上限
        return ValidationResult.Success;
    }
}

替换原有Range特性:

class MyModel
{
    [DecimalMinRange(1)]
    public decimal Price { get; set; }
}

方案2:修改OpenAPI Schema生成规则

通过自定义Schema过滤器,修正Range特性的处理逻辑:

using Microsoft.AspNetCore.OpenApi;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Schema;

builder.Services.AddOpenApi(options =>
{
    options.SchemaGenerator.ConfigureSchema += (context, schema) =>
    {
        if (context.Type != typeof(decimal)) return;

        var rangeAttr = context.Member?.GetCustomAttributes(typeof(RangeAttribute), false)
            .Cast<RangeAttribute>()
            .FirstOrDefault();

        if (rangeAttr?.Maximum is double max && max == double.MaxValue)
        {
            if (schema is JsonNumberSchema numberSchema)
            {
                // 将上限替换为decimal.MaxValue,避免科学计数法解析错误
                numberSchema.Maximum = decimal.MaxValue;
            }
        }
    };
});

该方案直接修正OpenAPI生成的Schema,既保留原有验证逻辑,又避免解析异常。

方案3:切换到FluentValidation

使用FluentValidation替代DataAnnotations,它的规则更灵活且能被OpenAPI组件正确处理:

  1. 安装NuGet包:FluentValidation.AspNetCore
  2. 注册服务:
builder.Services.AddFluentValidationAutoValidation();
  1. 编写验证规则:
using FluentValidation;

public class MyModelValidator : AbstractValidator<MyModel>
{
    public MyModelValidator()
    {
        RuleFor(m => m.Price)
            .GreaterThanOrEqualTo(1)
            .LessThanOrEqualTo((decimal)double.MaxValue);
    }
}

移除原有[Range]特性即可。

补充说明

decimal.MaxValue的字符串表示为普通数字格式(79228162514264337593543950335),而非科学计数法,因此OpenAPI组件可以正常解析,不会触发异常。

内容的提问来源于stack exchange,提问作者Parsa99

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 03:35:59