ASP.NET Core formularz POST skutkuje odpowiedzią HTTP 415 na nieobsługiwany typ nośnika

173

Wysłanie formularza POST HTTP request ( Content-Type: application/x-www-form-urlencoded) do poniższego kontrolera skutkuje odpowiedzią HTTP 415 Unsupported Media Type .

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

Nagłówki HTTP postu w formularzu:

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

Służyło to do pracy z ASP.NET MVC 5 na platformie .NET 4.6.

Bart Verkoeijen
źródło
nie musisz używać [FromForm] "Prześlij (model MyModel)", aby uzyskać model poprawnie.
hasan

Odpowiedzi:

298

W przypadku formularzy użyj [FromForm]atrybutu zamiast [FromBody]atrybutu.

Poniższy kontroler współpracuje z ASP.NET Core 1.1:

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

Uwaga: [FromXxx]jest wymagana, jeśli kontroler jest oznaczony [ApiController]. W przypadku normalnych kontrolerów widoku można go pominąć.

Bart Verkoeijen
źródło
104

Możesz użyć, [FromBody]ale musisz ustawić Content-Typenagłówek swojego żądania na application/json, tj

Content-Type: application/json
Bjorn Bailleul
źródło
1
Dlatego pytanie konkretnie wspomina o formularzu POST z typem zawartości application/x-www-form-urlencoded. Jak ze <form>strony HTML.
Bart Verkoeijen
To było dla mnie pomocne, ponieważ składałem przedmiot, a nie formularz. Zaakceptowana odpowiedź jest najbardziej poprawna dla PO, który już używał poprawnego typu treści dla [FromForm]. Mimo to cieszę się, że ten też tu był. :)
Ken Lyon
1
To wcale nie odpowiada na pytanie. Pytanie brzmi, jak utworzyć treść formularzy obsługi serwera, a nie jak po prostu powiedzieć wszystkim klientom, aby przestali je wysyłać!
csauve
Czekaj, czy to oznacza, że ​​niemożliwe jest pobranie treści z treści żądania innego niż application/jsonnp. application/text? @BartVerkoeijen jakieś pomysły?
SpiritBob
10

Najpierw musisz określić w nagłówkach Content-Type, na przykład może to być application/json.

Jeśli ustawisz application/jsontyp zawartości, musisz wysłać plik json.

Tak więc w bodyswoim żądaniu nie wyślesz na przykład form-datanie x-www-for-urlencodedtylko pliku rawjson{"Username": "user", "Password": "pass"}

Możesz dostosować przykład do różnych typów treści, w tym do tego, co chcesz wysłać.

Możesz użyć narzędzia takiego jak Postman lub curl, aby się tym bawić.

Gabriel P.
źródło
6

Oprócz dobrych odpowiedzi nie musisz używać [FromForm]formularza do pobierania danych w kontrolerze. Framework automatycznie konwertuje dane formularza na model, jak chcesz. Możesz wdrożyć jak następujące.

[HttpPost]
public async Task<IActionResult> Submit(MyModel model)
{
    //...
}
hasan
źródło
3
Nie to, co widzę.
François
Przetestowałem to i działa, może być inny problem z twoim kodem
hasan
To rozwiązało mój problem. Ajazowałem obiekt FormData z polami i plikami w nim, [FromForm] lub [FromBody] nie działały. Usunąłem je i zadziałało. (Asp.Net MVC Core 2.1 tył, vanilla js przód). Streszczenie tutaj .
Daniel Szabo
Zabawne, kilka miesięcy po moim poprzednim komentarzu - dzisiaj miałem ten sam problem w projekcie AspNetCore 2.2 Web Api i musiałem użyć [FromFrom], aby uruchomić go w kontrolerze WebAPI (patrz odpowiedź @ Bart).
Daniel Szabo
1
Dla mnie miałem [FromQuery]parametr, ale nie określałem Content-Type as application/json- dodając go w moim żądaniu, sprawiłem, że działało to również z parametrem [FromQuery].
Mike Upjohn
5

To jest mój przypadek: działa Środowisko: Kontroler AspNet Core 2.1:

public class MyController
{
    // ...

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

Widok:

<form method="post" asp-controller="MyController" asp-action="Search">
    <input name="MySearchModelProperty" id="MySearchModelProperty" />
    <input type="submit" value="Search" />
</form>
Quang Vu
źródło
2

problem może być spowodowany MVC MW. musisz ustawić formatterType w opcjach MVC:

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
źródło
Gdzie jest dostępna opcja options.UseCustomStringModelBinder ()? Nigdzie nie znalazłem jego dokumentacji.
Fabricio Araujo
0

Odpowiedź „Nieobsługiwany typ multimediów HTTP 415” wynika z Content-Type w nagłówku żądania. na przykład w javascript przez 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
źródło