[英]ASP.NET Core form POST results in a HTTP 415 Unsupported Media Type response
Sending a form POST HTTP request ( Content-Type: application/x-www-form-urlencoded
) to the below controller results into a HTTP 415 Unsupported Media Type response.将表单 POST HTTP 请求(
Content-Type: application/x-www-form-urlencoded
)发送到以下 controller 会导致HTTP 415 Unsupported Media Type响应。
public class MyController : Controller
{
[HttpPost]
public async Task<IActionResult> Submit([FromBody] MyModel model)
{
//...
}
}
Form post HTTP headers:表单发布 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
This used to work with ASP.NET MVC 5 on .NET 4.6.这曾经在 .NET 4.6 上与 ASP.NET MVC 5 一起使用。
For forms, use the [FromForm]
attribute instead of the [FromBody]
attribute.对于表单,请使用
[FromForm]
属性而不是[FromBody]
属性。
The below controller works with ASP.NET Core 1.1:以下控制器适用于 ASP.NET Core 1.1:
public class MyController : Controller
{
[HttpPost]
public async Task<IActionResult> Submit([FromForm] MyModel model)
{
//...
}
}
Note: [FromXxx]
is required if your controller is annotated with [ApiController]
.注:
[FromXxx]
如果你的控制器与注释的需要[ApiController]
For normal view controllers it can be omitted.对于普通的视图控制器,它可以省略。
您可以使用[FromBody]
但您需要将请求的Content-Type
标头设置为application/json
,即
Content-Type: application/json
First you need to specify in the Headers the Content-Type
, for example, it can be application/json
.首先,您需要在 Headers 中指定
Content-Type
,例如,它可以是application/json
。
If you set application/json
content type, then you need to send a json.如果您设置了
application/json
内容类型,那么您需要发送一个 json。
So in the body
of your request you will send not form-data
, not x-www-for-urlencoded
but a raw
json, for example {"Username": "user", "Password": "pass"}
因此,在您的请求
body
,您将发送的不是form-data
,不是x-www-for-urlencoded
而是raw
json,例如{"Username": "user", "Password": "pass"}
You can adapt the example to various content types, including what you want to send.您可以使示例适应各种内容类型,包括您要发送的内容。
You can use a tool like Postman or curl to play with this.你可以使用像 Postman 或 curl 这样的工具来玩这个。
As addition of good answers, You don't have to use [FromForm]
to get form data in controller.作为补充的好答案,您不必使用
[FromForm]
来获取控制器中的表单数据。 Framework automatically convert form data to model as you wish.框架会根据需要自动将表单数据转换为模型。 You can implement like following.
您可以实现如下。
[HttpPost]
public async Task<IActionResult> Submit(MyModel model)
{
//...
}
This is my case: it's run Environment: AspNet Core 2.1 Controller:这是我的情况:它运行环境:AspNet Core 2.1 控制器:
public class MyController
{
// ...
[HttpPost]
public ViewResult Search([FromForm]MySearchModel searchModel)
{
// ...
return View("Index", viewmodel);
}
}
View:查看:
<form method="post" asp-controller="MyController" asp-action="Search">
<input name="MySearchModelProperty" id="MySearchModelProperty" />
<input type="submit" value="Search" />
</form>
the problem can because of MVC MW.you must set formatterType in MVC options:问题可能是由于 MVC MW.you 必须在 MVC 选项中设置 formatterType:
services.AddMvc(options =>
{
options.UseCustomStringModelBinder();
options.AllowEmptyInputInBodyModelBinding = true;
foreach (var formatter in options.InputFormatters)
{
if (formatter.GetType() == typeof(SystemTextJsonInputFormatter))
((SystemTextJsonInputFormatter)formatter).SupportedMediaTypes.Add(
Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse("text/plain"));
}
}).AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
Follow the below steps:请按照以下步骤操作:
Add to sending request header Content-Type
field:添加到发送请求头
Content-Type
字段:
axios.post(`/Order/`, orderId, { headers: {'Content-Type': 'application/json'} })
Every data (simple or complex type) sent with axios should be placed without any extra brackets ( axios.post('/Order/', orderId, ...)
).使用 axios 发送的每个数据(简单或复杂类型)都不应放置任何额外的括号(
axios.post('/Order/', orderId, ...)
)。
WARNING!警告! There is one exception for
string
type - stringify it before send ( axios.post('/Order/', JSON.stringify(address), ...)
). string
类型有一个例外 - 在发送之前对其进行string
化( axios.post('/Order/', JSON.stringify(address), ...)
)。
Add method to controller:向控制器添加方法:
[HttpPost] public async Task<IActionResult> Post([FromBody]int orderId) { return Ok(); }
In my case 415 Unsupported Media Types was received since I used new FormData()
and sent it with axios.post(...)
but did not set headers: {content-type: 'multipart/form-data'}
.在我的情况下,收到了 415 Unsupported Media Types,因为我使用了
new FormData()
并使用axios.post(...)
发送了它,但没有设置headers: {content-type: 'multipart/form-data'}
。 I also had to do the same on the server side:我也必须在服务器端做同样的事情:
[Consumes("multipart/form-data")]
public async Task<IActionResult> FileUpload([FromForm] IFormFile formFile) { ... }
With .NET 5
I have a .NET API Controller method that looks like this:使用
.NET 5
我有一个 .NET API 控制器方法,如下所示:
[HttpPost("{rootEntity}/{id}")]
public ActionResult Post(RootEntity rootEntity, int id, [FromBody] string message)
{
...
}
I had this request:我有这个要求:
POST /api/Comment/1/1 HTTP/1.1
Host: localhost:12345
Content-Type: text/plain
Content-Length: 4
test
It resulted in the following Status Code response: 415 Unsupported Media Type它导致以下状态代码响应:415 Unsupported Media Type
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "00-e7ca54e9f313c24699c3ca4697b9363d-be4719bd10735245-00"
}
I then switched to Content-Type: application/json
like the answer from @BjornBailleul says but got this error instead:然后我切换到
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."
]
}
}
Got it working by also encapsulate the string in quotation marks like this: "test"
.通过将字符串封装在引号中来使其工作,如下所示:
"test"
。
Complete working request:完成工作要求:
POST /api/Comment/1/1 HTTP/1.1
Host: localhost:12345
Content-Type: application/json
Content-Length: 6
"test"
"HTTP 415 Unsupported Media Type response" stems from Content-Type in header of your request. “HTTP 415 Unsupported Media Type response”源于请求标头中的Content-Type 。 for example in javascript by axios:
例如在 axios 的 javascript 中:
Axios({
method: 'post',
headers: { 'Content-Type': 'application/json'},
url: '/',
data: data, // an object u want to send
}).then(function (response) {
console.log(response);
});
Another trap of note is making sure you're not decorating controllers with the Consume Attribute as below:另一个值得注意的陷阱是确保您没有使用如下的Consume 属性装饰控制器:
[Produces("application/json")]
[Consumes("application/json")]
public class MyController : Controller
This will fail with a 415 Unsupported Media Type if the upload is NOT JSON.如果上传不是 JSON,这将失败并显示415 Unsupported Media Type 。
A "friend of mine" was recently caught out by this like so:一个“我的朋友”最近被这样发现了:
public class MyFileUploadController : MyCustomController {
}
[Produces("application/json")]
[Consumes("application/json")]
public class MyCustomController : ControllerBase {
}
In my case, I received the HTTP 415 Unsupported Media Type response, since I specified the content type to be TEXT and NOT JSON, so simply changing the type solved the issue.就我而言,我收到了 HTTP 415 Unsupported Media Type 响应,因为我将内容类型指定为 TEXT 而不是 JSON,因此只需更改类型即可解决问题。 Please check the solution in more detail in the following blog post: https://www.howtodevelop.net/article/20/unsupported-media-type-415-in-aspnet-core-web-api
请在以下博客文章中更详细地检查解决方案: https : //www.howtodevelop.net/article/20/unsupported-media-type-415-in-aspnet-core-web-api
In my case, I had a method in my controller which was requiring an input parameter;就我而言,我的控制器中有一个需要输入参数的方法; unfortunately, the caller (an HttpClient) wasn't passing it.
不幸的是,调用者(一个 HttpClient)没有通过它。 Shame on me.
真丢人。
You must specify Encoding and Content Type, for instance:您必须指定编码和内容类型,例如:
var request = new HttpRequestMessage
{
Method = new HttpMethod("POST"),
RequestUri = new Uri(CombineUrl(_baseUrl, _resource))
};
request.Content = new StringContent(contentBody, System.Text.Encoding.UTF8, "application/json");
Use [FromForm]
for traditional HTML form post capture.使用
[FromForm]
进行传统的 HTML 表单后期捕获。 It can be used to capture either a single field value (from the POST HTML data stored in the body of the Http Request)...它可用于捕获单个字段值(来自存储在 Http 请求正文中的 POST HTML 数据)...
[HttpPost]
public string EditByPost([FromForm] string field1)
{
return "Success: " + field1;
}
...or you can capture the full form field set into a C# matching class... ...或者您可以将完整的表单字段集捕获到 C# 匹配 class...
[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; }
}
[FormBody]
works the same but it is a new form, requiring JavaScript and a Form data set formatted in JSON. It also is sent via the Http POST inside the body or payload section of the Request but requires you also send the 'application/json' Content-type plus form fields in JSON format. [FormBody]
工作原理相同,但它是一个新表单,需要 JavaScript 和格式为 JSON 的表单数据集。它也通过 Http POST 在请求的正文或有效负载部分内发送,但还需要您发送 'application/ json' 内容类型加上 JSON 格式的表单字段。 Because regular HTML forms cannot do that yet in 2023, you must use JavaScript tricks.因为常规 HTML forms 在 2023 年还不能做到这一点,所以您必须使用 JavaScript 技巧。
[HttpPost]
public ActionResult EditByPost([FromBody] Form1 form)
{
return new JsonResult(form);
}
To call the JavaScript-JSON [FormBody] WebAPI above, you have to use JavaScript and extract out the form fields from the HTML then send them with the JSON data and JSON content-type to the server:要调用上面的 JavaScript-JSON [FormBody] WebAPI,您必须使用 JavaScript 并从 HTML 中提取表单字段,然后将它们与 JSON 数据和 JSON 内容类型一起发送到服务器:
async function JavaScriptPOST() {
const response = await fetch('https://example.com/editbypost',
{
method: 'POST',
body: JSON.stringify({
formfield1: value,
formfield2: value,
formfield2: value
}),
headers: {
'Content-type':'application/json; charset=UTF-8',
}
}).then(...);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.