Bar*_*jen 132 c# asp.net-core-mvc asp.net-core
将表单POST HTTP request(Content-Type: application/x-www-form-urlencoded)发送到以下控制器会导致HTTP 415 Unsupported Media Type响应.
public class MyController : Controller
{
[HttpPost]
public async Task<IActionResult> Submit([FromBody] MyModel model)
{
//...
}
}
Run Code Online (Sandbox Code Playgroud)
表单发布HTTP标头:
POST /submit HTTP/1.1
Host: example.com:1337
Connection: keep-alive
Content-Length: 219
Pragma: no-cache
Cache-Control: no-cache
Origin: https://example.com:1337
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: https://example.com:1337/submit
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8,nl;q=0.6
Run Code Online (Sandbox Code Playgroud)
这曾经用于.NET 4.6上的ASP.NET MVC 5.
Bar*_*jen 228
对于表单,请使用[FromForm]属性而不是[FromBody]属性.
以下控制器适用于ASP.NET Core 1.1:
public class MyController : Controller
{
[HttpPost]
public async Task<IActionResult> Submit([FromForm] MyModel model)
{
//...
}
}
Run Code Online (Sandbox Code Playgroud)
Bjo*_*eul 79
您可以使用[FromBody],但需要将请求的Content-Type标头设置为application/json
喜欢
Content-Type: application/json
Run Code Online (Sandbox Code Playgroud)
Vit*_*kiv 11
new FormData()就我而言,自从我使用并发送axios.post(...)但未设置415 Unsupported Media Types 以来,收到了 415 Unsupported Media Types headers: {content-type: 'multipart/form-data'}。我也必须在服务器端做同样的事情:
[Consumes("multipart/form-data")]
public async Task<IActionResult> FileUpload([FromForm] IFormFile formFile) { ... }
Run Code Online (Sandbox Code Playgroud)
Sto*_*ely 11
当您尝试通过 POST 将表单字段数据发送到 ASP.NET 但使用不接受名称/值对的专用 WebAPI 端点处理程序之一时,这种不受支持的媒体类型错误很常见。[FromBody]是问题所在,并且不接受传统的 HTML5 表单字段名称/值对,但需要通过 JSON 进行 JavaScript POST。请继续阅读...
用于[FromForm]传统的 HTML 表单后期捕获。它可用于从名称-值对(从存储在 Http 请求正文中的 POST HTML 数据)中捕获单个表单字段值,也可用于捕获一批中的所有字段值。但您必须修改每个的 WebAPI C# 方法。
在传统的 HTML 表单字段 POST 到服务器中,提交时,浏览器使用发送到服务器的请求的 Http 正文发送表单的所有名称/值对。因此,提交以下 HTML 并将其方法更改为 POST 将所有字段以纯文本形式发送到服务器:
<form id="form1" name="form1" method="post" action="">
<input type="text" id="field1" name="field1" size="20" value="" /><br />
<input type="text" id="field2" name="field2" size="20" value="" /><br />
<input type="text" id="field3" name="field3" size="20" value="" /><br />
<!-- SEND POST as traditional Name-Value pair. -->
<button id="formbutton" name="formbutton" form="form1" value="submit">Form Submit (POST)</button>
</form>
Run Code Online (Sandbox Code Playgroud)
要仅捕获 ASP.NET WebAPI 中的表单字段值之一,您可以使用以下命令执行以下操作[FromForm]:
[HttpPost]
public string EditByPost([FromForm] string myfield1)
{
return "Success: " + myfield1;
}
Run Code Online (Sandbox Code Playgroud)
...或者您可以使用 C# 匹配对象将所有表单字段捕获为一个集合...
[HttpPost]
public ActionResult EditByPost([FromForm] Form1 form)
{
// Here I am just returning the full set of form fields
// back as a JSON object.
return new JsonResult(form);
}
// Here is the C# Class I created that matches the HTML
// form fields being captured by [FormForm]:
public class Form1
{
public string field1 { get; set; }
public string field2 { get; set; }
public string field3 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
[FromBody]是不同的。[FromBody] 打破了 20 多年来一直以相同方式工作的传统 HTML 表单字段 POST,并使用了不同的东西!
它的工作原理很像[FromForm],但它是一种新设计,需要JavaScript自定义 WebAPI 调用或脚本来发布 JSON 格式的表单数据,并在请求中使用 JSON mime-type 或“Content-Type”Http 标头。它通过请求正文或有效负载部分内的 Http POST 发送,但格式为带有“application/json”内容类型的 JSON,告诉您的 ASP.NET WebAPI Core 端点方法解析 JSON 对象,而不是传统的 HTML 形式名称-值对。
由于常规 HTML4/HTML5 表单无法 POST JSON 或其内容类型,因此您必须使用JavaScript 技巧并在 C# 中装饰您的属性来[FromBody]执行此操作。这就是使用常规 HTML 的人感到困惑的地方。
下面的示例现在正在侦听 JSON 表单数据,而不是名称-值对。它正在这样做并不明显,因为它看起来与[FromForm]版本相同......
[HttpPost]
public ActionResult EditByPost([FromBody] Form1 form)
{
return new JsonResult(form);
}
Run Code Online (Sandbox Code Playgroud)
要将带有 JSON 的表单字段数据发布到[FromBody]上面的 WebAPI,您必须使用JavaScript并手动从 HTML 中提取表单字段,然后将它们与 JSON 数据和 JSON 内容类型一起发送到服务器。大多数现代JavaScript API现在只是绕过 HTML 并存储原始 JSON 数据并将其发送到侦听 WebAPI POST。
下面,我使用新的 ECMAScript/JavaScript 技巧来提取与上面使用的相同的 HTML 表单字段值。然后,我使用 async-await 调用Promise 对象(由fetch包装),手动为侦听服务器添加正确的 JSON 标头内容类型,然后将这个新表单数据包直接 POST 到服务器,绕过 HTML。这可以添加到上面的 HTML 提交按钮作为关闭 HTML 提交过程并使用 JavaScript 的函数:
async function JavaScriptPOST() {
var form = document.getElementById('form1');
var myfield1 = form.querySelector('#field1').value;
var myfield2 = form.querySelector('#field2').value;
var myfield3 = form.querySelector('#field3').value;
const response = await fetch('https://example.com/editbypost',
{
method: 'POST',
body: JSON.stringify({
field1: myfield1,
field2: myfield2,
field2: myfield3
}),
headers: {
'Content-type':'application/json; charset=UTF-8',
}
}).then(...);
}
Run Code Online (Sandbox Code Playgroud)
意识到一件事...传统的 HTML 名称-值 POST 格式仍然是世界各地的主导技术。大多数 HTML 表单仍然使用传统的 POST 名称-值技术来发布数据。像这样的 JavaScript 技巧正在成为新的规范,但它们不会取代原始的 HTML 表单技术,也不会单独通过脚本编写。
但是,当这些技术供应商重写数十年来一直运行的技术堆栈时,了解旧技术的工作原理总是有帮助的。可悲的是,他们并没有让开发人员变得更容易、更快或直观,反而最终让像这张海报这样的人感到困惑。
作为补充的好答案,您不必使用[FromForm]来获取控制器中的表单数据。框架会根据需要自动将表单数据转换为模型。您可以实现如下。
[HttpPost]
public async Task<IActionResult> Submit(MyModel model)
{
//...
}
Run Code Online (Sandbox Code Playgroud)
我有.NET 5一个 .NET API 控制器方法,如下所示:
[HttpPost("{rootEntity}/{id}")]
public ActionResult Post(RootEntity rootEntity, int id, [FromBody] string message)
{
...
}
Run Code Online (Sandbox Code Playgroud)
我有这样的要求:
POST /api/Comment/1/1 HTTP/1.1
Host: localhost:12345
Content-Type: text/plain
Content-Length: 4
test
Run Code Online (Sandbox Code Playgroud)
它导致以下状态代码响应:415 不支持的媒体类型
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "00-e7ca54e9f313c24699c3ca4697b9363d-be4719bd10735245-00"
}
Run Code Online (Sandbox Code Playgroud)
然后我转而Content-Type: application/json喜欢@BjornBailleul 的答案,但收到了这个错误:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-0549e2c73842c249a93c8dc2f817e250-796e99fc0000224d-00",
"errors": {
"$": [
"'test' is an invalid JSON literal. Expected the literal 'true'. Path: $ | LineNumber: 0 | BytePositionInLine: 1."
]
}
}
Run Code Online (Sandbox Code Playgroud)
通过将字符串封装在引号中来使其工作,如下所示:"test"。
完整的工作要求:
POST /api/Comment/1/1 HTTP/1.1
Host: localhost:12345
Content-Type: application/json
Content-Length: 6
"test"
Run Code Online (Sandbox Code Playgroud)
首先,您需要在标题中指定Content-Type,例如,可以为application/json。
如果设置application/json内容类型,则需要发送一个json。
所以在body你的要求,你会送不form-data,不x-www-for-urlencoded,但一个rawJSON,例如{"Username": "user", "Password": "pass"}
您可以使示例适应各种内容类型,包括要发送的内容。
您可以使用Postman或curl等工具来玩这个游戏。
小智 5
This is my case: it's run Environment: AspNet Core 2.1 Controller:
public class MyController
{
// ...
[HttpPost]
public ViewResult Search([FromForm]MySearchModel searchModel)
{
// ...
return View("Index", viewmodel);
}
}
Run Code Online (Sandbox Code Playgroud)
View:
<form method="post" asp-controller="MyController" asp-action="Search">
<input name="MySearchModelProperty" id="MySearchModelProperty" />
<input type="submit" value="Search" />
</form>
Run Code Online (Sandbox Code Playgroud)
请按照以下步骤操作:
添加到发送请求头Content-Type字段:
axios.post(`/Order/`, orderId,
{
headers: {'Content-Type': 'application/json'}
})
Run Code Online (Sandbox Code Playgroud)
使用 axios 发送的每个数据(简单或复杂类型)都不应放置任何额外的括号 ( axios.post('/Order/', orderId, ...))。
警告!type有一个例外string- 在 send() 之前将其字符串化axios.post('/Order/', JSON.stringify(address), ...)。
向控制器添加方法:
[HttpPost]
public async Task<IActionResult> Post([FromBody]int orderId)
{
return Ok();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75605 次 |
| 最近记录: |