Bagikan melalui


Membuat API web dengan ASP.NET Core

ASP.NET Core mendukung pembuatan API web menggunakan pengontrol atau API minimal. Pengontrol dalam suatu API web adalah kelas yang berasal dari ControllerBase. Pengontrol diaktifkan dan dibuang berdasarkan per permintaan.

Artikel ini menguraikan cara menggunakan pengontrol untuk menangani permintaan API web. Untuk informasi tentang membuat API web tanpa pengontrol, lihat Tutorial: Membuat API minimal dengan ASP.NET Core.

Kelas ControllerBase

API web berbasis pengontrol terdiri dari satu kelas pengontrol atau lebih yang berasal dari ControllerBase. Templat proyek API web menyediakan pengontrol pemula:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Pengontrol API Web biasanya harus berasal dari ControllerBase, bukan Controller. Controller berasal dari ControllerBase dan menambahkan dukungan untuk tampilan sehingga cocok untuk menangani halaman web, bukan permintaan API web. Jika pengontrol yang sama harus mendukung tampilan dan API web, ambil dari Controller.

Kelas ControllerBase ini menyediakan banyak properti dan metode yang berguna untuk menangani permintaan HTTP. Misalnya, CreatedAtAction mengembalikan kode status 201:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Tabel berikut berisi contoh metode-metode di ControllerBase.

Metode Catatan
BadRequest Mengembalikan kode status 400.
NotFound Mengembalikan kode status 404.
PhysicalFile Mengembalikan satu file.
TryUpdateModelAsync Memanggil pengikatan model.
TryValidateModel Memanggil validasi model.

Untuk melihat daftar semua metode dan properti yang tersedia, baca ControllerBase.

Atribut

Namespace Microsoft.AspNetCore.Mvc menyediakan atribut yang dapat digunakan untuk mengonfigurasi perilaku pengontrol API web dan metode tindakan. Contoh berikut menggunakan atribut untuk menentukan kata kerja tindakan HTTP yang didukung dan kode status HTTP apa pun yang diketahui sekaligus dapat dikembalikan:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Berikut adalah beberapa contoh atribut yang tersedia.

Atribut Catatan
[Route] Menentukan pola URL untuk suatu pengontrol atau tindakan.
[Bind] Menentukan awalan dan properti yang akan disertakan untuk pengikatan model.
[HttpGet] Mengidentifikasi tindakan yang mendukung kata kerja tindakan HTTP GET.
[Consumes] Menentukan jenis data yang diterima oleh tindakan.
[Produces] Menentukan jenis data yang dikembalikan oleh tindakan.

Untuk mendapatkan daftar berisi atribut yang tersedia, baca Microsoft.AspNetCore.Mvc namespace.

Atribut ApiController

Atribut [ApiController] dapat diterapkan ke kelas pengontrol untuk mengaktifkan perilaku khusus API yang dogmatis berikut:

Atribut di pengontrol tertentu

Atribut [ApiController] dapat diterapkan ke pengontrol tertentu, misalnya dalam contoh berikut dari templat proyek:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Atribut pada sejumlah pengontrol

Salah satu metode untuk menggunakan atribut pada lebih dari satu pengontrol adalah membuat kelas pengontrol dasar kustom yang dianotasikan dengan atribut [ApiController]. Contoh berikut menunjukkan kelas dasar kustom dan suatu pengontrol yang berasal darinya:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase

Atribut pada suatu assembly

Atribut [ApiController] dapat diterapkan ke assembly. Saat atribut [ApiController] diterapkan ke assembly, atribut [ApiController] akan diterapkan ke semua pengontrol di assembly tersebut. Tidak ada cara untuk membatalkan pengontrol individu. Terapkan atribut tingkat assembly ke file Program.cs:

using Microsoft.AspNetCore.Mvc;
[assembly: ApiController]

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Persyaratan perutean atribut

Atribut [ApiController] menjadikan perutean atribut sebagai persyaratan. Contohnya:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Tindakan tidak dapat diakses melalui rute konvensional yang ditentukan oleh UseEndpoints, UseMvc, atau UseMvcWithDefaultRoute.

Respons HTTP 400 otomatis

Atribut [ApiController] membuat kesalahan validasi model memicu respons HTTP 400 secara otomatis. Akibatnya, kode berikut tidak diperlukan dalam suatu metode tindakan:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

ASP.NET Core MVC menggunakan filter tindakan ModelStateInvalidFilter untuk melakukan pemeriksaan awal.

Respons BadRequest default

Jenis respons default untuk respons HTTP 400 adalah ValidationProblemDetails. Isi respons berikut adalah salah satu contoh jenis serial:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

Jenis ValidationProblemDetails:

  • Menghasilkan format yang dapat dibaca mesin untuk menentukan kesalahan dalam respons API web.
  • Sesuai dengan spesifikasi RFC 7807.

Agar respons otomatis dan kustom konsisten, panggil metode ValidationProblem, bukan BadRequest. ValidationProblem mengembalikan objek ValidationProblemDetails serta respons otomatis.

Mencatat respons 400 otomatis

Untuk mencatat respons 400 otomatis, atur properti delegasi InvalidModelStateResponseFactory untuk melakukan pemrosesan kustom. Secara default, InvalidModelStateResponseFactory menggunakan ProblemDetailsFactory untuk membuat instans ValidationProblemDetails.

Contoh berikut menunjukkan cara mengambil instans ILogger<TCategoryName> untuk mencatat informasi mengenai respons 400 otomatis:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
      // To preserve the default behavior, capture the original delegate to call later.
        var builtInFactory = options.InvalidModelStateResponseFactory;

        options.InvalidModelStateResponseFactory = context =>
        {
            var logger = context.HttpContext.RequestServices
                                .GetRequiredService<ILogger<Program>>();

            // Perform logging here.
            // ...

            // Invoke the default behavior, which produces a ValidationProblemDetails
            // response.
            // To produce a custom response, return a different implementation of 
            // IActionResult instead.
            return builtInFactory(context);
        };
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Menonaktifkan respons 400 otomatis

Untuk menonaktifkan perilaku 400 otomatis, atur properti SuppressModelStateInvalidFilter ke true. Tambahkan kode yang disorot berikut:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Inferensi parameter sumber pengikatan

Atribut sumber pengikatan menentukan lokasi nilai parameter tindakan. Berikut adalah atribut sumber pengikatan yang ada:

