使用 ASP.NET Core 建立 Web APICreate web APIs with ASP.NET Core

作者:Scott AddieTom DykstraBy Scott Addie and Tom Dykstra

ASP.NET Core 支援使用 C# 建立 RESTful 服務,也稱為 Web API。ASP.NET Core supports creating RESTful services, also known as web APIs, using C#. 若要處理要求,Web API 會使用控制器。To handle requests, a web API uses controllers. Web API 中的「控制器」都衍生自類別 ControllerBaseControllers in a web API are classes that derive from ControllerBase. 此文章說明如何使用控制器來處理 API 要求。This article shows how to use controllers for handling API requests.

檢視或下載範例程式碼View or download sample code. (如何下載)。(How to download).

ControllerBase 類別ControllerBase class

Web API 有一或多個衍生自 ControllerBase 的控制器類別。A web API has one or more controller classes that derive from ControllerBase. 例如,Web API 專案範本會建立值控制器:For example, the web API project template creates a Values controller:

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

請不要從 Controller 基底類別衍生以建立 Web API 控制器。Don't create a web API controller by deriving from the Controller base class. Controller 衍生自 ControllerBase 並會新增檢視支援,以供處理網頁,而不是 Web API 要求。Controller derives from ControllerBase and adds support for views, so it's for handling web pages, not web API requests. 此規則的例外:如果您打算為檢視和 API 使用相同的控制器,請從 Controller 衍生該控制器。There's an exception to this rule: if you plan to use the same controller for both views and APIs, derive it from Controller.

ControllerBase 類別提供許多處理 HTTP 要求的實用屬性和方法。The ControllerBase class provides many properties and methods that are useful for handling HTTP requests. 例如,ControllerBase.CreatedAtAction 會傳回 201 狀態碼:For example, ControllerBase.CreatedAtAction returns a 201 status code:

[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);
}

以下是 ControllerBase 提供的一些其他方法範例。Here are some more examples of methods that ControllerBase provides.

方法Method 注意Notes
BadRequest 傳回 400 狀態碼。Returns 400 status code.
NotFound 傳回 404 狀態碼。Returns 404 status code.
PhysicalFile 傳回檔案。Returns a file.
TryUpdateModelAsync 叫用模型繫結Invokes model binding.
TryValidateModel 叫用模型驗證Invokes model validation.

如需所有可用方法和屬性的清單,請參閱 ControllerBaseFor a list of all available methods and properties, see ControllerBase.

屬性Attributes

Microsoft.AspNetCore.Mvc 命名空間提供的屬性,可用來設定 Web API 控制器和動作方法的行為。The Microsoft.AspNetCore.Mvc namespace provides attributes that can be used to configure the behavior of web API controllers and action methods. 下列範例會使用屬性來指定接受的 HTTP 方法和傳回的狀態碼:The following example uses attributes to specify the HTTP method accepted and the status codes returned:

[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);
}

以下是一些其他可用的屬性範例。Here are some more examples of attributes that are available.

屬性Attribute 注意Notes
[Route][Route] 指定控制器或動作的 URL 模式。Specifies URL pattern for a controller or action.
[Bind][Bind] 指定模型繫結要包含的前置詞和屬性。Specifies prefix and properties to include for model binding.
[HttpGet][HttpGet] 識別支援 HTTP GET 方法的動作。Identifies an action that supports the HTTP GET method.
[Consumes][Consumes] 指定動作所接受的資料類型。Specifies data types that an action accepts.
[Produces][Produces] 指定動作所傳回的資料類型。Specifies data types that an action returns.

如需包含可用屬性的清單,請參閱 Microsoft.AspNetCore.Mvc 命名空間。For a list that includes the available attributes, see the Microsoft.AspNetCore.Mvc namespace.

ApiController 屬性ApiController attribute

[ApiController] 屬性可以套用至控制器類別,以啟用 API 特定行為:The [ApiController] attribute can be applied to a controller class to enable API-specific behaviors:

這些功能都需要相容性版本 2.1 或更新版本。These features require a compatibility version of 2.1 or later.

特定控制站上的 ApiControllerApiController on specific controllers

[ApiController] 屬性可以套用至特定的控制器,如專案範本中的下列範例所示:The [ApiController] attribute can be applied to specific controllers, as in the following example from the project template:

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

多個控制站上的 ApiControllerApiController on multiple controllers

在多個控制站上使用同一屬性的方法之一,就是建立以 [ApiController] 屬性標註的自訂基底控制器類別。One approach to using the attribute on more than one controller is to create a custom base controller class annotated with the [ApiController] attribute. 以下範例顯示自訂的基底類別和從它衍生的控制站:Here's an example showing a custom base class and a controller that derives from it:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces("application/json")]
[Route("api/[controller]")]
public class PetsController : MyControllerBase

組件上的 ApiControllerApiController on an assembly

如果相容性版本設定為 2.2 或更新版本,[ApiController] 屬性就可以套用至組件。If compatibility version is set to 2.2 or later, the [ApiController] attribute can be applied to an assembly. 以這種方式標註會將 Web API 行為套用至組件中的所有控制器。Annotation in this manner applies web API behavior to all controllers in the assembly. 沒有任何方法可以退出個別控制器。There's no way to opt out for individual controllers. Startup 組件層級屬性套用至類別,如下列範例所示:Apply the assembly-level attribute to the Startup class as shown in the following example:

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

屬性路由需求Attribute routing requirement

ApiController 屬性會讓屬性路由需求。The ApiController attribute makes attribute routing a requirement. 例如:For example:

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

無法透過 UseMvc 中所定義的慣例路由Startup.Configure 中的 UseMvcWithDefaultRoute 來存取動作。Actions are inaccessible via conventional routes defined by UseMvc or UseMvcWithDefaultRoute in Startup.Configure.

HTTP 400 自動回應Automatic HTTP 400 responses

ApiController 屬性會讓模型驗證錯誤自動觸發 HTTP 400 回應。The ApiController attribute makes model validation errors automatically trigger an HTTP 400 response. 因此,動作方法不再需要下列程式碼:Consequently, the following code is unnecessary in an action method:

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

預設 BadRequest 回應Default BadRequest response

使用 2.2 或更新版本的相容性版本,HTTP 400 回應的預設回應類型為 ValidationProblemDetailsWith a compatibility version of 2.2 or later, the default response type for HTTP 400 responses is ValidationProblemDetails. ValidationProblemDetails 類型符合 RFC 7807 規格The ValidationProblemDetails type complies with the RFC 7807 specification.

若要變更 SerializableError 的預設回應,請在 Startup.ConfigureServices 中將 SuppressUseValidationProblemDetailsForInvalidModelStateResponses 屬性設定為 true,如下列範例所示:To change the default response to SerializableError, set the SuppressUseValidationProblemDetailsForInvalidModelStateResponses property to true in Startup.ConfigureServices, as shown in the following example:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

自訂 BadRequest 回應Customize BadRequest response

若要自訂驗證錯誤所產生的回應,請使用 InvalidModelStateResponseFactoryTo customize the response that results from a validation error, use InvalidModelStateResponseFactory. services.AddMvc().SetCompatibilityVersion 後面,新增下列醒目提示程式碼:Add the following highlighted code after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.InvalidModelStateResponseFactory = context =>
        {
            var problemDetails = new ValidationProblemDetails(context.ModelState)
            {
                Type = "https://contoso.com/probs/modelvalidation",
                Title = "One or more model validation errors occurred.",
                Status = StatusCodes.Status400BadRequest,
                Detail = "See the errors property for details.",
                Instance = context.HttpContext.Request.Path
            };

            return new BadRequestObjectResult(problemDetails)
            {
                ContentTypes = { "application/problem+json" }
            };
        };
    });

記錄自動 400 回應Log automatic 400 responses

