ChatGPT解决这个技术问题 Extra ChatGPT

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.

public class MyController : Controller
{
    [HttpPost]
    public async Task<IActionResult> Submit([FromBody] MyModel model)
    {
        //...
    }
}

Form post HTTP headers:

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.

you dont have to use [FromForm] "Submit(MyModel model)" also get the model correctly.

A
Austin Hanson

For forms, use the [FromForm] attribute instead of the [FromBody] attribute.

The below controller works with 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]. For normal view controllers it can be omitted.


S
Shimmy Weitzhandler

You can use [FromBody] but you need to set the Content-Type header of your request to application/json, i.e.

Content-Type: application/json

That's why the question specifically mentions a form POST, with content-type application/x-www-form-urlencoded. Like from a <form> on a HTML page.
This was helpful for me, because I was submitting an object, not a form. The accepted answer is the most correct for the OP, who was already using the correct content type for [FromForm]. Still, I'm glad this one was here too. :)
This does not answer the question at all. Question is how to make server support form bodies, not how to just tell all your clients to stop sending them!
Wait, does that mean it's impossible to ingest content from a request's body different than application/json, like application/text? @BartVerkoeijen any ideas?
G
Gabriel P.

First you need to specify in the Headers the Content-Type, for example, it can be application/json.

If you set application/json content type, then you need to send a 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"}

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.


B
Bernard Vander Beken

As addition of good answers, You don't have to use [FromForm] to get form data in controller. Framework automatically convert form data to model as you wish. You can implement like following.

[HttpPost]
public async Task<IActionResult> Submit(MyModel model)
{
    //...
}

Not what I see.
I have tested it and it was working, There can be another problem with your code
This solved my problem. I was ajaxing a FormData object with fields and files in it, [FromForm] or [FromBody] did not work. Removed them and it worked. (Asp.Net MVC Core 2.1 back, vanilla js front). Gist Here.
For me I had a [FromQuery] parameter, but I wasn't specifying the Content-Type as application/json - adding that in my request, made this work with the [FromQuery] parameter too.
I've updated the accepted answer but both @hasan and @François are correct. The [FromForm] attribute is only required if the Controller is an ApiController.
Q
Quang Vu

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);
    }
}

View:

<form method="post" asp-controller="MyController" asp-action="Search">
    <input name="MySearchModelProperty" id="MySearchModelProperty" />
    <input type="submit" value="Search" />
</form>

V
Vitaly Leskiv

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'}. I also had to do the same on the server side:

[Consumes("multipart/form-data")]
public async Task<IActionResult> FileUpload([FromForm] IFormFile formFile) { ... }

It does not work at this time, I still have a 415 with the [Consumes("multipart/form-data")], without I have null for every parameters :( Why is this so hard to do such a basic thing ..
@moff452 with multipart you have to use custom model binders(if you use custom model), otherwise you'll end up having nulls.
Finally, I didnt need decorators or [FromForm], I just forgot to add {get;set;} to each properties ... Now it works like a charm :)
1
1_bug

Follow the below steps:

Add to sending request header Content-Type field: 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, ...)).

WARNING! There is one exception for string type - stringify it before send (axios.post('/Order/', JSON.stringify(address), ...)).

Add method to controller: [HttpPost] public async Task Post([FromBody]int orderId) { return Ok(); }


O
Ogglas

With .NET 5 I have a .NET API Controller method that looks like this:

[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

{
    "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:

{
    "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".

Complete working request:

POST /api/Comment/1/1 HTTP/1.1
Host: localhost:12345
Content-Type: application/json
Content-Length: 6

"test"

https://i.stack.imgur.com/eatjM.png


If you vote down please say why, hard to improve answers otherwise.
h
hamid_reza hobab

the problem can because of MVC MW.you must set formatterType in MVC options:

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;
            });

Where options.UseCustomStringModelBinder() is available?? I don't found documentation of it in any place.
r
rism

Another trap of note is making sure you're not decorating controllers with the Consume Attribute as below:

[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.

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 {

}

M
Mahdi Jalali

"HTTP 415 Unsupported Media Type response" stems from Content-Type in header of your request. for example in javascript by axios:

Axios({
            method: 'post',
            headers: { 'Content-Type': 'application/json'},
            url: '/',
            data: data,  // an object u want to send
          }).then(function (response) {
            console.log(response);
          });

K
Kristina Cer

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. 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


F
Francesco B.

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. Shame on me.


F
Francisco

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");