Atribut Sumber pengikatan
[FromBody] Isi permintaan
[FromForm] Data formulir dalam isi permintaan
[FromHeader] Header permintaan
[FromQuery] Parameter string kueri permintaan
[FromRoute] Data rute dari permintaan saat ini
[FromServices] Layanan permintaan yang dimasukkan sebagai parameter tindakan
[AsParameters] Parameter metode

Peringatan

Jangan menggunakan [FromRoute] saat nilai mungkin berisi %2f (yaitu /). %2f tidak akan dilepaskan ke /. Gunakan [FromQuery] jika nilainya mungkin berisi %2f.

Tanpa atribut [ApiController] atau atribut sumber pengikatan, seperti [FromQuery], runtime ASP.NET Core mencoba menggunakan pengikat model objek yang kompleks. Pengikat model objek kompleks menarik data dari penyedia nilai dalam urutan tertentu.

Dalam contoh berikut, atribut [FromQuery] menunjukkan bahwa nilai parameter discontinuedOnly disediakan dalam string kueri URL permintaan:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

Atribut [ApiController] menerapkan aturan inferensi untuk sumber data default parameter tindakan. Dengan aturan ini, Anda tidak perlu mengidentifikasi sumber pengikatan secara manual dengan menerapkan atribut ke parameter tindakan. Berikut adalah perilaku aturan inferensi sumber pengikatan:

  • [FromServices] disimpulkan untuk parameter jenis kompleks yang terdaftar dalam Kontainer DI.
  • [FromBody] disimpulkan untuk parameter jenis kompleks yang tidak terdaftar dalam Kontainer DI. Pengecualian untuk aturan inferensi [FromBody] adalah jenis bawaan yang kompleks dengan arti khusus, seperti IFormCollection dan CancellationToken. Kode inferensi sumber pengikatan mengabaikan jenis khusus tersebut.
  • [FromForm] disimpulkan untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Ini tidak disimpulkan untuk jenis yang simpel atau ditentukan pengguna.
  • [FromRoute] disimpulkan untuk nama parameter tindakan apa pun yang cocok dengan suatu parameter dalam templat rute. Ketika ada lebih dari satu rute yang cocok dengan parameter tindakan, nilai rute apa pun dianggap [FromRoute].
  • [FromQuery] disimpulkan untuk parameter tindakan lainnya.

Catatan inferensi FromBody

[FromBody] tidak disimpulkan untuk jenis simpel, seperti string atau int. Oleh karena itu, atribut [FromBody] harus digunakan untuk jenis simpel ketika fungsionalitas tersebut diperlukan.

Ketika suatu tindakan memiliki lebih dari satu parameter yang terikat dari isi permintaan, pengecualian akan diterapkan. Misalnya, semua tanda tangan metode tindakan berikut akan menyebabkan pengecualian:

  • [FromBody] disimpulkan pada keduanya karena berjenis kompleks.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • atribut [FromBody] pada satu, disimpulkan di sisi lain karena merupakan jenis kompleks.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • atribut [FromBody] pada keduanya.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Catatan inferensi FromServices

Pengikatan parameter mengikat parameter melalui injeksi dependensi saat jenis tersebut dikonfigurasi sebagai layanan. Artinya, parameter tersebut tidak diperlukan untuk menerapkan atribut [FromServices] secara eksplisit ke suatu parameter. Dalam kode berikut, kedua tindakan mengembalikan waktu:

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    public ActionResult GetWithAttribute([FromServices] IDateTime dateTime) 
                                                        => Ok(dateTime.Now);

    [Route("noAttribute")]
    public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}

Dalam kasus tertentu, DI otomatis dapat menjeda aplikasi yang memiliki suatu jenis dalam DI sekaligus diterima di metode tindakan pengontrol API. Memiliki suatu jenis dalam DI dan sebagai suatu argumen di tindakan pengontrol API bukanlah hal yang umum terjadi.

Guna menonaktifkan inferensi [FromServices] untuk parameter tindakan tunggal, terapkan atribut sumber pengikatan yang diinginkan ke parameter. Misalnya, terapkan atribut [FromBody] ke parameter tindakan yang harus terikat dari isi permintaan.

Untuk menonaktifkan inferensi [FromServices] secara global, atur DisableImplicitFromServicesParameters ke true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddSingleton<IDateTime, SystemDateTime>();

builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

var app = builder.Build();

app.MapControllers();

app.Run();

Jenis diperiksa saat memulai aplikasi dengan IServiceProviderIsService. Tujuannya adalah menentukan apakah tindakan pengontrol API berasal dari DI atau sumber lain.

Mekanisme untuk menyimpulkan sumber pengikatan parameter tindakan Pengontrol Data API menggunakan aturan berikut:

Menonaktifkan aturan inferensi

Untuk menonaktifkan inferensi sumber pengikatan, atur SuppressInferBindingSourcesForParameters ke true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
        options.DisableImplicitFromServicesParameters = true;
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Inferensi permintaan multipart/form-data

Atribut [ApiController] menerapkan aturan inferensi untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Tipe isi permintaan multipart/form-data disimpulkan untuk jenis ini.

Untuk menonaktifkan perilaku default, atur properti SuppressConsumesConstraintForFormFileParameters ke true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Detail masalah untuk kode status kesalahan

MVC mengubah hasil kesalahan (hasil dengan kode status 400 atau lebih tinggi) menjadi hasil dengan ProblemDetails. Jenis ProblemDetails ini didasarkan pada spesifikasi RFC 7807 untuk menampilkan detail kesalahan yang dapat dibaca mesin dalam respons HTTP.

Pertimbangkan kode berikut dalam suatu tindakan pengontrol:

if (pet == null)
{
    return NotFound();
}

Metode NotFound ini membuat kode status HTTP 404 dengan isi ProblemDetails. Contohnya:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001"
}

Menonaktifkan respons ProblemDetails

Pembuatan ProblemDetails otomatis untuk kode status kesalahan dinonaktifkan saat properti SuppressMapClientErrors diatur ke true. Tambahkan kode berikut:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Menentukan jenis konten permintaan yang didukung dengan atribut [Consumes]

Secara default, suatu tindakan mendukung semua jenis konten permintaan yang tersedia. Misalnya, jika aplikasi dikonfigurasi untuk mendukung pemformat inputJSON maupun XML, tindakan mendukung beberapa jenis konten, termasuk application/json dan application/xml.

