我有一个用Asp.Net Core编写的简单后端API,它接收一个字符串:
[HttpPost]
public IResult Post([FromBody] string value)
{
//do something with value...
}
我的前端javascript看起来是这样的:
const request = {
method: 'POST',
mode : "cors",
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount, currency })
};
const response = await fetch(link, request);
const data = await response.json();
这似乎很容易,但我得到了以下错误:
"分析值时遇到意外字符:{.Path'',第1行,位置1。">
"值字段是必需的。">
问题出在正文中,它作为JSON对象发送:
{"amount":123,"currency":"eur"}
显然,解析会产生问题
如果使用Postman,我在正文内发送以下字符串:
"{\"amount \":123,\"currency \":\"eur\"}">
一切正常!
如果我通过javascript发送,它不会:(
所以,我的问题是:很明显,c#扰乱了主体中的数据类型。它期望一个字符串,但它正在接收一个JSON(尽管JSON.stringfy生成了一个字符串但不知何故,它似乎被解析回了介于两者之间的JSON(。
我能把C#上的类型改成JSON之类的吗?一切都会自动工作吗?有没有一种方法可以通过javascript发送一个看起来像JSON的字符串,而不需要在两者之间进行这种不必要的转换?
附加信息:
@Strike轻柔的方式不起作用。我收到一条错误消息,说只有一个参数可以与[FromBody]属性一起传递。
@joacoleza方式可能有效,但我希望避免它,因为它会在我的代码中填充数十个描述函数输入的小类。
这是有效的。但我的眼睛流血了:
body:"'" + JSON.stringify({amount, currency}) + "'"
这是传递字符串的最优雅的解决方案吗?
它期望value
有一个string
,但您给了它一个对象。可以更改方法的参数以接受具有amount
和currency
属性的对象,也可以更改方法参数以接受两个同名变量。
[HttpPost]
public IResult Post([FromBody] int amount, [FromBody] string currency)
{
//do something
}
尽管@joacoleza的答案确实有效,但在我的一个案例中它是不可行的(我收到的对象很大(约200个字段(,我只需要提取5个。此外,它可能会经常变化,即使我并没有真正被这些变化所打动,我也必须调整我的对象。
我终于自己找到了解决方案:
如前所述,.Net试图将正文的内容解析为请求的对象:
public ActionResult Post([FromBody] string value)
这需要一个字符串对象。如果我们想发送JSON并解析它,我们可以通过以下方式发送:'{"field":"value", "field2":"value2"}'
但是,如果我们不控制请求中主体的内容,并且我们正在接收一个X对象(或者我们可能想在运行时解析的不同对象(,我们只需要将函数参数的类型更改为JObject:
public ActionResult Post([FromBody] JObject value)
解析后的JObject将包含JSON的整个结构,但它仍然会给我们足够的自由,让我们对原始版本为所欲为,而不必为了转换而将其转换为POCO:var amount = value["amount"];
这就是我想要的。
试着这样做。
发送这样的请求:
const request = {
method: 'POST',
mode : "cors",
headers: { 'Content-Type': 'application/json' },
body: { amount: 100, currency: 'USD' })
};
const response = await fetch(link, request);
const data = await response.json();
并定义一个可以绑定到您发送的主体的类:
public class MyClass
{
public int Amount { get; set; }
public string Currency { get; set; }
}
并使用该类作为POST方法的参数:
[HttpPost]
public IResult Post([FromBody] MyClass data)
{
//do something with value...
}