Asp Net Core数据绑定中的小数点分隔符问题

时间:2018-11-02 11:34:16

标签: c# asp.net asp.net-mvc asp.net-core

我试图通过[FromForm]属性在AspNet.Core MVC中创建一个对象。

[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
[Route("[action]")]
public async Task<IActionResult> Payments([FromForm]IncomingPayment dataPayment)

我的问题:我的属性Amount从未成功设置,即始终为零。

/// <summary>
/// Объект данных запроса уведомления о поступившем платеже
/// </summary>
public class IncomingPayment
{
    /// <summary>
    /// Сумма поступившего платежа
    /// </summary>
    [Required]
    [BindProperty(Name = "amount", SupportsGet = false)]
    public decimal Amount { get; set; }

}

如何考虑转换为十进制值格式(680.37) 最好使用属性?

2 个答案:

答案 0 :(得分:0)

以这种方式解决了我的问题

/// <summary>
/// Объект данных запроса уведомления о поступившем платеже
/// </summary>
public class IncomingPayment
{
    /// <summary>
    /// Сумма поступившего платежа
    /// </summary>
    public decimal Amount { get; set; }

    /// <summary>
    /// Сумма поступившего платежа в строковом формате
    /// </summary>
    private string _amountAsString;

    /// <summary>
    /// Обертка суммы поступившего платежа в строковом формате
    /// </summary>
    [Required]
    [BindProperty(Name = "amount", SupportsGet = false)]
    public string AmountAsString
    {
        get => _amountAsString;
        set
        {
            _amountAsString = value;

            if (!decimal.TryParse(_amountAsString.Replace('.', Program.PointChar), out var doubleAmount)) return;

            Amount = doubleAmount;
        }
    }
}

好吧,当我启动应用程序时,我得到了系统分隔符

 PointChar = double.TryParse("1,2", out _) ? ',' : '.';

答案 1 :(得分:0)

自定义活页夹是前往此处的方法。这将是一个更通用的解决方案。

自定义活页夹

using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using System;
using System.Globalization;
using System.Threading.Tasks;

namespace CustomBinders
{
    public class DecimalBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Metadata.ModelType == typeof(decimal))
            {
                return new BinderTypeModelBinder(typeof(DecimalBinder));
            }
            if (context.Metadata.ModelType == typeof(decimal?))
            {
                return new BinderTypeModelBinder(typeof(DecimalBinder));
            }

            return null;
        }
    }

    public class DecimalBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));

            }
            var valueResult = bindingContext.ValueProvider
                 .GetValue(bindingContext.ModelName);

            if (valueResult == ValueProviderResult.None)
            {
                return Task.CompletedTask;
            }

            object actualValue = null;
            var culture = CultureInfo.CurrentCulture;

            if (valueResult.FirstValue != string.Empty)
            {
                try
                {
                    // Try with your local culture
                    actualValue = Convert.ToDecimal(valueResult.FirstValue, culture);
                }
                catch (FormatException)
                {
                    try
                    {
                        // Try with your invariant culture
                        actualValue = Convert.ToDecimal(valueResult.FirstValue, CultureInfo.InvariantCulture);
                    }
                    catch (FormatException)
                    {
                        bindingContext.ModelState.TryAddModelError(
                                    bindingContext.ModelName,
                                    "You should provide a valid decimal value");

                        return Task.CompletedTask;
                    }
                }
            }

            bindingContext.Result = ModelBindingResult.Success(actualValue);

            return Task.CompletedTask;
        }
    }
}

并像这样使用它

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // ... rest of configuration
        services.AddMvc( options=>
        {
            // ... rest of configuration
            options.ModelBinderProviders.Insert(0, new DecimalBinderProvider());
        }
    );
}