Dengan atribut [Consumes], suatu tindakan dapat membatasi jenis konten permintaan yang didukung. Terapkan atribut [Consumes] ke suatu tindakan atau pengontrol, yang menentukan satu atau beberapa jenis konten:

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

Dalam kode sebelumnya, tindakan CreateProduct menentukan jenis konten application/xml. Permintaan yang dirutekan ke tindakan ini harus menentukan header Content-Typeapplication/xml. Permintaan yang tidak menentukan header Content-Typeapplication/xml mengakibatkan respons 415 Unsupported Media Type.

Dengan atribut [Consumes] ini, tindakan dapat memengaruhi pilihannya berdasarkan jenis konten permintaan masuk dengan menerapkan batasan jenis. Pertimbangkan contoh berikut:

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

Dalam kode sebelumnya, ConsumesController dikonfigurasi untuk menangani permintaan yang dikirim ke URL https://localhost:5001/api/Consumes. Kedua tindakan pengontrol, PostJson dan PostForm, menangani permintaan POST dengan URL yang sama. Tanpa atribut [Consumes] yang menerapkan batasan jenis, pengecualian kecocokan ambigu akan diterapkan.

Atribut [Consumes] ini diterapkan ke kedua tindakan. Tindakan PostJson menangani permintaan yang dikirim dengan header Content-Typeapplication/json. Tindakan PostForm menangani permintaan yang dikirim dengan header Content-Typeapplication/x-www-form-urlencoded.

Sumber Daya Tambahan:

ASP.NET Core mendukung pembuatan API web menggunakan pengontrol atau API minimal. Pengontrol dalam suatu API web adalah kelas yang berasal dari ControllerBase. Artikel ini menguraikan cara menggunakan pengontrol untuk menangani permintaan API web. Untuk informasi tentang membuat API web tanpa pengontrol, lihat Tutorial: Membuat API minimal dengan ASP.NET Core.

Kelas ControllerBase

API web berbasis pengontrol terdiri dari satu kelas pengontrol atau lebih yang berasal dari ControllerBase. Templat proyek API web menyediakan pengontrol pemula:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Pengontrol API Web biasanya harus berasal dari ControllerBase, bukan Controller. Controller berasal dari ControllerBase dan menambahkan dukungan untuk tampilan sehingga cocok untuk menangani halaman web, bukan permintaan API web. Jika pengontrol yang sama harus mendukung tampilan dan API web, ambil dari Controller.

Kelas ControllerBase ini menyediakan banyak properti dan metode yang berguna untuk menangani permintaan HTTP. Misalnya, CreatedAtAction mengembalikan kode status 201:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Tabel berikut berisi contoh metode-metode di ControllerBase.

Metode Catatan
BadRequest Mengembalikan kode status 400.
NotFound Mengembalikan kode status 404.
PhysicalFile Mengembalikan satu file.
TryUpdateModelAsync Memanggil pengikatan model.
TryValidateModel Memanggil validasi model.

Untuk melihat daftar semua metode dan properti yang tersedia, baca ControllerBase.

Atribut

Namespace Microsoft.AspNetCore.Mvc menyediakan atribut yang dapat digunakan untuk mengonfigurasi perilaku pengontrol API web dan metode tindakan. Contoh berikut menggunakan atribut untuk menentukan kata kerja tindakan HTTP yang didukung dan kode status HTTP apa pun yang diketahui sekaligus dapat dikembalikan:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Berikut adalah beberapa contoh atribut yang tersedia.

Atribut Catatan
[Route] Menentukan pola URL untuk suatu pengontrol atau tindakan.
[Bind] Menentukan awalan dan properti yang akan disertakan untuk pengikatan model.
[HttpGet] Mengidentifikasi tindakan yang mendukung kata kerja tindakan HTTP GET.
[Consumes] Menentukan jenis data yang diterima oleh tindakan.
[Produces] Menentukan jenis data yang dikembalikan oleh tindakan.

Untuk mendapatkan daftar berisi atribut yang tersedia, baca Microsoft.AspNetCore.Mvc namespace.

Atribut ApiController

Atribut [ApiController] dapat diterapkan ke kelas pengontrol untuk mengaktifkan perilaku khusus API yang dogmatis berikut:

Atribut di pengontrol tertentu

Atribut [ApiController] dapat diterapkan ke pengontrol tertentu, misalnya dalam contoh berikut dari templat proyek:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Atribut pada sejumlah pengontrol

Salah satu metode untuk menggunakan atribut pada lebih dari satu pengontrol adalah membuat kelas pengontrol dasar kustom yang dianotasikan dengan atribut [ApiController]. Contoh berikut menunjukkan kelas dasar kustom dan suatu pengontrol yang berasal darinya:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase

Atribut pada suatu assembly

Atribut [ApiController] dapat diterapkan ke assembly. Saat atribut [ApiController] diterapkan ke assembly, atribut [ApiController] akan diterapkan ke semua pengontrol di assembly tersebut. Tidak ada cara untuk membatalkan pengontrol individu. Terapkan atribut tingkat assembly ke file Program.cs:

using Microsoft.AspNetCore.Mvc;
[assembly: ApiController]

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Persyaratan perutean atribut

Atribut [ApiController] menjadikan perutean atribut sebagai persyaratan. Contohnya:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Tindakan tidak dapat diakses melalui rute konvensional yang ditentukan oleh UseEndpoints, UseMvc, atau UseMvcWithDefaultRoute.

Respons HTTP 400 otomatis

Atribut [ApiController] membuat kesalahan validasi model memicu respons HTTP 400 secara otomatis. Akibatnya, kode berikut tidak diperlukan dalam suatu metode tindakan:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

ASP.NET Core MVC menggunakan filter tindakan ModelStateInvalidFilter untuk melakukan pemeriksaan awal.

Respons BadRequest default

Isi respons berikut adalah salah satu contoh jenis serial:

{
  "": [
    "A non-empty request body is required."
  ]
}

Jenis respons default untuk respons HTTP 400 adalah ValidationProblemDetails. Isi respons berikut adalah salah satu contoh jenis serial:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

Jenis ValidationProblemDetails:

  • Menghasilkan format yang dapat dibaca mesin untuk menentukan kesalahan dalam respons API web.
  • Sesuai dengan spesifikasi RFC 7807.

Agar respons otomatis dan kustom konsisten, panggil metode ValidationProblem, bukan BadRequest. ValidationProblem mengembalikan objek ValidationProblemDetails serta respons otomatis.

