Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从多语言前端向REST API传递小数_C#_Angular_Asp.net Core_Asp.net Core Webapi - Fatal编程技术网

C# 从多语言前端向REST API传递小数

C# 从多语言前端向REST API传递小数,c#,angular,asp.net-core,asp.net-core-webapi,C#,Angular,Asp.net Core,Asp.net Core Webapi,我在.NETCore3中有一个RESTAPI,在Angular 8中有一个前端。我的前端是一个多语言的管理面板,在这里我需要配置产品的价格。问题是我无法收到带有十进制值的价格 我的.NET核心API的默认区域性是“en-US”,但我的客户端从前端使用“nl-nl”。正如您所知,荷兰使用“,”而不是“,”作为小数点,因此我在提交的模型中没有得到价格。下面是代码片段 RESTAPI 实体 控制器方法 [HttpPost] 公共任务存储产品([FromForm]产品模型){ ..保存产品的代码。。。。

我在.NETCore3中有一个RESTAPI,在Angular 8中有一个前端。我的前端是一个多语言的管理面板,在这里我需要配置产品的价格。问题是我无法收到带有十进制值的价格

我的.NET核心API的默认区域性是“en-US”,但我的客户端从前端使用“nl-nl”。正如您所知,荷兰使用“,”而不是“,”作为小数点,因此我在提交的模型中没有得到价格。下面是代码片段

RESTAPI

实体

控制器方法

[HttpPost]
公共任务存储产品([FromForm]产品模型){
..保存产品的代码。。。。
}
Stratup.cs

services.Configure(选项=>
{
var supportedCultures=新列表
{
新文化信息(“en”),
新文化信息(“de”),
新文化资讯(“fr”),
新文化信息(“sv”)
};
options.RequestCultureProviders=新列表()
{
新的AcceptLanguageHeaderRequestCultureProvider()
};
options.FallBackToParentCultures=true;
options.SupportedCultures=SupportedCultures;
options.supportedCultures=supportedCultures;
});
我尝试将Requestdefault culture设置为“nl”,但“en”值不起作用。任何人都可以帮助我如何将小数点从多语言前端传递到RESTAPI


谢谢。

从客户那里获取价格的十进制值是个糟糕的主意。我记得一个偶然的开发者把购物车放进饼干里的故事,包括价格。没过多久,这个错误就被发现并利用了。公司收到了账单,因为他们把他们的商店弄坏了

永远不要相信用户的输入。特别是如果用户在互联网上

至于具体的问题:您基本上有前端和后端文化不同的问题。对于在进程之间传输数字,我得到了3条建议:

  • 切勿将其作为字符串传输。字符串可以说是第二糟糕的处理格式。唯一更糟糕的是原始二进制文件
  • 如果必须将它们作为字符串传输,请确保在两个端点都选择固定区域性和编码。XML和JSON之类的东西往往会帮你解决这个问题。但是你可能得选一些像这样的东西
  • 如果您正在传输、存储或检索日期时间,请始终以UTC的形式进行。希望您没有那种罕见的必须存储原始时区(如日历)的应用程序

根据您的问题,您的问题似乎是前端代码提交的价格带有逗号。只有将价格的字符串表示形式(而不是数字表示形式)发送到服务器时,才能执行此操作

您应该修改前端代码,以便始终将价格值存储和传输为
数字
。您可以使用
Intl.NumberFormat()
控制以字符串形式向用户显示价格的方式

由于用户必须输入价格,您可能使用了
标记来获取产品的成本。因为我们希望用户能够在这里输入逗号,所以我们不能使用
-相反,我们可以简单地修改从客户端的这个输入标记中获得的值,方法是将字符串中出现的逗号替换为句点-
数量。替换(',','。)
-然后尝试从字符串-
parseInt中解析数字(金额,10)


如果
parseInt
返回
NaN
,则应向用户显示验证错误。

如果使用
[FromForm]
,则可以为
Price
属性创建自己的自定义mobel活页夹:

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.行动

[HttpPost]
public Task<IActionResult> SaveProduct([FromForm]Product model){
  ....code to save the product....
}
[HttpPost]
公共任务存储产品([FromForm]产品模型){
..保存产品的代码。。。。
}

您知道,从URL获取价格肯定会被滥用?就像人们输入0.01的价格一样?@Christopher我发布的是严格键入的数字格式的值,数字格式在不同的文化中是不同的,这意味着0.01是产品价格的正确值,也是0,01。这是由于文化v变量从何处检索价格?基于标记,我假设
SaveProduct
是一个REST API调用,并且您正在接收
application/json
?如果是这种情况,您应该修改角度前端代码以提交一个数字。值的内部表示形式(即成本)可以不同于外部表示(即,如何向用户显示)。您应该将角度形式代码添加到此问题中,这将非常有帮助。是{SaveProduct}是一个REST API调用,但我没有传递json数据,我提交的是formdata。如果我在提交angular之前需要修复数据,我必须在每个HttpPost请求中进行修复。这是我不想要的。这更多的是C#帮助请求,而不是angularWell我是为互联网用户做的,我们知道他们可以做什么。我已经尝试了你提到的两个m方法现在唯一剩下的就是将值作为字符串传递,然后在API中将它们转换成十进制(这不是一个好主意)。“从客户端以价格获取十进制值是一个糟糕的主意。”听起来OP是在设计一个系统,用户可以通过设计来创建产品并指定其价格,所以我认为这不是一个非常有用的建议。@DanPantry,嗯,从来没有考虑过这个选项。但现在你说了,这终于有意义了。好吧,我的文章的其余部分仍然适用。我希望我有一些Angular的知识来编写一些代码。Bu我之所以在这里,只是因为C#标记。不过,你的其余答案是肯定的:1.不要将数字作为字符串传输。它们是数字。字符串对用户来说应该是不透明的
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;
    }
}
public class Product
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    [BindProperty(BinderType = typeof(DecimalModelBinder))]
    public decimal Price { get; set; }
}
[HttpPost]
public Task<IActionResult> SaveProduct([FromForm]Product model){
  ....code to save the product....
}