ASP.NET Core Web API のコントローラー アクションの戻り値の型Controller action return types in ASP.NET Core Web API

作成者: Scott AddieBy Scott Addie

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

ASP.NET Core では、Web API コントローラー アクションの戻り値の型に次のオプションを提供しています。ASP.NET Core offers the following options for Web API controller action return types:

このドキュメントでは、各戻り値の型を使用するのが最適な場合について説明します。This document explains when it's most appropriate to use each return type.

特定の型Specific type

最もシンプルなアクションでは、プリミティブ データ型または複合データ型が返されます (string やカスタム オブジェクトの型など)。The simplest action returns a primitive or complex data type (for example, string or a custom object type). カスタム Product オブジェクトのコレクションを返す次のアクションを考えてみましょう。Consider the following action, which returns a collection of custom Product objects:

[HttpGet]
public IEnumerable<Product> Get()
{
    return _repository.GetProducts();
}

アクションの実行中に保護できる既知の条件がない場合は、特定の型を返すだけで十分です。Without known conditions to safeguard against during action execution, returning a specific type could suffice. 前のアクションでパラメーターを受け取っていないので、パラメーターの制約の検証は必要ありません。The preceding action accepts no parameters, so parameter constraints validation isn't needed.

アクションで既知の条件を考慮する必要がある場合は、複数の戻り値のパスが導入されます。When known conditions need to be accounted for in an action, multiple return paths are introduced. このような場合、ActionResult の戻り値の型とプリミティブまたは複合の戻り値の型を混在させるのが一般的です。In such a case, it's common to mix an ActionResult return type with the primitive or complex return type. この種類のアクションに対応するには、IActionResult または ActionResult<T> のいずれかが必要です。Either IActionResult or ActionResult<T> are necessary to accommodate this type of action.

IActionResult 型IActionResult type

IActionResult の戻り値の型は、アクションで複数の ActionResult の戻り値の型が可能な場合に適しています。The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. ActionResult 型は、さまざまな HTTP 状態コードを表します。The ActionResult types represent various HTTP status codes. このカテゴリに当てはまる一般的な戻り値の型には、BadRequestResult (400)、NotFoundResult (404)、OkObjectResult (200) などがあります。Some common return types falling into this category are BadRequestResult (400), NotFoundResult (404), and OkObjectResult (200).

アクションには複数の戻り値の型とパスがあるため、[ProducesResponseType] 属性を十分に使える必要があります。Because there are multiple return types and paths in the action, liberal use of the [ProducesResponseType] attribute is necessary. この属性は、Swagger などのツールで生成される API ヘルプ ページのよりわかりやすい応答の詳細を生成します。This attribute produces more descriptive response details for API help pages generated by tools like Swagger. [ProducesResponseType] は、アクションによって返される既知の型と HTTP 状態コードを示します。[ProducesResponseType] indicates the known types and HTTP status codes to be returned by the action.

同期アクションSynchronous action

2 つの戻り値の型が考えられる、次の同期アクションを考えてみましょう。Consider the following synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(200, Type = typeof(Product))]
[ProducesResponseType(404)]
public IActionResult GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return Ok(product);
}

前のアクションでは、id によって表される製品が、基になるデータ ストアに存在しないと、404 状態コードが返されます。In the preceding action, a 404 status code is returned when the product represented by id doesn't exist in the underlying data store. return new NotFoundResult(); へのショートカットとして、NotFound ヘルパー メソッドが呼び出されます。The NotFound helper method is invoked as a shortcut to return new NotFoundResult();. 製品が存在する場合は、ペイロードを表す Product オブジェクトが、200 状態コードと共に返されます。If the product does exist, a Product object representing the payload is returned with a 200 status code. Ok ヘルパー メソッドは、return new OkObjectResult(product); の短縮形式として呼び出されます。The Ok helper method is invoked as the shorthand form of return new OkObjectResult(product);.

非同期アクションAsynchronous action

2 つの戻り値の型が考えられる、次の非同期アクションを考えてみましょう。Consider the following asynchronous action in which there are two possible return types:

[HttpPost]
[ProducesResponseType(201, Type = typeof(Product))]
[ProducesResponseType(400)]
public async Task<IActionResult> CreateAsync([FromBody] Product product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    await _repository.AddProductAsync(product);

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

前のアクションでは、モデルの検証に失敗し、BadRequest ヘルパー メソッドが呼び出されるときに、400 状態コードが返されます。In the preceding action, a 400 status code is returned when model validation fails and the BadRequest helper method is invoked. たとえば、次のモデルでは、要求で Name プロパティと値を提供する必要があることを示しています。For example, the following model indicates that requests must provide the Name property and a value. そのため、要求で適切な Name を提供するのに失敗すると、モデルの検証が失敗します。Therefore, failure to provide a proper Name in the request causes model validation to fail.

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

前のアクションのその他の既知のリターン コードは、CreatedAtAction ヘルパー メソッドで生成される 201 です。The preceding action's other known return code is a 201, which is generated by the CreatedAtAction helper method. このパスでは、Product オブジェクトが返されます。In this path, the Product object is returned.

ActionResult<T> 型ActionResult<T> type

ASP.NET Core 2.1 では、Web API コントローラー アクションに対して、ActionResult<T> の戻り値の型が導入されました。ASP.NET Core 2.1 introduces the ActionResult<T> return type for Web API controller actions. これにより、ActionResult から派生する型、または特定の型を返すことができます。It enables you to return a type deriving from ActionResult or return a specific type. ActionResult<T> により、IActionResult 型は次の利点を得られます。ActionResult<T> offers the following benefits over the IActionResult type:

  • [ProducesResponseType] 属性の Type プロパティを除外することができます。The [ProducesResponseType] attribute's Type property can be excluded. たとえば、[ProducesResponseType(200, Type = typeof(Product))][ProducesResponseType(200)] に簡略化されます。For example, [ProducesResponseType(200, Type = typeof(Product))] is simplified to [ProducesResponseType(200)]. アクションの予期される戻り値の型は、代わりに ActionResult<T>T から推論されます。The action's expected return type is instead inferred from the T in ActionResult<T>.
  • 暗黙的なキャスト演算子は、TActionResult の両方の ActionResult<T> への変換をサポートしています。Implicit cast operators support the conversion of both T and ActionResult to ActionResult<T>. TObjectResult に変換されます。つまり、return new ObjectResult(T);return T; に簡略化されます。T converts to ObjectResult, which means return new ObjectResult(T); is simplified to return T;.

C# はインターフェイス上での暗黙的なキャスト演算子をサポートしていません。C# doesn't support implicit cast operators on interfaces. そのため、ActionResult<T> を使用するには、インターフェイスを具象型に変換する必要があります。Consequently, conversion of the interface to a concrete type is necessary to use ActionResult<T>. たとえば、次の例における IEnumerable の使用は機能しません。For example, use of IEnumerable in the following example doesn't work:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get()
{
    return _repository.GetProducts();
}

上記のコードを修正するための選択肢の 1 つは、_repository.GetProducts().ToList(); を返すことです。One option to fix the preceding code is to return _repository.GetProducts().ToList();.

ほとんどのアクションには、特定の戻り値の型があります。Most actions have a specific return type. アクションの実行中に予期しない状態が発生する場合、特定の型は返されません。Unexpected conditions can occur during action execution, in which case the specific type isn't returned. たとえば、アクションの入力パラメーターがモデルの検証に失敗する場合があります。For example, an action's input parameter may fail model validation. このような場合、通常は特定の型ではなく、適切な ActionResult 型が返されます。In such a case, it's common to return the appropriate ActionResult type instead of the specific type.

同期アクションSynchronous action

2 つの戻り値の型が考えられる、同期アクションを考えてみましょう。Consider a synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public ActionResult<Product> GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return product;
}

上記のコードでは、データベースに製品が存在しない場合に 404 状態コードが返されます。In the preceding code, a 404 status code is returned when the product doesn't exist in the database. 製品が存在する場合は、対応する Product オブジェクトが返されます。If the product does exist, the corresponding Product object is returned. ASP.NET Core 2.1 より前のバージョンでは、return product; 行は return Ok(product); になっていました。Before ASP.NET Core 2.1, the return product; line would have been return Ok(product);.

ヒント

ASP.NET Core 2.1 以降では、コントローラー クラスが [ApiController] 属性で修飾されていると、アクション パラメーター バインディング ソースの推論が有効になります。As of ASP.NET Core 2.1, action parameter binding source inference is enabled when a controller class is decorated with the [ApiController] attribute. ルート テンプレート内の名前と一致するパラメーター名は、要求のルート データを使用して自動的にバインドされます。A parameter name matching a name in the route template is automatically bound using the request route data. したがって、前のアクションの id パラメーターは、[FromRoute] 属性を使用して明示的に注釈付けされません。Consequently, the preceding action's id parameter isn't explicitly annotated with the [FromRoute] attribute.

非同期アクションAsynchronous action

2 つの戻り値の型が考えられる、非同期アクションを考えてみましょう。Consider an asynchronous action in which there are two possible return types:

[HttpPost]
[ProducesResponseType(201)]
[ProducesResponseType(400)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    await _repository.AddProductAsync(product);

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

モデルの検証に失敗すると、BadRequest メソッドが呼び出され、400 状態コードが返されます。If model validation fails, the BadRequest method is invoked to return a 400 status code. 特定の検証エラーを含む ModelState プロパティが渡されます。The ModelState property containing the specific validation errors is passed to it. モデルの検証に成功すると、データベースに製品が作成されます。If model validation succeeds, the product is created in the database. 201 状態コードが返されます。A 201 status code is returned.

ヒント

ASP.NET Core 2.1 以降では、コントローラー クラスが [ApiController] 属性で修飾されていると、アクション パラメーター バインディング ソースの推論が有効になります。As of ASP.NET Core 2.1, action parameter binding source inference is enabled when a controller class is decorated with the [ApiController] attribute. 複合型パラメーターは、要求本文を使用して自動的にバインドされます。Complex type parameters are automatically bound using the request body. したがって、前のアクションの product パラメーターは、[FromBody] 属性を使用して明示的に注釈付けされません。Consequently, the preceding action's product parameter isn't explicitly annotated with the [FromBody] attribute.

その他の技術情報Additional resources