Mencatat respons 400 otomatis

Untuk mencatat respons 400 otomatis, atur properti delegasi InvalidModelStateResponseFactory untuk melakukan pemrosesan kustom. Secara default, InvalidModelStateResponseFactory menggunakan ProblemDetailsFactory untuk membuat instans ValidationProblemDetails.

Contoh berikut menunjukkan cara mengambil instans ILogger<TCategoryName> untuk mencatat informasi mengenai respons 400 otomatis:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
      // To preserve the default behavior, capture the original delegate to call later.
        var builtInFactory = options.InvalidModelStateResponseFactory;

        options.InvalidModelStateResponseFactory = context =>
        {
            var logger = context.HttpContext.RequestServices
                                .GetRequiredService<ILogger<Program>>();

            // Perform logging here.
            // ...

            // Invoke the default behavior, which produces a ValidationProblemDetails
            // response.
            // To produce a custom response, return a different implementation of 
            // IActionResult instead.
            return builtInFactory(context);
        };
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Menonaktifkan respons 400 otomatis

Untuk menonaktifkan perilaku 400 otomatis, atur properti SuppressModelStateInvalidFilter ke true. Tambahkan kode yang disorot berikut:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Inferensi parameter sumber pengikatan

Atribut sumber pengikatan menentukan lokasi nilai parameter tindakan. Berikut adalah atribut sumber pengikatan yang ada:

Atribut Sumber pengikatan
[FromBody] Isi permintaan
[FromForm] Data formulir dalam isi permintaan
[FromHeader] Header permintaan
[FromQuery] Parameter string kueri permintaan
[FromRoute] Data rute dari permintaan saat ini
[FromServices] Layanan permintaan yang dimasukkan sebagai parameter tindakan

Peringatan

Jangan menggunakan [FromRoute] saat nilai mungkin berisi %2f (yaitu /). %2f tidak akan dilepaskan ke /. Gunakan [FromQuery] jika nilainya mungkin berisi %2f.

Tanpa atribut [ApiController] atau atribut sumber pengikatan, seperti [FromQuery], runtime ASP.NET Core mencoba menggunakan pengikat model objek yang kompleks. Pengikat model objek kompleks menarik data dari penyedia nilai dalam urutan tertentu.

Dalam contoh berikut, atribut [FromQuery] menunjukkan bahwa nilai parameter discontinuedOnly disediakan dalam string kueri URL permintaan:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

Atribut [ApiController] menerapkan aturan inferensi untuk sumber data default parameter tindakan. Dengan aturan ini, Anda tidak perlu mengidentifikasi sumber pengikatan secara manual dengan menerapkan atribut ke parameter tindakan. Berikut adalah perilaku aturan inferensi sumber pengikatan:

  • [FromBody] disimpulkan untuk parameter jenis kompleks yang tidak terdaftar dalam Kontainer DI. Pengecualian untuk aturan inferensi [FromBody] adalah jenis bawaan yang kompleks dengan arti khusus, seperti IFormCollection dan CancellationToken. Kode inferensi sumber pengikatan mengabaikan jenis khusus tersebut.
  • [FromForm] disimpulkan untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Ini tidak disimpulkan untuk jenis yang simpel atau ditentukan pengguna.
  • [FromRoute] disimpulkan untuk nama parameter tindakan apa pun yang cocok dengan suatu parameter dalam templat rute. Ketika ada lebih dari satu rute yang cocok dengan parameter tindakan, nilai rute apa pun dianggap [FromRoute].
  • [FromQuery] disimpulkan untuk parameter tindakan lainnya.

Catatan inferensi FromBody

[FromBody] tidak disimpulkan untuk jenis simpel, seperti string atau int. Oleh karena itu, atribut [FromBody] harus digunakan untuk jenis simpel ketika fungsionalitas tersebut diperlukan.

Ketika suatu tindakan memiliki lebih dari satu parameter yang terikat dari isi permintaan, pengecualian akan diterapkan. Misalnya, semua tanda tangan metode tindakan berikut akan menyebabkan pengecualian:

  • [FromBody] disimpulkan pada keduanya karena berjenis kompleks.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • atribut [FromBody] pada satu, disimpulkan di sisi lain karena merupakan jenis kompleks.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • atribut [FromBody] pada keduanya.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Menonaktifkan aturan inferensi

Untuk menonaktifkan inferensi sumber pengikatan, atur SuppressInferBindingSourcesForParameters ke true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Inferensi permintaan multipart/form-data

Atribut [ApiController] menerapkan aturan inferensi untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Tipe isi permintaan multipart/form-data disimpulkan untuk jenis ini.

Untuk menonaktifkan perilaku default, atur properti SuppressConsumesConstraintForFormFileParameters ke true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Detail masalah untuk kode status kesalahan

MVC mengubah hasil kesalahan (hasil dengan kode status 400 atau lebih tinggi) menjadi hasil dengan ProblemDetails. Jenis ProblemDetails ini didasarkan pada spesifikasi RFC 7807 untuk menampilkan detail kesalahan yang dapat dibaca mesin dalam respons HTTP.

Pertimbangkan kode berikut dalam suatu tindakan pengontrol:

if (pet == null)
{
    return NotFound();
}

Metode NotFound ini membuat kode status HTTP 404 dengan isi ProblemDetails. Contohnya:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001"
}

Menonaktifkan respons ProblemDetails

Pembuatan ProblemDetails otomatis untuk kode status kesalahan dinonaktifkan saat properti SuppressMapClientErrors diatur ke true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Menentukan jenis konten permintaan yang didukung dengan atribut [Consumes]

Secara default, suatu tindakan mendukung semua jenis konten permintaan yang tersedia. Misalnya, jika aplikasi dikonfigurasi untuk mendukung pemformat inputJSON maupun XML, tindakan mendukung beberapa jenis konten, termasuk application/json dan application/xml.

Dengan atribut [Consumes], suatu tindakan dapat membatasi jenis konten permintaan yang didukung. Terapkan atribut [Consumes] ke suatu tindakan atau pengontrol, yang menentukan satu atau beberapa jenis konten:

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

Dalam kode sebelumnya, tindakan CreateProduct menentukan jenis konten application/xml. Permintaan yang dirutekan ke tindakan ini harus menentukan header Content-Typeapplication/xml. Permintaan yang tidak menentukan header Content-Typeapplication/xml mengakibatkan respons 415 Unsupported Media Type.