請參閱如何在模型驗證錯誤上記錄自動 400 回應 (aspnet/AspNetCore.Docs #12157) (英文)。See How to log automatic 400 responses on model validation errors (aspnet/AspNetCore.Docs #12157).

停用自動 400Disable automatic 400

若要停用自動 400 行為,請將 SuppressModelStateInvalidFilter 屬性設定為 trueTo disable the automatic 400 behavior, set the SuppressModelStateInvalidFilter property to true. services.AddMvc().SetCompatibilityVersion 後面的 Startup.ConfigureServices 中,新增下列醒目提示程式碼:Add the following highlighted code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

繫結來源參數推斷Binding source parameter inference

繫結來源屬性可定義動作參數值的所在位置。A binding source attribute defines the location at which an action parameter's value is found. 系統提供下列繫結來源屬性:The following binding source attributes exist:

屬性Attribute 繫結來源Binding source
[FromBody][FromBody] 要求本文Request body
[FromForm][FromForm] 要求本文中的表單資料Form data in the request body
[FromHeader][FromHeader] 要求標頭Request header
[FromQuery][FromQuery] 要求查詢字串參數Request query string parameter
[FromRoute][FromRoute] 來自目前要求的路由資料Route data from the current request
[FromServices][FromServices] 作為動作參數插入的要求服務The request service injected as an action parameter

警告

當值可能包含 %2f (也就是 /) 時,請勿使用 [FromRoute]Don't use [FromRoute] when values might contain %2f (that is /). %2f 不會是未逸出的 /%2f won't be unescaped to /. 如果值可能包含 %2f,請使用 [FromQuery]Use [FromQuery] if the value might contain %2f.

若沒有 [ApiController] 屬性或繫結來源屬性 (例如 [FromQuery]),ASP.NET Core 執行階段會嘗試使用複雜物件模型繫結器。Without the [ApiController] attribute or binding source attributes like [FromQuery], the ASP.NET Core runtime attempts to use the complex object model binder. 複雜物件模型繫結器會以定義的順序從值提供者提取資料。The complex object model binder pulls data from value providers in a defined order.

在下列範例中,[FromQuery] 屬性表示 discontinuedOnly 參數值是在要求 URL 查詢字串中提供:In the following example, the [FromQuery] attribute indicates that the discontinuedOnly parameter value is provided in the request URL's query string:

[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;
}

[ApiController] 屬性會依據動作參數的預設資料來源套用推斷規則。The [ApiController] attribute applies inference rules for the default data sources of action parameters. 這些規則透過將屬性套用至動作參數,讓您不必以手動方式識別的繫結來源。These rules save you from having to identify binding sources manually by applying attributes to the action parameters. 繫結來源推斷規則的行為如下所示:The binding source inference rules behave as follows:

  • 系統會依據複雜類型參數推斷 [FromBody][FromBody] is inferred for complex type parameters. 如果是任何具有像是 IFormCollectionCancellationToken 等特殊意義的複雜內建類型,則為 [FromBody] 推斷規則的例外。An exception to the [FromBody] inference rule is any complex, built-in type with a special meaning, such as IFormCollection and CancellationToken. 繫結來源推斷程式碼會忽略這些特殊的類型。The binding source inference code ignores those special types.
  • [FromForm] 針對類型 IFormFileIFormFileCollection 的動作參數推斷的。[FromForm] is inferred for action parameters of type IFormFile and IFormFileCollection. 而不會依據任何簡單或使用者定義的類型進行推斷。It's not inferred for any simple or user-defined types.
  • 系統會依據符合路由範本參數的任何動作參數名稱推斷 [FromRoute][FromRoute] is inferred for any action parameter name matching a parameter in the route template. 如果有多個路由符合動作參數,則會將任何路由值視為 [FromRoute]When more than one route matches an action parameter, any route value is considered [FromRoute].
  • 系統會依據任何其他動作參數推斷 [FromQuery][FromQuery] is inferred for any other action parameters.

FromBody 推斷備註FromBody inference notes

並不會為像是 stringint 等簡單型別,推斷 [FromBody][FromBody] isn't inferred for simple types such as string or int. 因此,當需要使用該功能時,應為簡單型別使用 [FromBody] 屬性。Therefore, the [FromBody] attribute should be used for simple types when that functionality is needed.

當動作有多個參數從要求主體繫結時,會擲回例外狀況。When an action has more than one parameter bound from the request body, an exception is thrown. 例如,下列所有動作方法簽章都會造成例外狀況:For example, all of the following action method signatures cause an exception:

  • 因兩個參數都是複雜類型,而推斷 [FromBody][FromBody] inferred on both because they're complex types.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • 因為其為複雜類型,所以一個有 [FromBody] 屬性,而推斷另一個。[FromBody] attribute on one, inferred on the other because it's a complex type.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • 兩者均有 [FromBody] 屬性。[FromBody] attribute on both.

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

注意

在 ASP.NET Core 2.1 中,集合類型參數 (例如清單與陣列) 不正確地推斷為 [FromQuery]In ASP.NET Core 2.1, collection type parameters such as lists and arrays are incorrectly inferred as [FromQuery]. [FromBody] 屬性應該用於這些參數 (若它們將從要求本文繫結)。The [FromBody] attribute should be used for these parameters if they are to be bound from the request body. 此行為在 ASP.NET Core 2.2 或更新版本中已修正,其中集合類型參數預設推斷為從本文繫結。This behavior is corrected in ASP.NET Core 2.2 or later, where collection type parameters are inferred to be bound from the body by default.

停用推斷規則Disable inference rules

若要停用繫結來源推斷,請將 SuppressInferBindingSourcesForParameters 設定為 trueTo disable binding source inference, set SuppressInferBindingSourcesForParameters to true. services.AddMvc().SetCompatibilityVersion 後,於 Startup.ConfigureServices 中新增下列程式碼:Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

多部分/表單資料要求推斷Multipart/form-data request inference

當以 [FromForm] 屬性標註動作參數,而 [ApiController] 屬性套用推斷規則時:會推斷 multipart/form-data 要求內容類型。The [ApiController] attribute applies an inference rule when an action parameter is annotated with the [FromForm] attribute: the multipart/form-data request content type is inferred.

若要停用預設行為,請在 Startup.ConfigureServices 中將 SuppressConsumesConstraintForFormFileParameters 設定為 true,如下列範例所示:To disable the default behavior, set SuppressConsumesConstraintForFormFileParameters to true in Startup.ConfigureServices, as shown in the following example:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

錯誤狀態碼的問題詳細資料Problem details for error status codes

當相容性版本為 2.2 或更新版本時,MVC 會將錯誤結果 (具有狀態碼 400 以上的結果) 為具有 ProblemDetails 的結果。When the compatibility version is 2.2 or later, MVC transforms an error result (a result with status code 400 or higher) to a result with ProblemDetails. RFC 7807 規格為基礎的 ProblemDetails 類型,在 HTTP 回應中提供電腦可讀取的錯誤詳細資料。The ProblemDetails type is based on the RFC 7807 specification for providing machine-readable error details in an HTTP response.

請考慮下列控制器動作中的程式碼:Consider the following code in a controller action:

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

NotFound 的 HTTP 回應具有 404 狀態碼,並附有 ProblemDetails 本文。The HTTP response for NotFound has a 404 status code with a ProblemDetails body. 例如:For example:

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

自訂 ProblemDetails 回應Customize ProblemDetails response

使用 ClientErrorMapping 屬性可設定 ProblemDetails 回應的內容。Use the ClientErrorMapping property to configure the contents of the ProblemDetails response. 舉例來說,下列程式碼會更新 404 回應的 type 屬性:For example, the following code updates the type property for 404 responses:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

停用 ProblemDetails 回應Disable ProblemDetails response

ProblemDetails 屬性設定為 SuppressMapClientErrors 時,會停用自動建立 trueThe automatic creation of ProblemDetails is disabled when the SuppressMapClientErrors property is set to true. 將下列程式碼加入 Startup.ConfigureServicesAdd the following code in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

其他資源Additional resources