【发布时间】:2021-09-19 17:09:40
【问题描述】:
我创建了一个全新的 ASP.NET Core 2.1 API 项目,其中包含一个 Data dto 类和这个控制器操作:
[HttpPost]
public ActionResult<Data> Post([FromForm][FromBody] Data data)
{
return new ActionResult<Data>(data);
}
public class Data
{
public string Id { get; set; }
public string Txt { get; set; }
}
它应该将数据回显给用户,没什么特别的。但是,这两个属性中只有一个有效,具体取决于顺序。
这是测试请求:
curl -X POST http://localhost:5000/api/values \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'id=qwer567&txt=text%20from%20x-www-form-urlencoded'
和
curl -X POST http://localhost:5000/api/values \
-H 'Content-Type: application/json' \
-d '{
"id": "abc123",
"txt": "text from application/json"
}'
我尝试了几种方法,都无济于事:
- 创建自定义子
BindingSource,但这似乎只是元数据。 - 使用属性
[CompositeBindingSource(...)],但构造函数是私有的,这可能不是预期用途 - 为此创建一个
IModelBinder和提供程序,但是 (1) 我可能只希望在特定的控制器操作上使用它并且 (2) 看起来确实需要大量工作才能获得两个内部模型绑定器(用于 Body 和 FormCollection)
那么,将FromForm 和FromBody(或者我猜是任何其他来源的组合)属性组合成一个属性的正确方法是什么?
澄清这背后的原因,并解释为什么我的问题不是this question 的重复:我想知道如何使用相同的 URI / Route 来支持两种不同类型的发送数据。 (尽管可能按照某些人的口味,可能包括我自己的口味,不同的路线/uris 可能更合适。)
【问题讨论】:
-
请问您为什么要这样做?我刚刚尝试过 bc 也许我认为你可以省略这两个属性并且它会起作用。表单请求仅适用于 [FromForm],而 json-request 不适用 [FromBody]。
-
因为我想为消费者提供两种调用 API 的方式。 (至少,我认为这就是原因。其他人问过我同样的问题,此时我只想知道是为了知道:D)。 PS。如果我没记错的话,在最近的版本中省略
[FromBody]是可行的,因为它是按照惯例假设的。 -
@Jeroen:你是对的,但仅当
[ApiController]属性应用于控制器时。对于使用该属性修饰的控制器,类参数被假定为隐式[FromBody]。但是,在这种情况下,如果您确实想要这样,则需要应用[FromForm]。 -
这个answer(它是我的)可能有助于解释
[ApiController]方法并拆分@ChrisPratt 在他的回答中建议的两个动作(我已将其标记为可能重复)。 -
在问题的底部查看我的编辑,解释为什么我认为它不是重复的。
标签: c# asp.net-core