Dengan atribut [Consumes] ini, tindakan dapat memengaruhi pilihannya berdasarkan jenis konten permintaan masuk dengan menerapkan batasan jenis. Pertimbangkan contoh berikut:

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

Dalam kode sebelumnya, ConsumesController dikonfigurasi untuk menangani permintaan yang dikirim ke URL https://localhost:5001/api/Consumes. Kedua tindakan pengontrol, PostJson dan PostForm, menangani permintaan POST dengan URL yang sama. Tanpa atribut [Consumes] yang menerapkan batasan jenis, pengecualian kecocokan ambigu akan diterapkan.

Atribut [Consumes] ini diterapkan ke kedua tindakan. Tindakan PostJson menangani permintaan yang dikirim dengan header Content-Typeapplication/json. Tindakan PostForm menangani permintaan yang dikirim dengan header Content-Typeapplication/x-www-form-urlencoded.

Sumber Daya Tambahan:

ASP.NET Core mendukung pembuatan RESTlayanan penuh, yang juga dikenal sebagai web API web, menggunakan C#. Untuk menangani permintaan, API web menggunakan pengontrol. Pengontrol dalam suatu API web adalah kelas yang berasal dari ControllerBase. Artikel ini menguraikan cara menggunakan pengontrol untuk menangani permintaan API web.

Melihat atau mengunduh kode sampel. (Cara mengunduh).

Kelas ControllerBase

API web terdiri dari satu atau beberapa kelas pengontrol yang berasal dari ControllerBase. Templat proyek API web menyediakan pengontrol pemula:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Jangan membuat pengontrol API web yang berasal dari kelas Controller. Controller berasal dari ControllerBase dan menambahkan dukungan untuk tampilan sehingga cocok untuk menangani halaman web, bukan permintaan API web. Ada pengecualian untuk aturan ini: jika Anda berencana menggunakan pengontrol yang sama untuk tampilan dan API web, ambil dari Controller.

Kelas ControllerBase ini menyediakan banyak properti dan metode yang berguna untuk menangani permintaan HTTP. Misalnya, ControllerBase.CreatedAtAction mengembalikan kode status 201:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Berikut adalah beberapa contoh metode lainnya yang disediakan oleh ControllerBase.

Metode Catatan
BadRequest Mengembalikan kode status 400.
NotFound Mengembalikan kode status 404.
PhysicalFile Mengembalikan satu file.
TryUpdateModelAsync Memanggil pengikatan model.
TryValidateModel Memanggil validasi model.

Untuk melihat daftar semua metode dan properti yang tersedia, baca ControllerBase.

Atribut

Namespace Microsoft.AspNetCore.Mvc menyediakan atribut yang dapat digunakan untuk mengonfigurasi perilaku pengontrol API web dan metode tindakan. Contoh berikut menggunakan atribut untuk menentukan kata kerja tindakan HTTP yang didukung dan kode status HTTP apa pun yang diketahui sekaligus dapat dikembalikan:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Berikut adalah beberapa contoh atribut yang tersedia.

Atribut Catatan
[Route] Menentukan pola URL untuk suatu pengontrol atau tindakan.
[Bind] Menentukan awalan dan properti yang akan disertakan untuk pengikatan model.
[HttpGet] Mengidentifikasi tindakan yang mendukung kata kerja tindakan HTTP GET.
[Consumes] Menentukan jenis data yang diterima oleh tindakan.
[Produces] Menentukan jenis data yang dikembalikan oleh tindakan.

Untuk mendapatkan daftar berisi atribut yang tersedia, baca Microsoft.AspNetCore.Mvc namespace.

Atribut ApiController

Atribut [ApiController] dapat diterapkan ke kelas pengontrol untuk mengaktifkan perilaku khusus API yang dogmatis berikut:

Atribut di pengontrol tertentu

Atribut [ApiController] dapat diterapkan ke pengontrol tertentu, misalnya dalam contoh berikut dari templat proyek:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Atribut pada sejumlah pengontrol

Salah satu metode untuk menggunakan atribut pada lebih dari satu pengontrol adalah membuat kelas pengontrol dasar kustom yang dianotasikan dengan atribut [ApiController]. Contoh berikut menunjukkan kelas dasar kustom dan suatu pengontrol yang berasal darinya:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase

Atribut pada suatu assembly

Atribut [ApiController] dapat diterapkan ke assembly. Anotasi dengan cara ini menerapkan perilaku API web untuk semua pengontrol di assembly. Tidak ada cara untuk membatalkan pengontrol individu. Terapkan atribut tingkat assembly ke deklarasi namespace layanan di sekitar kelas Startup:

[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

Persyaratan perutean atribut

Atribut [ApiController] menjadikan perutean atribut sebagai persyaratan. Contohnya:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Tindakan tidak dapat diakses melalui rute konvensional yang ditentukan oleh UseEndpoints, UseMvc, atau UseMvcWithDefaultRoute di Startup.Configure.

Respons HTTP 400 otomatis

Atribut [ApiController] membuat kesalahan validasi model memicu respons HTTP 400 secara otomatis. Akibatnya, kode berikut tidak diperlukan dalam suatu metode tindakan:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

ASP.NET Core MVC menggunakan filter tindakan ModelStateInvalidFilter untuk melakukan pemeriksaan awal.

Respons BadRequest default

Isi permintaan berikut adalah salah satu contoh jenis serial:

{
  "": [
    "A non-empty request body is required."
  ]
}

Jenis respons default untuk respons HTTP 400 adalah ValidationProblemDetails. Isi permintaan berikut adalah salah satu contoh jenis serial:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

Jenis ValidationProblemDetails:

  • Menghasilkan format yang dapat dibaca mesin untuk menentukan kesalahan dalam respons API web.
  • Sesuai dengan spesifikasi RFC 7807.

Agar respons otomatis dan kustom konsisten, panggil metode ValidationProblem, bukan BadRequest. ValidationProblem mengembalikan objek ValidationProblemDetails serta respons otomatis.

Mencatat respons 400 otomatis

Untuk mencatat respons 400 otomatis, atur properti delegasi InvalidModelStateResponseFactory untuk melakukan pemrosesan kustom di Startup.ConfigureServices. Secara default, InvalidModelStateResponseFactory menggunakan ProblemDetailsFactory untuk membuat instans ValidationProblemDetails.

Contoh berikut menunjukkan cara mengambil instans ILogger<TCategoryName> untuk mencatat informasi mengenai respons 400 otomatis:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        // To preserve the default behavior, capture the original delegate to call later.
        var builtInFactory = options.InvalidModelStateResponseFactory;

        options.InvalidModelStateResponseFactory = context =>
        {
            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Startup>>();

            // Perform logging here.
            // ...

            // Invoke the default behavior, which produces a ValidationProblemDetails response.
            // To produce a custom response, return a different implementation of IActionResult instead.
            return builtInFactory(context);
        };
    });

