Jenis pengembalian tindakan pengontrol di API web ASP.NET Core
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Melihat atau mengunduh kode sampel (cara mengunduh)
ASP.NET Core menyediakan opsi berikut untuk jenis pengembalian tindakan pengontrol API web:
Artikel ini menjelaskan kapan paling tepat untuk menggunakan setiap jenis pengembalian.
Jenis tertentu
Tindakan paling dasar mengembalikan jenis data primitif atau kompleks, misalnya, string
atau objek kustom. Pertimbangkan tindakan berikut, yang mengembalikan kumpulan objek kustom Product
:
[HttpGet]
public Task<List<Product>> Get() =>
_productContext.Products.OrderBy(p => p.Name).ToListAsync();
Tanpa kondisi yang diketahui untuk melindungi, mengembalikan jenis tertentu sudah cukup. Tindakan sebelumnya tidak menerima parameter, sehingga validasi batasan parameter tidak diperlukan.
Ketika beberapa jenis pengembalian dimungkinkan, adalah umum untuk mencampur ActionResult jenis pengembalian dengan jenis pengembalian primitif atau kompleks. Baik IActionResult atau ActionResult<T> diperlukan untuk mengakomodasi jenis tindakan ini. Beberapa sampel beberapa jenis pengembalian disediakan dalam artikel ini.
Mengembalikan IEnumerable<T> atau IAsyncEnumerable<T>
Lihat Mengembalikan IEnumerable<T>
atau IAsyncEnumerable<T>
untuk pertimbangan performa.
ASP.NET Buffer Core hasil tindakan yang kembali IEnumerable<T> sebelum menulisnya ke respons. Pertimbangkan untuk mendeklarasikan jenis pengembalian tanda tangan tindakan untuk IAsyncEnumerable<T> menjamin iterasi asinkron. Pada akhirnya, mode iterasi didasarkan pada jenis beton yang mendasar yang dikembalikan dan formatter yang dipilih memengaruhi bagaimana hasilnya diproses:
- Saat menggunakan
System.Text.Json
formatter, MVC bergantung pada dukungan yangSystem.Text.Json
ditambahkan untuk mengalirkan hasilnya. - Saat menggunakan
Newtonsoft.Json
atau denganXML-based
formatter, hasilnya di-buffer.
Pertimbangkan tindakan berikut, yang mengembalikan rekaman produk dengan harga jual sebagai IEnumerable<Product>
:
[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
var products = _productContext.Products.OrderBy(p => p.Name).ToList();
foreach (var product in products)
{
if (product.IsOnSale)
{
yield return product;
}
}
}
Setara IAsyncEnumerable<Product>
dengan tindakan sebelumnya adalah:
[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
var products = _productContext.Products.OrderBy(p => p.Name).AsAsyncEnumerable();
await foreach (var product in products)
{
if (product.IsOnSale)
{
yield return product;
}
}
}
Jenis IActionResult
IActionResult Jenis pengembalian sesuai ketika beberapa ActionResult
jenis pengembalian dimungkinkan dalam tindakan. Jenis mewakili ActionResult
berbagai kode status HTTP. Setiap kelas non-abstrak yang berasal dari ActionResult
memenuhi syarat sebagai jenis pengembalian yang valid. Beberapa jenis pengembalian umum dalam kategori ini adalah BadRequestResult (400), NotFoundResult (404), dan OkObjectResult (200). Atau, metode kenyamanan di ControllerBase kelas dapat digunakan untuk mengembalikan ActionResult
jenis dari tindakan. Misalnya, return BadRequest();
adalah bentuk singkatan dari return new BadRequestResult();
.
Karena ada beberapa jenis pengembalian dan jalur dalam jenis tindakan ini, penggunaan [ProducesResponseType]
liberal atribut diperlukan. Atribut ini menghasilkan detail respons yang lebih deskriptif untuk halaman bantuan API web yang dihasilkan oleh alat seperti Swagger. [ProducesResponseType]
menunjukkan jenis yang diketahui dan kode status HTTP yang akan dikembalikan oleh tindakan.
Tindakan sinkron
Pertimbangkan tindakan sinkron berikut di mana ada dua jenis pengembalian yang mungkin:
[HttpGet("{id}")]
[ProducesResponseType<Product>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById_IActionResult(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? NotFound() : Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk yang diwakili oleh
id
tidak ada di penyimpanan data yang mendasar. Metode NotFound kenyamanan dipanggil sebagai singkatan darireturn new NotFoundResult();
. - Kode status 200 dikembalikan dengan
Product
objek ketika produk memang ada. Metode Ok kenyamanan dipanggil sebagai singkatan darireturn new OkObjectResult(product);
.
Tindakan asinkron
Pertimbangkan tindakan asinkron berikut di mana ada dua jenis pengembalian yang mungkin:
[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync_IActionResult(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
return CreatedAtAction(nameof(CreateAsync_IActionResult), new { id = product.Id }, product);
}
Dalam tindakan sebelumnya:
Kode status 400 dikembalikan ketika deskripsi produk berisi "Widget XYZ". Metode BadRequest kenyamanan dipanggil sebagai singkatan dari
return new BadRequestResult();
.Kode status 201 dihasilkan oleh CreatedAtAction metode kenyamanan saat produk dibuat. Kode berikut adalah alternatif untuk memanggil
CreatedAtAction
:return new CreatedAtActionResult(nameof(CreateAsync), "Products", new { id = product.Id }, product);
Di jalur kode sebelumnya,
Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Misalnya, model berikut menunjukkan bahwa permintaan harus menyertakan Name
properti dan Description
. Kegagalan untuk menyediakan Name
dan Description
dalam permintaan menyebabkan validasi model gagal.
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
[Required]
public string Description { get; set; } = string.Empty;
public bool IsOnSale { get; set; }
}
[ApiController]
Jika atribut diterapkan, kesalahan validasi model menghasilkan kode status 400. Untuk informasi selengkapnya, lihat Respons HTTP 400 otomatis.
ActionResult vs IActionResult
Bagian berikut dibandingkan dengan ActionResult
IActionResult
Jenis T> ActionResult<
ASP.NET Core menyertakan jenis pengembalian ActionResult<T> untuk tindakan pengontrol API web. Ini memungkinkan pengembalian jenis yang berasal dari ActionResult atau mengembalikan jenis tertentu. ActionResult<T>
menawarkan manfaat berikut atas jenis IActionResult:
[ProducesResponseType]
Properti atributType
dapat dikecualikan. Misalnya,[ProducesResponseType(200, Type = typeof(Product))]
disederhanakan ke[ProducesResponseType(200)]
. Jenis pengembalian tindakan yang diharapkan disimpulkanT
dari dalamActionResult<T>
.- Operator cast implisit mendukung konversi baik
T
danActionResult
keActionResult<T>
.T
mengonversi ke ObjectResult, yang berartireturn new ObjectResult(T);
disederhanakan kereturn T;
.
C# tidak mendukung operator cast implisit pada antarmuka. Akibatnya, konversi antarmuka ke jenis beton diperlukan untuk menggunakan ActionResult<T>
. Misalnya, penggunaan IEnumerable
dalam contoh berikut tidak berfungsi:
[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
_repository.GetProducts();
Salah satu opsi untuk memperbaiki kode sebelumnya adalah mengembalikan _repository.GetProducts().ToList();
.
Sebagian besar tindakan memiliki jenis pengembalian tertentu. Kondisi tak terduga dapat terjadi selama eksekusi tindakan, dalam hal ini jenis tertentu tidak dikembalikan. Misalnya, parameter input tindakan mungkin gagal dalam validasi model. Dalam kasus seperti itu, adalah umum untuk mengembalikan jenis yang sesuai ActionResult
alih-alih jenis tertentu.
Tindakan sinkron
Pertimbangkan tindakan sinkron di mana ada dua jenis pengembalian yang mungkin:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById_ActionResultOfT(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? NotFound() : product;
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada.
Tindakan asinkron
Pertimbangkan tindakan asinkron di mana ada dua jenis pengembalian yang mungkin:
[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync_ActionResultOfT(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
return CreatedAtAction(nameof(CreateAsync_ActionResultOfT), new { id = product.Id }, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 (BadRequest) dikembalikan oleh runtime ASP.NET Core saat:
- Atribut
[ApiController]
telah diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh CreatedAtAction metode saat produk dibuat. Dalam jalur kode ini,
Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Jenis HttpResults
Selain jenis hasil bawaan khusus MVC (IActionResult dan ActionResult<T>), ASP.NET Core menyertakan jenis HttpResults yang dapat digunakan di API Minimal dan API Web.
Berbeda dari jenis hasil khusus MVC, :HttpResults
Adalah implementasi hasil yang diproses oleh panggilan ke IResult.ExecuteAsync.
Tidak memanfaatkan Formatter yang dikonfigurasi. Tidak memanfaatkan formatter yang dikonfigurasi berarti:
- Beberapa fitur seperti
Content negotiation
tidak tersedia. - Yang dihasilkan
Content-Type
diputuskanHttpResults
oleh implementasi.
- Beberapa fitur seperti
HttpResults
dapat berguna saat berbagi kode antara API Minimal dan API Web.
Jenis IResult
Namespace Microsoft.AspNetCore.Http.HttpResults berisi kelas yang mengimplementasikan IResult antarmuka. Antarmuka IResult
mendefinisikan kontrak yang mewakili hasil titik akhir HTTP. Kelas Hasil statis digunakan untuk membuat berbagai IResult
objek yang mewakili berbagai jenis respons.
Tabel hasil bawaan memperlihatkan pembantu hasil umum.
Pertimbangkan gambar berikut:
[HttpGet("{id}")]
[ProducesResponseType<Product>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IResult GetById(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? Results.NotFound() : Results.Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada, yang dihasilkan oleh Results.Ok<T>().
Pertimbangkan gambar berikut:
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType<Product>(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IResult> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return Results.BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
var location = Url.Action(nameof(CreateAsync), new { id = product.Id }) ?? $"/{product.Id}";
return Results.Created(location, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 dikembalikan saat:
- Atribut
[ApiController]
telah diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh
Results.Create
metode saat produk dibuat. Dalam jalur kode ini,Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Hasil<TResult1, jenis TResultN>
Kelas TypedResults statis mengembalikan implementasi konkret IResult
yang memungkinkan penggunaan IResult
sebagai jenis pengembalian. Penggunaan implementasi konkret IResult
menawarkan manfaat berikut atas jenis IResult:
[ProducesResponseType]
Semua atribut dapat dikecualikan, karenaHttpResult
implementasi berkontribusi secara otomatis ke metadata titik akhir.
Ketika beberapa IResult
jenis pengembalian diperlukan, pengembalian Results<TResult1, TResultN>
lebih disukai daripada mengembalikan IResult
. Mengembalikan Results<TResult1, TResultN>
lebih disukai karena jenis serikat generik secara otomatis mempertahankan metadata titik akhir.
Jenis Results<TResult1, TResultN>
gabungan menerapkan operator cast implisit sehingga pengkompilasi dapat secara otomatis mengonversi jenis yang ditentukan dalam argumen generik ke instans jenis union. Ini memiliki manfaat tambahan untuk memberikan pemeriksaan waktu kompilasi bahwa handler rute sebenarnya hanya mengembalikan hasil yang dinyatakannya. Mencoba mengembalikan jenis yang tidak dinyatakan sebagai salah satu argumen generik untuk Results<>
menghasilkan kesalahan kompilasi.
Pertimbangkan gambar berikut:
[HttpGet("{id}")]
public Results<NotFound, Ok<Product>> GetById(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? TypedResults.NotFound() : TypedResults.Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada, yang dihasilkan oleh TypedResults.Ok<T>.
[HttpPost]
public async Task<Results<BadRequest, Created<Product>>> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return TypedResults.BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
var location = Url.Action(nameof(CreateAsync), new { id = product.Id }) ?? $"/{product.Id}";
return TypedResults.Created(location, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 dikembalikan saat:
- Atribut
[ApiController]
diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh
TypedResults.Created
metode saat produk dibuat. Dalam jalur kode ini,Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Sumber Daya Tambahan:
Melihat atau mengunduh kode sampel (cara mengunduh)
ASP.NET Core menyediakan opsi berikut untuk jenis pengembalian tindakan pengontrol API web:
Artikel ini menjelaskan kapan paling tepat untuk menggunakan setiap jenis pengembalian.
Jenis tertentu
Tindakan paling dasar mengembalikan jenis data primitif atau kompleks, misalnya, string
atau objek kustom. Pertimbangkan tindakan berikut, yang mengembalikan kumpulan objek kustom Product
:
[HttpGet]
public Task<List<Product>> Get() =>
_productContext.Products.OrderBy(p => p.Name).ToListAsync();
Tanpa kondisi yang diketahui untuk melindungi, mengembalikan jenis tertentu sudah cukup. Tindakan sebelumnya tidak menerima parameter, sehingga validasi batasan parameter tidak diperlukan.
Ketika beberapa jenis pengembalian dimungkinkan, adalah umum untuk mencampur ActionResult jenis pengembalian dengan jenis pengembalian primitif atau kompleks. Baik IActionResult atau ActionResult<T> diperlukan untuk mengakomodasi jenis tindakan ini. Beberapa sampel beberapa jenis pengembalian disediakan dalam artikel ini.
Mengembalikan IEnumerable<T> atau IAsyncEnumerable<T>
Lihat Mengembalikan IEnumerable<T>
atau IAsyncEnumerable<T>
untuk pertimbangan performa.
ASP.NET Buffer Core hasil tindakan yang kembali IEnumerable<T> sebelum menulisnya ke respons. Pertimbangkan untuk mendeklarasikan jenis pengembalian tanda tangan tindakan untuk IAsyncEnumerable<T> menjamin iterasi asinkron. Pada akhirnya, mode iterasi didasarkan pada jenis beton yang mendasar yang dikembalikan dan formatter yang dipilih memengaruhi bagaimana hasilnya diproses:
- Saat menggunakan
System.Text.Json
formatter, MVC bergantung pada dukungan yangSystem.Text.Json
ditambahkan untuk mengalirkan hasilnya. - Saat menggunakan
Newtonsoft.Json
atau denganXML-based
formatter, hasilnya di-buffer.
Pertimbangkan tindakan berikut, yang mengembalikan rekaman produk dengan harga jual sebagai IEnumerable<Product>
:
[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
var products = _productContext.Products.OrderBy(p => p.Name).ToList();
foreach (var product in products)
{
if (product.IsOnSale)
{
yield return product;
}
}
}
Setara IAsyncEnumerable<Product>
dengan tindakan sebelumnya adalah:
[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
var products = _productContext.Products.OrderBy(p => p.Name).AsAsyncEnumerable();
await foreach (var product in products)
{
if (product.IsOnSale)
{
yield return product;
}
}
}
Jenis IActionResult
IActionResult Jenis pengembalian sesuai ketika beberapa ActionResult
jenis pengembalian dimungkinkan dalam tindakan. Jenis mewakili ActionResult
berbagai kode status HTTP. Setiap kelas non-abstrak yang berasal dari ActionResult
memenuhi syarat sebagai jenis pengembalian yang valid. Beberapa jenis pengembalian umum dalam kategori ini adalah BadRequestResult (400), NotFoundResult (404), dan OkObjectResult (200). Atau, metode kenyamanan di ControllerBase kelas dapat digunakan untuk mengembalikan ActionResult
jenis dari tindakan. Misalnya, return BadRequest();
adalah bentuk singkatan dari return new BadRequestResult();
.
Karena ada beberapa jenis pengembalian dan jalur dalam jenis tindakan ini, penggunaan [ProducesResponseType]
liberal atribut diperlukan. Atribut ini menghasilkan detail respons yang lebih deskriptif untuk halaman bantuan API web yang dihasilkan oleh alat seperti Swagger. [ProducesResponseType]
menunjukkan jenis yang diketahui dan kode status HTTP yang akan dikembalikan oleh tindakan.
Tindakan sinkron
Pertimbangkan tindakan sinkron berikut di mana ada dua jenis pengembalian yang mungkin:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById_IActionResult(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? NotFound() : Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk yang diwakili oleh
id
tidak ada di penyimpanan data yang mendasar. Metode NotFound kenyamanan dipanggil sebagai singkatan darireturn new NotFoundResult();
. - Kode status 200 dikembalikan dengan
Product
objek ketika produk memang ada. Metode Ok kenyamanan dipanggil sebagai singkatan darireturn new OkObjectResult(product);
.
Tindakan asinkron
Pertimbangkan tindakan asinkron berikut di mana ada dua jenis pengembalian yang mungkin:
[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync_IActionResult(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
return CreatedAtAction(nameof(GetById_IActionResult), new { id = product.Id }, product);
}
Dalam tindakan sebelumnya:
Kode status 400 dikembalikan ketika deskripsi produk berisi "Widget XYZ". Metode BadRequest kenyamanan dipanggil sebagai singkatan dari
return new BadRequestResult();
.Kode status 201 dihasilkan oleh CreatedAtAction metode kenyamanan saat produk dibuat. Kode berikut adalah alternatif untuk memanggil
CreatedAtAction
:return new CreatedAtActionResult(nameof(GetById), "Products", new { id = product.Id }, product);
Di jalur kode sebelumnya,
Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Misalnya, model berikut menunjukkan bahwa permintaan harus menyertakan Name
properti dan Description
. Kegagalan untuk menyediakan Name
dan Description
dalam permintaan menyebabkan validasi model gagal.
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
[Required]
public string Description { get; set; } = string.Empty;
public bool IsOnSale { get; set; }
}
[ApiController]
Jika atribut diterapkan, kesalahan validasi model menghasilkan kode status 400. Untuk informasi selengkapnya, lihat Respons HTTP 400 otomatis.
ActionResult vs IActionResult
Bagian berikut dibandingkan dengan ActionResult
IActionResult
Jenis T> ActionResult<
ASP.NET Core menyertakan jenis pengembalian ActionResult<T> untuk tindakan pengontrol API web. Ini memungkinkan pengembalian jenis yang berasal dari ActionResult atau mengembalikan jenis tertentu. ActionResult<T>
menawarkan manfaat berikut atas jenis IActionResult:
[ProducesResponseType]
Properti atributType
dapat dikecualikan. Misalnya,[ProducesResponseType(200, Type = typeof(Product))]
disederhanakan ke[ProducesResponseType(200)]
. Jenis pengembalian tindakan yang diharapkan disimpulkanT
dari dalamActionResult<T>
.- Operator cast implisit mendukung konversi baik
T
danActionResult
keActionResult<T>
.T
mengonversi ke ObjectResult, yang berartireturn new ObjectResult(T);
disederhanakan kereturn T;
.
C# tidak mendukung operator cast implisit pada antarmuka. Akibatnya, konversi antarmuka ke jenis beton diperlukan untuk menggunakan ActionResult<T>
. Misalnya, penggunaan IEnumerable
dalam contoh berikut tidak berfungsi:
[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
_repository.GetProducts();
Salah satu opsi untuk memperbaiki kode sebelumnya adalah mengembalikan _repository.GetProducts().ToList();
.
Sebagian besar tindakan memiliki jenis pengembalian tertentu. Kondisi tak terduga dapat terjadi selama eksekusi tindakan, dalam hal ini jenis tertentu tidak dikembalikan. Misalnya, parameter input tindakan mungkin gagal dalam validasi model. Dalam kasus seperti itu, adalah umum untuk mengembalikan jenis yang sesuai ActionResult
alih-alih jenis tertentu.
Tindakan sinkron
Pertimbangkan tindakan sinkron di mana ada dua jenis pengembalian yang mungkin:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById_ActionResultOfT(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? NotFound() : product;
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada.
Tindakan asinkron
Pertimbangkan tindakan asinkron di mana ada dua jenis pengembalian yang mungkin:
[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync_ActionResultOfT(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
return CreatedAtAction(nameof(GetById_ActionResultOfT), new { id = product.Id }, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 (BadRequest) dikembalikan oleh runtime ASP.NET Core saat:
- Atribut
[ApiController]
telah diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh CreatedAtAction metode saat produk dibuat. Dalam jalur kode ini,
Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Jenis HttpResults
Selain jenis hasil bawaan khusus MVC (IActionResult dan ActionResult<T>), ASP.NET Core menyertakan jenis HttpResults yang dapat digunakan di API Minimal dan API Web.
Berbeda dari jenis hasil khusus MVC, :HttpResults
Adalah implementasi hasil yang diproses oleh panggilan ke IResult.ExecuteAsync.
Tidak memanfaatkan Formatter yang dikonfigurasi. Tidak memanfaatkan formatter yang dikonfigurasi berarti:
- Beberapa fitur seperti
Content negotiation
tidak tersedia. - Yang dihasilkan
Content-Type
diputuskanHttpResults
oleh implementasi.
- Beberapa fitur seperti
HttpResults
dapat berguna saat berbagi kode antara API Minimal dan API Web.
Jenis IResult
Namespace Microsoft.AspNetCore.Http.HttpResults berisi kelas yang mengimplementasikan IResult antarmuka. Antarmuka IResult
mendefinisikan kontrak yang mewakili hasil titik akhir HTTP. Kelas Hasil statis digunakan untuk membuat berbagai IResult
objek yang mewakili berbagai jenis respons.
Tabel hasil bawaan memperlihatkan pembantu hasil umum.
Pertimbangkan gambar berikut:
[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IResult GetById(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? Results.NotFound() : Results.Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada, yang dihasilkan oleh Results.Ok<T>().
Pertimbangkan gambar berikut:
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(typeof(Product), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IResult> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return Results.BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}";
return Results.Created(location, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 dikembalikan saat:
- Atribut
[ApiController]
telah diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh
Results.Create
metode saat produk dibuat. Dalam jalur kode ini,Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Hasil<TResult1, jenis TResultN>
Kelas TypedResults statis mengembalikan implementasi konkret IResult
yang memungkinkan penggunaan IResult
sebagai jenis pengembalian. Penggunaan implementasi konkret IResult
menawarkan manfaat berikut atas jenis IResult:
[ProducesResponseType]
Semua atribut dapat dikecualikan, karenaHttpResult
implementasi berkontribusi secara otomatis ke metadata titik akhir.
Ketika beberapa IResult
jenis pengembalian diperlukan, pengembalian Results<TResult1, TResultN>
lebih disukai daripada mengembalikan IResult
. Mengembalikan Results<TResult1, TResultN>
lebih disukai karena jenis serikat generik secara otomatis mempertahankan metadata titik akhir.
Jenis Results<TResult1, TResultN>
gabungan menerapkan operator cast implisit sehingga pengkompilasi dapat secara otomatis mengonversi jenis yang ditentukan dalam argumen generik ke instans jenis union. Ini memiliki manfaat tambahan untuk memberikan pemeriksaan waktu kompilasi bahwa handler rute sebenarnya hanya mengembalikan hasil yang dinyatakannya. Mencoba mengembalikan jenis yang tidak dinyatakan sebagai salah satu argumen generik untuk Results<>
menghasilkan kesalahan kompilasi.
Pertimbangkan gambar berikut:
[HttpGet("{id}")]
public Results<NotFound, Ok<Product>> GetById(int id)
{
var product = _productContext.Products.Find(id);
return product == null ? TypedResults.NotFound() : TypedResults.Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada, yang dihasilkan oleh TypedResults.Ok<T>.
[HttpPost]
public async Task<Results<BadRequest, Created<Product>>> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return TypedResults.BadRequest();
}
_productContext.Products.Add(product);
await _productContext.SaveChangesAsync();
var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}";
return TypedResults.Created(location, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 dikembalikan saat:
- Atribut
[ApiController]
diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh
TypedResults.Create
metode saat produk dibuat. Dalam jalur kode ini,Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Sumber Daya Tambahan:
Melihat atau mengunduh kode sampel (cara mengunduh)
ASP.NET Core menawarkan opsi berikut untuk jenis pengembalian tindakan pengontrol API web:
Dokumen ini menjelaskan kapan paling tepat untuk menggunakan setiap jenis pengembalian.
Jenis tertentu
Tindakan paling sederhana mengembalikan jenis data primitif atau kompleks (misalnya, string
atau jenis objek kustom). Pertimbangkan tindakan berikut, yang mengembalikan kumpulan objek kustom Product
:
[HttpGet]
public List<Product> Get() =>
_repository.GetProducts();
Tanpa kondisi yang diketahui untuk melindungi selama eksekusi tindakan, mengembalikan jenis tertentu sudah cukup. Tindakan sebelumnya tidak menerima parameter, sehingga validasi batasan parameter tidak diperlukan.
Ketika beberapa jenis pengembalian dimungkinkan, adalah umum untuk mencampur ActionResult jenis pengembalian dengan jenis pengembalian primitif atau kompleks. Baik IActionResult atau ActionResult<T> diperlukan untuk mengakomodasi jenis tindakan ini. Beberapa sampel dari beberapa jenis pengembalian disediakan dalam dokumen ini.
Mengembalikan IEnumerable<T> atau IAsyncEnumerable<T>
ASP.NET Buffer Core hasil tindakan yang kembali IEnumerable<T> sebelum menulisnya ke respons. Pertimbangkan untuk mendeklarasikan jenis pengembalian tanda tangan tindakan untuk IAsyncEnumerable<T> menjamin iterasi asinkron. Pada akhirnya, mode iterasi didasarkan pada jenis beton yang mendasar yang dikembalikan. MVC secara otomatis buffer jenis beton apa pun yang mengimplementasikan IAsyncEnumerable<T>
.
Pertimbangkan tindakan berikut, yang mengembalikan rekaman produk dengan harga jual sebagai IEnumerable<Product>
:
[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
var products = _repository.GetProducts();
foreach (var product in products)
{
if (product.IsOnSale)
{
yield return product;
}
}
}
Setara IAsyncEnumerable<Product>
dengan tindakan sebelumnya adalah:
[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
var products = _repository.GetProductsAsync();
await foreach (var product in products)
{
if (product.IsOnSale)
{
yield return product;
}
}
}
Jenis IActionResult
IActionResult Jenis pengembalian sesuai ketika beberapa ActionResult
jenis pengembalian dimungkinkan dalam tindakan. Jenis mewakili ActionResult
berbagai kode status HTTP. Setiap kelas non-abstrak yang berasal dari ActionResult
memenuhi syarat sebagai jenis pengembalian yang valid. Beberapa jenis pengembalian umum dalam kategori ini adalah BadRequestResult (400), NotFoundResult (404), dan OkObjectResult (200). Atau, metode kenyamanan di ControllerBase kelas dapat digunakan untuk mengembalikan ActionResult
jenis dari tindakan. Misalnya, return BadRequest();
adalah bentuk singkatan dari return new BadRequestResult();
.
Karena ada beberapa jenis pengembalian dan jalur dalam jenis tindakan ini, penggunaan [ProducesResponseType]
liberal atribut diperlukan. Atribut ini menghasilkan detail respons yang lebih deskriptif untuk halaman bantuan API web yang dihasilkan oleh alat seperti Swagger. [ProducesResponseType]
menunjukkan jenis yang diketahui dan kode status HTTP yang akan dikembalikan oleh tindakan.
Tindakan sinkron
Pertimbangkan tindakan sinkron berikut di mana ada dua jenis pengembalian yang mungkin:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}
return Ok(product);
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk yang diwakili oleh
id
tidak ada di penyimpanan data yang mendasar. Metode NotFound kenyamanan dipanggil sebagai singkatan darireturn new NotFoundResult();
. - Kode status 200 dikembalikan dengan
Product
objek ketika produk memang ada. Metode Ok kenyamanan dipanggil sebagai singkatan darireturn new OkObjectResult(product);
.
Tindakan asinkron
Pertimbangkan tindakan asinkron berikut di mana ada dua jenis pengembalian yang mungkin:
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
await _repository.AddProductAsync(product);
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 dikembalikan ketika deskripsi produk berisi "Widget XYZ". Metode BadRequest kenyamanan dipanggil sebagai singkatan dari
return new BadRequestResult();
. - Kode status 201 dihasilkan oleh CreatedAtAction metode kenyamanan saat produk dibuat. Alternatif untuk panggilan
CreatedAtAction
adalahreturn new CreatedAtActionResult(nameof(GetById), "Products", new { id = product.Id }, product);
. Dalam jalur kode ini,Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Misalnya, model berikut menunjukkan bahwa permintaan harus menyertakan Name
properti dan Description
. Kegagalan untuk menyediakan Name
dan Description
dalam permintaan menyebabkan validasi model gagal.
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public bool IsOnSale { get; set; }
}
[ApiController]
Jika atribut diterapkan, kesalahan validasi model menghasilkan kode status 400. Untuk informasi selengkapnya, lihat Respons HTTP 400 otomatis.
ActionResult vs IActionResult
Bagian berikut dibandingkan dengan ActionResult
IActionResult
Jenis T> ActionResult<
ASP.NET Core menyertakan jenis pengembalian ActionResult<T> untuk tindakan pengontrol API web. Ini memungkinkan Anda mengembalikan jenis yang berasal dari ActionResult atau mengembalikan jenis tertentu. ActionResult<T>
menawarkan manfaat berikut atas jenis IActionResult:
[ProducesResponseType]
Properti atributType
dapat dikecualikan. Misalnya,[ProducesResponseType(200, Type = typeof(Product))]
disederhanakan ke[ProducesResponseType(200)]
. Jenis pengembalian tindakan yang diharapkan malah disimpulkanT
dari dalamActionResult<T>
.- Operator cast implisit mendukung konversi baik
T
danActionResult
keActionResult<T>
.T
mengonversi ke ObjectResult, yang berartireturn new ObjectResult(T);
disederhanakan kereturn T;
.
C# tidak mendukung operator cast implisit pada antarmuka. Akibatnya, konversi antarmuka ke jenis beton diperlukan untuk menggunakan ActionResult<T>
. Misalnya, penggunaan IEnumerable
dalam contoh berikut tidak berfungsi:
[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
_repository.GetProducts();
Salah satu opsi untuk memperbaiki kode sebelumnya adalah mengembalikan _repository.GetProducts().ToList();
.
Sebagian besar tindakan memiliki jenis pengembalian tertentu. Kondisi tak terduga dapat terjadi selama eksekusi tindakan, dalam hal ini jenis tertentu tidak dikembalikan. Misalnya, parameter input tindakan mungkin gagal dalam validasi model. Dalam kasus seperti itu, adalah umum untuk mengembalikan jenis yang sesuai ActionResult
alih-alih jenis tertentu.
Tindakan sinkron
Pertimbangkan tindakan sinkron di mana ada dua jenis pengembalian yang mungkin:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}
return product;
}
Dalam tindakan sebelumnya:
- Kode status 404 dikembalikan ketika produk tidak ada di database.
- Kode status 200 dikembalikan dengan objek yang
Product
sesuai ketika produk memang ada.
Tindakan asinkron
Pertimbangkan tindakan asinkron di mana ada dua jenis pengembalian yang mungkin:
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
await _repository.AddProductAsync(product);
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
Dalam tindakan sebelumnya:
- Kode status 400 (BadRequest) dikembalikan oleh runtime ASP.NET Core saat:
- Atribut
[ApiController]
telah diterapkan dan validasi model gagal. - Deskripsi produk berisi "Widget XYZ".
- Atribut
- Kode status 201 dihasilkan oleh CreatedAtAction metode saat produk dibuat. Dalam jalur kode ini,
Product
objek disediakan dalam isi respons.Location
Header respons yang berisi URL produk yang baru dibuat disediakan.
Sumber Daya Tambahan:
ASP.NET Core
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk