3 回答

TA貢獻1735條經驗 獲得超5個贊
您可能能夠通過自定義實現您正在尋找的內容IActionConstraint:
從概念上講,IActionConstraint 是一種重載形式,但它不是重載具有相同名稱的方法,而是在匹配相同 URL 的操作之間進行重載。
我對此進行了一些嘗試,并提出了以下IActionConstraint實現:
public class FormContentTypeAttribute : Attribute, IActionConstraint
{
public int Order => 0;
public bool Accept(ActionConstraintContext ctx) =>
ctx.RouteContext.HttpContext.Request.HasFormContentType;
}
如您所見,它非常簡單——它只是檢查傳入的 HTTP 請求是否屬于表單內容類型。為了使用它,您可以歸因于相關操作。這是一個完整的示例,其中還包含此答案中建議的想法,但使用您的操作:
[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],但我已經在示例中明確包含了它。
也來自文檔:
...帶有 IActionConstraint 的動作總是被認為比沒有的動作更好。
這意味著當傳入的請求不是表單內容類型時,FormContentType我顯示的屬性將排除該特定操作,因此使用PostFromBody. 否則,如果它是表單內容類型,則該PostFromForm操作將獲勝,因為它被“認為更好”。
我已經在相當基本的水平上對此進行了測試,它似乎確實可以滿足您的需求??赡苡行┣闆r下它不太合適,所以我鼓勵你玩玩它,看看你可以用它去哪里。我完全希望您可能會發現它完全倒塌的情況,但仍然是一個值得探索的有趣想法。
最后,如果您不喜歡必須使用屬性,可以配置一個約定,例如使用反射來查找具有[FromForm]屬性的操作并自動添加約束。這篇關于該主題的優秀文章中有更多詳細信息。

TA貢獻1856條經驗 獲得超11個贊
你不能。一個動作只能接受一個或另一個。為了解決這個問題,您可以簡單地創建多個操作,一個有[FromBody]
一個沒有。它們當然也需要單獨的路由,因為屬性的存在不足以區分重載。但是,您可以將 action 的主體分解為兩個 action 都可以使用的私有方法,至少可以保持 DRY。

TA貢獻1794條經驗 獲得超8個贊
我喜歡接受的答案中提出的解決方案,甚至使用了一段時間,但現在我們有了這個[Consumes]屬性。
你甚至可以將兩者映射到同一個路由 URL,這是個好消息。
[HttpPost]
[Route("/api/Post")] //same route but different "Consumes"
[Consumes("application/x-www-form-urlencoded")]
public ActionResult Post([FromForm] Data data)
{
DoStuff();
}
[HttpPost]
[Route("/api/Post")] //same route but different "Consumes"
[Consumes("application/json")]
public ActionResult PostJson([FromBody] Data data)
{
Post(data); //just call the other action method
}
https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-5.0#define-supported-request-content-types-with-the-consumes-attribute
- 3 回答
- 0 關注
- 1586 瀏覽
添加回答
舉報