Menonaktifkan respons 400 otomatis

Untuk menonaktifkan perilaku 400 otomatis, atur properti SuppressModelStateInvalidFilter ke true. Tambahkan kode yang disorot berikut di Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
        options.DisableImplicitFromServicesParameters = true;
    });

Inferensi parameter sumber pengikatan

Atribut sumber pengikatan menentukan lokasi nilai parameter tindakan. Berikut adalah atribut sumber pengikatan yang ada:

Atribut Sumber pengikatan
[FromBody] Isi permintaan
[FromForm] Data formulir dalam isi permintaan
[FromHeader] Header permintaan
[FromQuery] Parameter string kueri permintaan
[FromRoute] Data rute dari permintaan saat ini
[FromServices] Layanan permintaan yang dimasukkan sebagai parameter tindakan

Peringatan

Jangan menggunakan [FromRoute] saat nilai mungkin berisi %2f (yaitu /). %2f tidak akan dilepaskan ke /. Gunakan [FromQuery] jika nilainya mungkin berisi %2f.

Tanpa atribut [ApiController] atau atribut sumber pengikatan, seperti [FromQuery], runtime ASP.NET Core mencoba menggunakan pengikat model objek yang kompleks. Pengikat model objek kompleks menarik data dari penyedia nilai dalam urutan tertentu.

Dalam contoh berikut, atribut [FromQuery] menunjukkan bahwa nilai parameter discontinuedOnly disediakan dalam string kueri URL permintaan:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

Atribut [ApiController] menerapkan aturan inferensi untuk sumber data default parameter tindakan. Dengan aturan ini, Anda tidak perlu mengidentifikasi sumber pengikatan secara manual dengan menerapkan atribut ke parameter tindakan. Berikut adalah perilaku aturan inferensi sumber pengikatan:

  • [FromBody] disimpulkan untuk parameter jenis kompleks. Pengecualian untuk aturan inferensi [FromBody] adalah jenis bawaan yang kompleks dengan arti khusus, seperti IFormCollection dan CancellationToken. Kode inferensi sumber pengikatan mengabaikan jenis khusus tersebut.
  • [FromForm] disimpulkan untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Ini tidak disimpulkan untuk jenis yang simpel atau ditentukan pengguna.
  • [FromRoute] disimpulkan untuk nama parameter tindakan apa pun yang cocok dengan suatu parameter dalam templat rute. Ketika ada lebih dari satu rute yang cocok dengan parameter tindakan, nilai rute apa pun dianggap [FromRoute].
  • [FromQuery] disimpulkan untuk parameter tindakan lainnya.

Catatan inferensi FromBody

[FromBody] tidak disimpulkan untuk jenis simpel, seperti string atau int. Oleh karena itu, atribut [FromBody] harus digunakan untuk jenis simpel ketika fungsionalitas tersebut diperlukan.

Ketika suatu tindakan memiliki lebih dari satu parameter yang terikat dari isi permintaan, pengecualian akan diterapkan. Misalnya, semua tanda tangan metode tindakan berikut akan menyebabkan pengecualian:

  • [FromBody] disimpulkan pada keduanya karena berjenis kompleks.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • atribut [FromBody] pada satu, disimpulkan di sisi lain karena merupakan jenis kompleks.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • atribut [FromBody] pada keduanya.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Menonaktifkan aturan inferensi

Untuk menonaktifkan inferensi sumber pengikatan, atur SuppressInferBindingSourcesForParameters ke true. Tambahkan kode berikut ke Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
        options.DisableImplicitFromServicesParameters = true;
    });

Inferensi permintaan multipart/form-data

Atribut [ApiController] menerapkan aturan inferensi untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Tipe isi permintaan multipart/form-data disimpulkan untuk jenis ini.

Untuk menonaktifkan perilaku default, atur properti SuppressConsumesConstraintForFormFileParameters ke true di Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
        options.DisableImplicitFromServicesParameters = true;
    });

Detail masalah untuk kode status kesalahan

MVC mengubah hasil kesalahan (hasil dengan kode status 400 atau lebih tinggi) menjadi hasil dengan ProblemDetails. Jenis ProblemDetails ini didasarkan pada spesifikasi RFC 7807 untuk menampilkan detail kesalahan yang dapat dibaca mesin dalam respons HTTP.

Pertimbangkan kode berikut dalam suatu tindakan pengontrol:

if (pet == null)
{
    return NotFound();
}

Metode NotFound ini membuat kode status HTTP 404 dengan isi ProblemDetails. Contohnya:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001"
}

Menonaktifkan respons ProblemDetails

Pembuatan ProblemDetails otomatis untuk kode status kesalahan dinonaktifkan saat properti SuppressMapClientErrors diatur ke true. Tambahkan kode berikut ke Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
        options.DisableImplicitFromServicesParameters = true;
    });

Menentukan jenis konten permintaan yang didukung dengan atribut [Consumes]

Secara default, suatu tindakan mendukung semua jenis konten permintaan yang tersedia. Misalnya, jika aplikasi dikonfigurasi untuk mendukung pemformat inputJSON maupun XML, tindakan mendukung beberapa jenis konten, termasuk application/json dan application/xml.

Dengan atribut [Consumes], suatu tindakan dapat membatasi jenis konten permintaan yang didukung. Terapkan atribut [Consumes] ke suatu tindakan atau pengontrol, yang menentukan satu atau beberapa jenis konten:

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

Dalam kode sebelumnya, tindakan CreateProduct menentukan jenis konten application/xml. Permintaan yang dirutekan ke tindakan ini harus menentukan header Content-Typeapplication/xml. Permintaan yang tidak menentukan header Content-Typeapplication/xml mengakibatkan respons 415 Unsupported Media Type.

Dengan atribut [Consumes] ini, tindakan dapat memengaruhi pilihannya berdasarkan jenis konten permintaan masuk dengan menerapkan batasan jenis. Pertimbangkan contoh berikut:

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

Dalam kode sebelumnya, ConsumesController dikonfigurasi untuk menangani permintaan yang dikirim ke URL https://localhost:5001/api/Consumes. Kedua tindakan pengontrol, PostJson dan PostForm, menangani permintaan POST dengan URL yang sama. Tanpa atribut [Consumes] yang menerapkan batasan jenis, pengecualian kecocokan ambigu akan diterapkan.

Atribut [Consumes] ini diterapkan ke kedua tindakan. Tindakan PostJson menangani permintaan yang dikirim dengan header Content-Typeapplication/json. Tindakan PostForm menangani permintaan yang dikirim dengan header Content-Typeapplication/x-www-form-urlencoded.

Sumber Daya Tambahan:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Jangan membuat pengontrol API web yang berasal dari kelas Controller. Controller berasal dari ControllerBase dan menambahkan dukungan untuk tampilan sehingga cocok untuk menangani halaman web, bukan permintaan API web. Ada pengecualian untuk aturan ini: jika Anda berencana menggunakan pengontrol yang sama untuk tampilan dan API web, ambil dari Controller. Kelas ControllerBase ini menyediakan banyak properti dan metode yang berguna untuk menangani permintaan HTTP. Misalnya, ControllerBase.CreatedAtAction mengembalikan kode status 201:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Berikut adalah beberapa contoh metode lainnya yang disediakan oleh ControllerBase:

Metode Catatan
BadRequest Mengembalikan kode status 400.
NotFound Mengembalikan kode status 404.
PhysicalFile Mengembalikan satu file.
TryUpdateModelAsync Memanggil pengikatan model.
TryValidateModel Memanggil validasi model.

Untuk melihat daftar semua metode dan properti yang tersedia, baca ControllerBase.

Atribut

Namespace Microsoft.AspNetCore.Mvc menyediakan atribut yang dapat digunakan untuk mengonfigurasi perilaku pengontrol API web dan metode tindakan. Contoh berikut menggunakan atribut untuk menentukan kata kerja tindakan HTTP yang didukung dan kode status HTTP apa pun yang diketahui sekaligus dapat dikembalikan:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Berikut adalah beberapa contoh atribut yang tersedia:

Atribut Catatan
[Route] Menentukan pola URL untuk suatu pengontrol atau tindakan.
[Bind] Menentukan awalan dan properti yang akan disertakan untuk pengikatan model.
[HttpGet] Mengidentifikasi tindakan yang mendukung kata kerja tindakan HTTP GET.
[Consumes] Menentukan jenis data yang diterima oleh tindakan.
[Produces] Menentukan jenis data yang dikembalikan oleh tindakan.

Untuk mendapatkan daftar berisi atribut yang tersedia, baca Microsoft.AspNetCore.Mvc namespace.

Atribut ApiController

Atribut [ApiController] dapat diterapkan ke kelas pengontrol untuk mengaktifkan perilaku khusus API yang dogmatis berikut:

Atribut di pengontrol tertentu

Atribut [ApiController] dapat diterapkan ke pengontrol tertentu, misalnya dalam contoh berikut dari templat proyek:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Atribut pada sejumlah pengontrol

Salah satu metode untuk menggunakan atribut pada lebih dari satu pengontrol adalah membuat kelas pengontrol dasar kustom yang dianotasikan dengan atribut [ApiController]. Contoh berikut menunjukkan kelas dasar kustom dan suatu pengontrol yang berasal darinya:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("api/[controller]")]
public class PetsController : MyControllerBase

Atribut pada suatu assembly

Jika versi kompatibilitas diatur ke 2.2 atau yang lebih baru, atribut [ApiController] dapat diterapkan ke assembly. Anotasi dengan cara ini menerapkan perilaku API web untuk semua pengontrol di assembly. Tidak ada cara untuk membatalkan pengontrol individu. Terapkan atribut tingkat assembly ke deklarasi namespace layanan di sekitar kelas Startup:

