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

如何在ASP.NET Core MVC+EF Core应用中输入非整数价格?

产品价格输入验证与绑定问题解决方案

问题描述

我开发了一款产品管理应用,产品列表页的每个产品都配有CRUD按钮。输入整数价格时一切正常,但输入带逗号的价格会触发验证错误:

Product Price field must be a number.
输入带点的价格时,价格值总是被设置为0。此前已在Stack Overflow及其他网站查找过资料。

模型代码

[Table("Products")]
public class Product
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long? ProductID { get; set; }

    [DisplayName("Name")]
    [Required(ErrorMessage = "Name of product is required.")]
    public string ProductName { get; set; } = string.Empty;

    [DisplayName("Price")]
    [Required(ErrorMessage = "Price of product is required.")]
    [Range(0.01, double.MaxValue, ErrorMessage = "Enter a positive price")]
    [DataType(DataType.Currency)]
    [DisplayFormat(DataFormatString = "{0:N}", ApplyFormatInEditMode = true)]
    [Column(TypeName = "decimal(8,2)")]
    public decimal ProductPrice { get; set; }
}

视图代码

<form asp-controller="Product" asp-action="CreateProduct" method="post">
     <div asp-validation-summary="ModelOnly" class="text-danger"></div>
     <div class="form-group">
          <label asp-for="@Model.ProductName" class="control-label"></label>
          <input asp-for="@Model.ProductName" class="form-control" />
          <span asp-validation-for="@Model.ProductName" class="text-danger"></span>
     </div>
     <div class="form-group">
          <label asp-for="@Model.ProductPrice" class="control-label"></label>
          <input asp-for="@Model.ProductPrice" class="form-control" />
          <span asp-validation-for="@Model.ProductPrice" class="text-danger"></span>
     </div>
     <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="submit" class="btn btn-primary">Create</button>
     </div>
</form>

问题原因

这是区域性数字格式不匹配导致的:ASP.NET Core默认可能使用英文区域性(en-US),该区域性用点.作为小数分隔符;而输入的逗号,是部分欧洲区域性(如de-DE、fr-FR)的小数分隔符,导致模型绑定和验证失败。输入点但值变成0,是因为当前请求的区域性无法识别点作为分隔符,绑定错误后默认赋值0。

解决方案

1. 配置全局区域性支持

在Program.cs中设置应用支持多区域性,并允许自动检测请求区域性:

var builder = WebApplication.CreateBuilder(args);

// 配置请求本地化选项
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("de-DE"),
        new CultureInfo("fr-FR"),
        // 添加需要支持的其他区域性
    };

    options.DefaultRequestCulture = new RequestCulture("en-US");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
    // 设置区域性检测优先级
    options.RequestCultureProviders = new List<IRequestCultureProvider>
    {
        new QueryStringRequestCultureProvider(),
        new CookieRequestCultureProvider(),
        new AcceptLanguageHeaderRequestCultureProvider()
    };
});

var app = builder.Build();

// 启用请求本地化中间件(需放在路由中间件之前)
app.UseRequestLocalization();

// 其他中间件配置...
app.Run();

2. 修正模型Range特性类型不匹配

将Range特性中的double.MaxValue替换为decimal.MaxValue,避免decimal与double类型转换带来的问题:

[DisplayName("Price")]
[Required(ErrorMessage = "Price of product is required.")]
[Range(0.01m, decimal.MaxValue, ErrorMessage = "Enter a positive price")]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:N}", ApplyFormatInEditMode = true)]
[Column(TypeName = "decimal(8,2)")]
public decimal ProductPrice { get; set; }

3. 前端输入格式化优化(可选)

添加JavaScript代码,根据浏览器当前语言自动格式化价格输入,提升用户体验:

const priceInput = document.getElementById('ProductPrice');
priceInput.addEventListener('blur', function() {
    const rawValue = this.value.replace(/[^0-9.,]/g, '');
    // 统一转换为数字
    const number = parseFloat(rawValue.replace(',', '.'));
    if (!isNaN(number)) {
        // 根据浏览器语言格式化
        this.value = number.toLocaleString(navigator.language, {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        });
    }
});

4. 强制动作使用特定区域性(可选)

如果不需要多区域性支持,可在控制器动作上强制指定区域性,比如支持逗号分隔的德语区域性:

[HttpPost]
[Culture("de-DE")]
public IActionResult CreateProduct(Product model)
{
    if (ModelState.IsValid)
    {
        // 执行产品保存逻辑
        return RedirectToAction(nameof(Index));
    }
    return View(model);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:29:58