передача десятичных дробей в REST API из многоязычного интерфейса - PullRequest
0 голосов
/ 09 ноября 2019

У меня есть REST API в .Net Core 3 и внешний интерфейс в Angular 8. Мой фронт - это многоязычная админ-панель, где мне нужно настроить цену на продукт. Проблема в том, что я не могу получить цену с десятичными значениями.

Моя стандартная культура .NET Core API - это "en-US", но мой клиент использует "nl-NL" из внешнего интерфейса. Как вы знаете, в Нидерландах они используют "," вместо "."поэтому я не получаю цену в представленной модели. Вот фрагменты кода:

REST API

Сущность

public class Product{
  public Guid Id {get;set;}
  public string Name {get;set;}
  public decimal Price {get;set;}
}

Метод контроллера

[HttpPost]
public Task<IActionResult> SaveProduct([FromForm]Product model){
  ....code to save the product....
}

Stratup.cs

services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new List<CultureInfo>
            {
                new CultureInfo("en"),
                new CultureInfo("de"),
                new CultureInfo("fr"),
                new CultureInfo("sv")
            };
            options.RequestCultureProviders = new List<IRequestCultureProvider>()
            {
                new AcceptLanguageHeaderRequestCultureProvider()
            };
            options.FallBackToParentCultures = true;
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });

Я попытался установить для культуры Requestdefault значение "nl", но тогда значения "en" не работают. Может ли кто-нибудь, пожалуйста, помогите мне, как передать десятичные точки из многоязычного интерфейса в REST API.

Спасибо.

Ответы [ 3 ]

0 голосов
/ 10 ноября 2019

Судя по вашему вопросу, похоже, ваша проблема в том, что ваш код переднего плана отправляет цену с запятой. Это возможно только в том случае, если вы отправляете на сервер строковое представление цены, а не числовое значение.

Вам следует изменить свой код переднего плана, чтобы всегда сохранять и передавать значение цены как number. Вы можете управлять отображением цены пользователю в строках, используя Intl.NumberFormat().

. Поскольку пользователю необходимо ввести цену, вы, вероятно, используете тег <input type=text /> для определения стоимости продукта. ,Поскольку мы хотим, чтобы пользователи могли вводить запятые здесь, мы не можем использовать <input type=number /> - вместо этого мы можем просто изменить значение, которое мы получаем из этого входного тега на стороне клиента, заменив вхождения запятых в строке точкой- amount.replace(',', '.') - и затем пытается проанализировать число из строки - parseInt(amount, 10).

Если parseInt возвращает NaN, вы должны отобразить ошибку проверки пользователю.

0 голосов
/ 11 ноября 2019

Если вы используете [FromForm], вы можете создать свой собственный пользовательский механизм связывания мобеля для свойства Price:

1.Создать DecimalModelBinder

public class DecimalModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {

        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (valueProviderResult == null)
        {
            return Task.CompletedTask;
        }

        var value = valueProviderResult.FirstValue;

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

        // Replace commas and remove spaces
        value = value.Replace(",", ".").Trim();

        decimal myValue = 0;
        if (!decimal.TryParse(value, out myValue))
        {
            // Error
            bindingContext.ModelState.TryAddModelError(
                                    bindingContext.ModelName,
                                    "Could not parse MyValue.");
            return Task.CompletedTask;
        }

        bindingContext.Result = ModelBindingResult.Success(myValue);
        return Task.CompletedTask;
    }
}

2.Используйтеэто на Price свойство

public class Product
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    [BindProperty(BinderType = typeof(DecimalModelBinder))]
    public decimal Price { get; set; }
}

3.Action

[HttpPost]
public Task<IActionResult> SaveProduct([FromForm]Product model){
  ....code to save the product....
}
0 голосов
/ 09 ноября 2019

Получение десятичных значений цены от клиента - ужасная идея. Я помню истории, когда случайный разработчик поместил корзину в печенье, , включая цены . Потребовалось не так много времени, чтобы эту ошибку можно было найти и использовать. У компании был счет, потому что они сделали свой магазин неисправным.

Никогда не доверяйте данным пользователя. Особенно, если этот пользователь находится в Интернете.

Что касается конкретной проблемы: у вас в основном есть проблема, связанная с вариациями внешнего интерфейса и внутреннего интерфейса. Я получил 3 совета для передачи чисел между процессами:

  • никогда не передавайте их как строку. Строка, возможно, является вторым худшим форматом для обработки. Единственное, что хуже, это необработанный двоичный файл
  • , если вам нужно передать их в виде строки, убедитесь, что вы выбрали фиксированную культуру и кодировку в обеих конечных точках. Такие вещи, как XML и JSON, как правило, позаботятся об этом за вас. Но вам, возможно, придется выбрать что-то вроде Инвариантная культура .
  • Если вы передаете, сохраняете или получаете DateTime, всегда делайте это в формате UTC. И надеюсь, что у вас нет того редкого приложения, которое должно хранить оригинальный часовой пояс (например, Callendar).
...