[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

Persyaratan perutean atribut

Atribut [ApiController] menjadikan perutean atribut sebagai persyaratan. Contohnya:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Tindakan tidak dapat diakses melalui rute konvensional yang ditentukan oleh UseMvc atau UseMvcWithDefaultRoute di Startup.Configure.

Respons HTTP 400 otomatis

Atribut [ApiController] membuat kesalahan validasi model memicu respons HTTP 400 secara otomatis. Akibatnya, kode berikut tidak diperlukan dalam suatu metode tindakan:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

ASP.NET Core MVC menggunakan filter tindakan ModelStateInvalidFilter untuk melakukan pemeriksaan awal.

Respons BadRequest default

Dengan versi kompatibilitas 2.1, jenis respons default untuk respons HTTP 400 adalah SerializableError. Isi permintaan berikut adalah salah satu contoh jenis serial:

{
  "": [
    "A non-empty request body is required."
  ]
}

Dengan versi kompatibilitas 2.2 atau yang lebih baru, jenis respons default untuk respons HTTP 400 adalah ValidationProblemDetails. Isi permintaan berikut adalah salah satu contoh jenis serial:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

Jenis ValidationProblemDetails:

  • Menghasilkan format yang dapat dibaca mesin untuk menentukan kesalahan dalam respons API web.
  • Sesuai dengan spesifikasi RFC 7807.

Agar respons otomatis dan kustom konsisten, panggil metode ValidationProblem, bukan BadRequest. ValidationProblem mengembalikan objek ValidationProblemDetails serta respons otomatis.

Mencatat respons 400 otomatis

Baca Cara mencatat respons 400 otomatis pada kesalahan validasi model (dotnet/AspNetCore.Docs#12157).

Menonaktifkan respons 400 otomatis

Untuk menonaktifkan perilaku 400 otomatis, atur properti SuppressModelStateInvalidFilter ke true. Tambahkan kode yang disorot berikut di Startup.ConfigureServices:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Inferensi parameter sumber pengikatan

Atribut sumber pengikatan menentukan lokasi nilai parameter tindakan. Berikut adalah atribut sumber pengikatan yang ada:

Atribut Sumber pengikatan
[FromBody] Isi permintaan
[FromForm] Data formulir dalam isi permintaan
[FromHeader] Header permintaan
[FromQuery] Parameter string kueri permintaan
[FromRoute] Data rute dari permintaan saat ini
[FromServices] Layanan permintaan yang dimasukkan sebagai parameter tindakan

Peringatan

Jangan menggunakan [FromRoute] saat nilai mungkin berisi %2f (yaitu /). %2f tidak akan dilepaskan ke /. Gunakan [FromQuery] jika nilainya mungkin berisi %2f. Tanpa atribut [ApiController] atau atribut sumber pengikatan, seperti [FromQuery], runtime ASP.NET Core mencoba menggunakan pengikat model objek yang kompleks. Pengikat model objek kompleks menarik data dari penyedia nilai dalam urutan tertentu.

Dalam contoh berikut, atribut [FromQuery] menunjukkan bahwa nilai parameter discontinuedOnly disediakan dalam string kueri URL permintaan:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

Atribut [ApiController] menerapkan aturan inferensi untuk sumber data default parameter tindakan. Dengan aturan ini, Anda tidak perlu mengidentifikasi sumber pengikatan secara manual dengan menerapkan atribut ke parameter tindakan. Berikut adalah perilaku aturan inferensi sumber pengikatan:

  • [FromBody] disimpulkan untuk parameter jenis kompleks. Pengecualian untuk aturan inferensi [FromBody] adalah jenis bawaan yang kompleks dengan arti khusus, seperti IFormCollection dan CancellationToken. Kode inferensi sumber pengikatan mengabaikan jenis khusus tersebut.
  • [FromForm] disimpulkan untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Ini tidak disimpulkan untuk jenis yang simpel atau ditentukan pengguna.
  • [FromRoute] disimpulkan untuk nama parameter tindakan apa pun yang cocok dengan suatu parameter dalam templat rute. Ketika ada lebih dari satu rute yang cocok dengan parameter tindakan, nilai rute apa pun dianggap [FromRoute].
  • [FromQuery] disimpulkan untuk parameter tindakan lainnya.

Catatan inferensi FromBody

[FromBody] tidak disimpulkan untuk jenis simpel, seperti string atau int. Oleh karena itu, atribut [FromBody] harus digunakan untuk jenis simpel ketika fungsionalitas tersebut diperlukan.

Ketika suatu tindakan memiliki lebih dari satu parameter yang terikat dari isi permintaan, pengecualian akan diterapkan. Misalnya, semua tanda tangan metode tindakan berikut akan menyebabkan pengecualian:

  • [FromBody] disimpulkan pada keduanya karena berjenis kompleks.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • atribut [FromBody] pada satu, disimpulkan di sisi lain karena merupakan jenis kompleks.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • atribut [FromBody] pada keduanya.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Catatan

Dalam ASP.NET Core 2.1, parameter jenis koleksi, seperti daftar dan array, salah disimpulkan sebagai [FromQuery]. Atribut [FromBody] harus digunakan untuk parameter ini jika parameter tersebut harus terikat dari isi permintaan. Perilaku ini dikoreksi di ASP.NET Core 2.2 atau yang lebih baru. Di situ, parameter jenis koleksi disimpulkan agar terikat dari isi secara default.

Menonaktifkan aturan inferensi

Untuk menonaktifkan inferensi sumber pengikatan, atur SuppressInferBindingSourcesForParameters ke true. Tambahkan kode berikut ke Startup.ConfigureServices:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Inferensi permintaan multipart/form-data

Atribut [ApiController] menerapkan aturan inferensi untuk parameter tindakan jenis IFormFile dan IFormFileCollection. Tipe isi permintaan multipart/form-data disimpulkan untuk jenis ini. Untuk menonaktifkan perilaku default, atur properti SuppressConsumesConstraintForFormFileParameters ke true di Startup.ConfigureServices:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Detail masalah untuk kode status kesalahan

Ketika versi kompatibilitasnya adalah 2.2 atau yang lebih baru, MVC mengubah hasil kesalahan (hasil dengan kode status 400 atau lebih tinggi) ke hasil dengan ProblemDetails. Jenis ProblemDetails ini didasarkan pada spesifikasi RFC 7807 untuk menampilkan detail kesalahan yang dapat dibaca mesin dalam respons HTTP. Pertimbangkan kode berikut dalam suatu tindakan pengontrol:

if (pet == null)
{
    return NotFound();
}

Metode NotFound ini membuat kode status HTTP 404 dengan isi ProblemDetails. Contohnya:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001"
}

Menonaktifkan respons ProblemDetails

Pembuatan ProblemDetails otomatis untuk kode status kesalahan dinonaktifkan saat properti SuppressMapClientErrors diatur ke true. Tambahkan kode berikut ke Startup.ConfigureServices:

Menentukan jenis konten permintaan yang didukung dengan atribut [Consumes]

Secara default, suatu tindakan mendukung semua jenis konten permintaan yang tersedia. Misalnya, jika aplikasi dikonfigurasi untuk mendukung pemformat inputJSON maupun XML, tindakan mendukung beberapa jenis konten, termasuk application/json dan application/xml.

Dengan atribut [Consumes], suatu tindakan dapat membatasi jenis konten permintaan yang didukung. Terapkan atribut [Consumes] ke suatu tindakan atau pengontrol, yang menentukan satu atau beberapa jenis konten:

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

Dalam kode sebelumnya, tindakan CreateProduct menentukan jenis konten application/xml. Permintaan yang dirutekan ke tindakan ini harus menentukan header Content-Typeapplication/xml. Permintaan yang tidak menentukan header Content-Typeapplication/xml mengakibatkan respons 415 Unsupported Media Type. Dengan atribut [Consumes] ini, tindakan dapat memengaruhi pilihannya berdasarkan jenis konten permintaan masuk dengan menerapkan batasan jenis. Pertimbangkan contoh berikut:

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

Dalam kode sebelumnya, ConsumesController dikonfigurasi untuk menangani permintaan yang dikirim ke URL https://localhost:5001/api/Consumes. Kedua tindakan pengontrol, PostJson dan PostForm, menangani permintaan POST dengan URL yang sama. Tanpa atribut [Consumes] yang menerapkan batasan jenis, pengecualian kecocokan ambigu akan diterapkan. Atribut [Consumes] ini diterapkan ke kedua tindakan. Tindakan PostJson menangani permintaan yang dikirim dengan header Content-Typeapplication/json. Tindakan PostForm menangani permintaan yang dikirim dengan header Content-Typeapplication/x-www-form-urlencoded.

Sumber Daya Tambahan: