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

.NET 7 Razor Pages荷兰文化下Decimal/DateTime绑定模型为Null问题

问题原因及解决办法

原因分析

当使用AJAX提交数据时,.NET Razor Pages的模型绑定行为和Form提交存在差异:

  • Form提交时,模型绑定会自动采用当前请求配置的nl-NL区域性,能正常解析荷兰格式的Decimal(如2,01)和DateTime(如30-12-2022)。
  • AJAX提交JSON数据时,默认模型绑定会使用**不变区域性(InvariantCulture)**解析,该区域性不识别逗号作为小数分隔符、dd-MM-yyyy的日期格式,导致这两个字段解析失败,触发模型验证错误,最终整个UpdateModel实例为null。

解决办法

方法1:配置后端模型绑定使用请求区域性

在Program.cs中配置MVC模型绑定规则,强制使用当前请求的区域性解析数据:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        // 注册自定义模型绑定器,优先处理Decimal和DateTime
        options.ModelBinderProviders.Insert(0, new DecimalModelBinderProvider());
        options.ModelBinderProviders.Insert(1, new DateTimeModelBinderProvider());
    })
    .AddViewLocalization()
    .AddDataAnnotationsLocalization();

// 配置请求区域性
var supportedCultures = new[] { new CultureInfo("nl-NL") };
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("nl-NL"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures
});

自定义Decimal模型绑定器示例:

public class DecimalModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.ModelType == typeof(decimal) || context.Metadata.ModelType == typeof(decimal?))
        {
            return new DecimalModelBinder();
        }
        return null;
    }
}

public class DecimalModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == ValueProviderResult.None) return Task.CompletedTask;

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
        var value = valueProviderResult.FirstValue;

        if (string.IsNullOrEmpty(value)) return Task.CompletedTask;

        if (decimal.TryParse(value, NumberStyles.Any, bindingContext.HttpContext.RequestCulture.Culture, out var result))
        {
            bindingContext.Result = ModelBindingResult.Success(result);
        }
        else
        {
            bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, $"无法将值 {value} 转换为Decimal类型");
        }

        return Task.CompletedTask;
    }
}

DateTime模型绑定器可参照上述逻辑,将解析逻辑替换为DateTime.TryParse并使用请求区域性。

方法2:前端转换为不变区域性格式后提交

在AJAX发送前,手动将荷兰格式的数值和日期转换为不变区域性识别的格式:

  • Decimal:把逗号替换为点(如2,01→2.01)
  • DateTime:转换为ISO 8601格式(如30-12-2022→2022-12-30T00:00:00)

示例JS代码:

// 格式化Decimal
function formatDecimal(value) {
    return value.replace(',', '.');
}

// 格式化DateTime(输入为dd-MM-yyyy格式)
function formatDate(dateStr) {
    const [day, month, year] = dateStr.split('-');
    return `${year}-${month}-${day}T00:00:00`;
}

// 构造提交数据
const submitData = {
    Id: 1,
    Quantity: formatDecimal('2,01'),
    Date: formatDate('30-12-2022'),
    // 其他字段...
};

// 发送AJAX请求
$.ajax({
    url: '/YourPage?handler=Update',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify(submitData),
    headers: {
        'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
    },
    success: (res) => {
        // 处理成功逻辑
    }
});

方法3:给模型字段添加格式化注解

在UpdateModel的字段上添加[DisplayFormat]属性,明确指定格式和区域性:

public class UpdateModel
{
    public int Id { get; set; }

    [DisplayFormat(DataFormatString = "{0:N2}", ApplyFormatInEditMode = true, NullDisplayText = "")]
    [DataType(DataType.Currency)]
    public decimal Quantity { get; set; }

    [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
    [DataType(DataType.Date)]
    public DateTime Date { get; set; }

    // 其他字段...
}

同时确保已在Program.cs中启用本地化和区域性配置(同方法1中的请求区域性配置)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 09:30:37