ASP.NET Core dari POST menghasilkan respons HTTP 415 Jenis Media yang Tidak Didukung

173

Mengirim formulir POST HTTP request ( Content-Type: application/x-www-form-urlencoded) ke pengontrol di bawah ini menghasilkan respons HTTP 415 Jenis Media yang Tidak Didukung .

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

Bentuk pos tajuk 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

Ini digunakan untuk bekerja dengan ASP.NET MVC 5 di .NET 4.6.

Bart Verkoeijen
sumber
Anda tidak harus menggunakan [FromForm] "Kirim (model MyModel)" juga mendapatkan model dengan benar.
hasan

Jawaban:

298

Untuk formulir, gunakan [FromForm]atribut alih-alih [FromBody]atribut.

Pengontrol di bawah ini berfungsi dengan ASP.NET Core 1.1:

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

Catatan: [FromXxx]diperlukan jika controller Anda dijelaskan dengan [ApiController]. Untuk pengontrol tampilan normal, ini dapat dihilangkan.

Bart Verkoeijen
sumber
104

Anda dapat menggunakan [FromBody]tetapi Anda perlu mengatur Content-Typeheader permintaan Anda application/json, yaitu

Content-Type: application/json
Bjorn Bailleul
sumber
1
Itu sebabnya pertanyaan secara khusus menyebutkan bentuk POST, dengan tipe konten application/x-www-form-urlencoded. Suka dari <form>pada halaman HTML.
Bart Verkoeijen
Ini bermanfaat bagi saya, karena saya mengirimkan objek, bukan formulir. Jawaban yang diterima adalah yang paling benar untuk OP, yang sudah menggunakan tipe konten yang benar untuk [FromForm]. Tetap saja, aku senang yang ini juga ada di sini. :)
Ken Lyon
1
Ini sama sekali tidak menjawab pertanyaan. Pertanyaannya adalah bagaimana membuat badan formulir dukungan server, bukan bagaimana hanya memberi tahu semua klien Anda untuk berhenti mengirim mereka!
csauve
Tunggu, apakah itu berarti tidak mungkin untuk mengambil konten dari tubuh permintaan yang berbeda dari application/json, seperti application/text? @ BartVerkoeijen ada ide?
SpiritBob
10

Pertama, Anda perlu menentukan di Headers Content-Type, misalnya, bisa application/json.

Jika Anda mengatur application/jsonjenis konten, maka Anda perlu mengirim json.

Jadi dalam bodypermintaan Anda, Anda tidak akan mengirim form-data, x-www-for-urlencodedtetapi rawjson, misalnya{"Username": "user", "Password": "pass"}

Anda dapat menyesuaikan contoh dengan berbagai jenis konten, termasuk apa yang ingin Anda kirim.

Anda dapat menggunakan alat seperti tukang pos atau ikal untuk bermain dengan ini.

Gabriel P.
sumber
6

Sebagai tambahan jawaban yang bagus, Anda tidak harus menggunakan [FromForm]untuk mendapatkan data formulir di controller. Kerangka kerja secara otomatis mengonversi data formulir ke model yang Anda inginkan. Anda dapat menerapkan seperti berikut.

[HttpPost]
public async Task<IActionResult> Submit(MyModel model)
{
    //...
}
hasan
sumber
3
Bukan apa yang saya lihat.
François
Saya telah mengujinya dan ternyata berfungsi, Mungkin ada masalah lain dengan kode Anda
hasan
Ini menyelesaikan masalah saya. Saya sedang memperbaiki objek FormData dengan bidang dan file di dalamnya, [FromForm] atau [FromBody] tidak berfungsi. Dihapus dan berhasil. (Asp.Net MVC Core 2.1 kembali, vanilla js depan). Intinya di sini .
Daniel Szabo
Lucu, beberapa bulan setelah komentar saya sebelumnya - hari ini saya memiliki masalah yang sama dalam proyek AspNetCore 2.2 Web Api, dan saya harus menggunakan [FromFrom] untuk membuatnya bekerja di pengontrol WebAPI (lihat jawaban @ Bart).
Daniel Szabo
1
Bagi saya, saya memiliki [FromQuery]parameter, tetapi saya tidak menentukan Tipe Konten sebagai application/json- menambahkan bahwa dalam permintaan saya, membuat ini berfungsi dengan parameter [FromQuery] juga.
Mike Upjohn
5

Ini adalah kasus saya: dijalankan Lingkungan: AspNet Core 2.1 Controller:

public class MyController
{
    // ...

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

Melihat:

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

masalahnya bisa karena MVC MW. Anda harus mengatur formatterType dalam opsi 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
sumber
Di mana opsi. GunakanCustomStringModelBinder () tersedia ?? Saya tidak menemukan dokumentasi di tempat mana pun.
Fabricio Araujo
0

"HTTP 415 Respons Jenis Media yang Tidak Didukung" berasal dari Content-Type di header permintaan Anda. misalnya dalam javascript oleh 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
sumber