Der POST des ASP.NET Core-Formulars führt zu einer HTTP 415-Antwort auf den nicht unterstützten Medientyp

173

Das Senden einer POST-HTTP-Formularanforderung ( Content-Type: application/x-www-form-urlencoded) an den folgenden Controller führt zu einer nicht unterstützten HTTP 415-Medientypantwort .

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

Formular nach HTTP-Headern:

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

Dies funktionierte früher mit ASP.NET MVC 5 unter .NET 4.6.

Bart Verkoeijen
quelle
Sie müssen nicht [FromForm] "Submit (MyModel model)" verwenden, um das Modell auch korrekt zu erhalten.
Hasan

Antworten:

298

Verwenden Sie für Formulare das [FromForm]Attribut anstelle des [FromBody]Attributs.

Der folgende Controller funktioniert mit ASP.NET Core 1.1:

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

Hinweis: [FromXxx]ist erforderlich, wenn Ihr Controller mit Anmerkungen versehen ist [ApiController]. Bei normalen Ansichtssteuerungen kann dies weggelassen werden.

Bart Verkoeijen
quelle
104

Sie können verwenden, [FromBody]aber Sie müssen den Content-TypeHeader Ihrer Anfrage auf setzen application/json, dh

Content-Type: application/json
Björn Bailleul
quelle
1
Aus diesem Grund wird in der Frage speziell ein POST- Formular mit Inhaltstyp erwähnt application/x-www-form-urlencoded. Wie von einer <form>auf einer HTML-Seite.
Bart Verkoeijen
Dies war hilfreich für mich, da ich ein Objekt und kein Formular eingereicht habe. Die akzeptierte Antwort ist die richtigste für das OP, das bereits den richtigen Inhaltstyp für [FromForm] verwendet hat. Trotzdem bin ich froh, dass dieser auch hier war. :)
Ken Lyon
1
Dies beantwortet die Frage überhaupt nicht. Die Frage ist, wie Sie Serverunterstützungsformulare erstellen und nicht wie Sie allen Ihren Clients sagen, dass sie das Senden beenden sollen!
Csauve
Warten, heißt das es unmöglich ist Inhalt der von einer Anfrage Körper anders aufnehmen als application/json, wie application/text? @ BartVerkoeijen irgendwelche Ideen?
SpiritBob
10

Zuerst müssen Sie in den Headern angeben Content-Type, wie es beispielsweise sein kann application/json.

Wenn Sie den application/jsonInhaltstyp festlegen , müssen Sie einen JSON senden.

So bodysenden Sie in Ihrer Anfrage nicht form-data, x-www-for-urlencodedsondern rawzum Beispiel einen json{"Username": "user", "Password": "pass"}

Sie können das Beispiel an verschiedene Inhaltstypen anpassen, einschließlich der zu sendenden Inhalte.

Sie können ein Werkzeug wie Postman oder Curl verwenden, um damit zu spielen.

Gabriel P.
quelle
6

Als Ergänzung zu guten Antworten müssen Sie keine [FromForm]Formulardaten im Controller abrufen. Framework konvertiert Formulardaten automatisch in ein Modell, wie Sie es wünschen. Sie können wie folgt implementieren.

[HttpPost]
public async Task<IActionResult> Submit(MyModel model)
{
    //...
}
hasan
quelle
3
Nicht was ich sehe.
François
Ich habe es getestet und es hat funktioniert. Es kann ein anderes Problem mit Ihrem Code geben
Hasan
Dies löste mein Problem. Ich habe ein FormData-Objekt mit Feldern und Dateien bearbeitet, [FromForm] oder [FromBody] haben nicht funktioniert. Entfernte sie und es funktionierte. (Asp.Net MVC Core 2.1 hinten, Vanille js vorne). Kern hier .
Daniel Szabo
Witzig, ein paar Monate nach meinem vorherigen Kommentar - heute hatte ich das gleiche Problem im AspNetCore 2.2 Web Api-Projekt und musste [FromFrom] verwenden, um es in einem WebAPI-Controller zum Laufen zu bringen (siehe @ Barts Antwort).
Daniel Szabo
1
Für mich hatte ich einen [FromQuery]Parameter, aber ich habe den Inhaltstyp nicht als angegeben application/json- das Hinzufügen in meiner Anfrage hat dazu geführt, dass dies auch mit dem Parameter [FromQuery] funktioniert.
Mike Upjohn
5

Dies ist mein Fall: Es wird ausgeführt. Umgebung: AspNet Core 2.1 Controller:

public class MyController
{
    // ...

    [HttpPost]
    public ViewResult Search([FromForm]MySearchModel searchModel)
    {
        // ...
        return View("Index", viewmodel);
    }
}

Aussicht:

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

Das Problem kann aufgrund von MVC MW auftreten. Sie müssen formatterType in den MVC-Optionen festlegen:

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;
            });
hamid_reza hobab
quelle
Wo options.UseCustomStringModelBinder () verfügbar ist? Ich habe an keiner Stelle eine Dokumentation darüber gefunden.
Fabricio Araujo
0

"HTTP 415-Antwort für nicht unterstützte Medientypen" stammt von Content-Type im Header Ihrer Anfrage. Zum Beispiel in Javascript von Axios:

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