ASP。NET核心:[FromBody] vs [FromForm]
当您试图将表单字段数据发送给ASP时,不支持的媒体类型错误很常见。NET通过POST,但使用它的专门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="https://localhost:44347/api/test/edit">
<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>
在ASP. xml中仅捕获一个表单字段值。你可以使用[FromForm]…
[HttpPost]
public string EditByPost([FromForm] string myfield1)
{
return "Success: " + myfield1;
}
...或者你可以捕获所有的表单字段作为一个集合使用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; }
}
奇怪的生物叫[FromBody]
[FromBody] is different. It breaks the traditional HTML form field POST that has worked the same for 20+ years and uses something different! It works much like [FromForm] does, but it is a new design, requiring JavaScript and its form data formatted in JSON with the JSON mime-type or "Content-Type" Http header in the Request that is sent to the server. It is also sent via the Http POST inside the body or payload section of the Request, but formatted as JSON with the 'application/json' Content-type, telling your ASP.NET WebAPI Core endpoint method to parse JSON objects, not traditional HTML form name-value pairs.
因为常规的HTML4/HTML5表单不能POST JSON或其内容类型,你必须使用JavaScript技巧,并在c#中使用[FromBody]装饰你的属性来做到这一点。这就是让使用普通HTML的人感到困惑的地方。
下面的示例现在监听JSON表单数据,而不是名称-值对。这并不是很明显,因为它看起来和[FromForm]版本一样…
[HttpPost]
public ActionResult EditByPost([FromBody] Form1 form)
{
return new JsonResult(form);
}
要将带有JSON的表单字段数据发送到上面的[FromBody] WebAPI,您必须使用JavaScript并手动从HTML中提取表单字段,然后将它们与JSON数据和JSON内容类型一起发送到服务器。现在,大多数现代JavaScript api只是绕过HTML,将原始JSON数据存储并发送到监听的WebAPI POST。
下面,我将使用一个新的ECMAScript/JavaScript技巧来提取上面使用的相同的HTML表单字段值。然后,我使用async-await调用Promise对象(由fetch包装),手动为侦听服务器添加正确的JSON头内容类型,然后绕过HTML直接将这个新表单数据包POST到服务器。这可以添加到上面的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(...);
}
要意识到一件事,HTML仍然是世界上的主导技术。大多数HTML表单仍然使用传统的post名称-值技术发布数据。像这样的JavaScript技巧正在成为新的规范,但它们不会取代原始的HTML表单技术,也不会仅通过脚本来取代。
但是,当这些技术供应商根据几十年来的工作方式重写技术堆栈时,了解旧技术的工作方式总是有帮助的。可悲的是,它们并没有让开发人员更容易、更快或更直观,而是像这张海报一样让人困惑。