gpt4 book ai didi

c# - 如何在 ASP.NET Core 中结合 FromBody 和 FromForm BindingSource?

转载 作者:行者123 更新时间:2023-11-30 19:08:37 27 4
gpt4 key购买 nike

我创建了一个新的 ASP.NET Core 2.1 API 项目,其中包含一个 Data dto 类和这个 Controller 操作:

[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(...)],但构造函数是私有(private)的,这可能不是预期用途
  • 为此创建一个 IModelBinder 和提供程序,但是 (1) 我可能只希望在特定的 Controller 操作上使用它,并且 (2) 看起来确实需要做很多工作才能获得两个内部模型绑定(bind)器 (用于 Body 和 FormCollection)

那么,将 FromFormFromBody(或者我猜是任何其他源组合)属性合并为一个属性的正确方法是什么?

澄清这背后的原因,并解释为什么我的问题不是 this question 的重复问题:我想知道如何使用相同的 URI/路由来支持两种不同类型的发送数据。 (尽管可能符合某些人的口味,包括我自己的口味,但不同的路线/uris 可能更合适。)

最佳答案

您也许可以通过自定义 IActionConstraint 实现您想要的效果:

Conceptually, IActionConstraint is a form of overloading, but instead of overloading methods with the same name, it's overloading between actions that match the same URL.

我对此进行了一些尝试,并提出了以下 IActionConstraint 实现:

public class FormContentTypeAttribute : Attribute, IActionConstraint
{
public int Order => 0;

public bool Accept(ActionConstraintContext ctx) =>
ctx.RouteContext.HttpContext.Request.HasFormContentType;
}

如您所见,它非常简单 - 它只是检查传入的 HTTP 请求是否属于表单内容类型。为了使用它,您可以对相关操作进行属性化。这是一个完整的示例,其中还包括此 answer 中建议的想法,但使用你的 Action :

[HttpPost]
[FormContentType]
public ActionResult<Data> PostFromForm([FromForm] Data data) =>
DoPost(data);

[HttpPost]
public ActionResult<Data> PostFromBody([FromBody] Data data) =>
DoPost(data);

private ActionResult<Data> DoPost(Data data) =>
new ActionResult<Data>(data);

[FromBody] 在上面是可选的,因为使用了 [ApiController],但我将其包含在示例中以明确显示。

同样来自文档:

...an action with an IActionConstraint is always considered better than an action without.

这意味着当传入请求不是表单内容类型时,我显示的 FormContentType 属性将排除该特定操作,因此使用 PostFromBody .否则,如果它表单内容类型,PostFromForm 操作将获胜,因为它“被认为更好”。

我已经在相当基础的水平上对此进行了测试,它似乎确实可以满足您的需求。可能在某些情况下它不太合适,所以我鼓励您尝试一下,看看可以用到哪里。我完全希望您会发现它完全折叠的情况,但尽管如此,探索它仍然是一个有趣的想法。

最后,如果您不喜欢使用属性,可以配置一个约定,例如使用反射查找具有 [FromForm] 属性的操作并自动添加约束。这个优秀的 post 中有更多详细信息关于这个话题。

关于c# - 如何在 ASP.NET Core 中结合 FromBody 和 FromForm BindingSource?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51673361/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com