Tworzenie internetowych interfejsów API za pomocą platformy ASP.NET Core

ASP.NET Core obsługuje tworzenie internetowych interfejsów API przy użyciu kontrolerów lub minimalnych interfejsów API. Kontrolery w internetowym interfejsie API to klasy pochodne klasy ControllerBase. Kontrolery są aktywowane i usuwane na zasadzie każdego żądania.

W tym artykule pokazano, jak używać kontrolerów do obsługi żądań internetowego interfejsu API. Aby uzyskać informacje na temat tworzenia internetowych interfejsów API bez kontrolerów, zobacz Samouczek: tworzenie minimalnego interfejsu API przy użyciu platformy ASP.NET Core.

Ważne

Począwszy od ASP.NET Core 10, znane punkty końcowe API nie przekierowują już do stron logowania podczas korzystania z cookie uwierzytelniania. Zamiast tego zwracają kody stanu 401/403. Aby uzyskać szczegółowe informacje, zobacz Zachowanie uwierzytelniania punktu końcowego interfejsu API w programie ASP.NET Core.

Klasa ControllerBase

Internetowy interfejs API oparty na kontrolerze składa się z co najmniej jednej klasy kontrolera pochodnej od klasy ControllerBase. Szablon projektu internetowego interfejsu API udostępnia kontroler startowy:

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

Kontrolery internetowego interfejsu API powinny zwykle być pochodnymi klasy ControllerBase, a nie Controller. Klasa Controller jest pochodną klasy ControllerBase i dodano w niej obsługę widoków, dlatego jest przeznaczona do obsługi stron internetowych, a nie żądań internetowego interfejsu API. Jeśli ten sam kontroler musi obsługiwać widoki i internetowe interfejsy API, powinien być pochodną klasy Controller.

Klasa ControllerBase udostępnia wiele właściwości i metod, które są przydatne do obsługi żądań HTTP. Na przykład CreatedAtAction zwraca kod stanu 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);
}

Poniższa tabela zawiera przykłady metod w klasie ControllerBase.

Method Notes
BadRequest Zwraca kod stanu 400.
NotFound Zwraca kod stanu 404.
PhysicalFile Zwraca plik.
TryUpdateModelAsync Wywołuje powiązanie modelu.
TryValidateModel Wywołuje weryfikację modelu.

Aby uzyskać listę wszystkich dostępnych metod i właściwości, zobacz ControllerBase.

Attributes

Przestrzeń nazw Microsoft.AspNetCore.Mvc udostępnia atrybuty, których można użyć do skonfigurowania zachowania kontrolerów internetowego interfejsu API i metod akcji. W poniższym przykładzie użyto atrybutów do określenia obsługiwanego polecenia akcji HTTP i wszystkich znanych kodów stanu HTTP, które mogą zostać zwrócone:

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

Poniżej przedstawiono więcej przykładów dostępnych atrybutów.

Attribute Notes
[Route] Określa wzorzec adresu URL dla kontrolera lub akcji.
[Bind] Określa prefiks i właściwości do uwzględnienia dla powiązania modelu.
[HttpGet] Identyfikuje akcję, która obsługuje polecenie akcji HTTP GET.
[Consumes] Określa typy danych, które akceptuje akcja.
[Produces] Określa typy danych zwracane przez akcję.

Aby uzyskać listę zawierającą dostępne atrybuty, zobacz przestrzeń nazw Microsoft.AspNetCore.Mvc.

Atrybut ApiController

Atrybut [ApiController] można zastosować do klasy kontrolera w celu umożliwienia następujących zachowań specyficznych dla interfejsu API:

Atrybut w przypadku określonych kontrolerów

Atrybut [ApiController] można zastosować do określonych kontrolerów, jak w poniższym przykładzie z szablonu projektu:

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

Atrybut w przypadku wielu kontrolerów

Jednym z rozwiązań pozwalających na używanie atrybutu na więcej niż jednym kontrolerze jest utworzenie niestandardowej klasy kontrolera podstawowego oznaczonej atrybutem [ApiController]. W poniższym przykładzie przedstawiono niestandardową klasę bazową i kontroler, który jest jej pochodną:

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

Atrybut zestawu

Atrybut [ApiController] można zastosować do zestawu. Po zastosowaniu atrybutu [ApiController] do zestawu wszystkie kontrolery w zestawie mają zastosowany atrybut [ApiController]. Nie ma możliwości wyłączenie z tego poszczególnych kontrolerów. Zastosuj atrybut na poziomie zestawu do pliku 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();

Wymaganie dotyczące routingu atrybutów

Atrybut [ApiController] wymusza użycie routingu atrybutów. Przykład:

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

Akcje są niedostępne za pośrednictwem konwencjonalnych tras zdefiniowanych przez UseEndpoints, UseMvc lub UseMvcWithDefaultRoute.

Automatyczne odpowiedzi HTTP 400

Atrybut [ApiController] sprawia, że błędy weryfikacji modelu automatycznie wyzwalają odpowiedź HTTP 400. W związku z tym następujący kod jest niepotrzebny w metodzie akcji:

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

ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do sprawdzenia poprzednich warunków.

Domyślna odpowiedź BadRequest

Domyślnym typem odpowiedzi dla odpowiedzi HTTP 400 jest ValidationProblemDetails. Następująca treść odpowiedzi jest przykładem typu serializowanego:

{
  "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."
    ]
  }
}

Typ ValidationProblemDetails:

  • Udostępnia format czytelny dla komputera do określania błędów w odpowiedziach internetowego interfejsu API.
  • Jest zgodny ze specyfikacją RFC 7807.

Aby zapewnić spójność odpowiedzi automatycznych i niestandardowych, wywołaj metodę ValidationProblem zamiast BadRequest. ValidationProblem zwraca obiekt ValidationProblemDetails, a także odpowiedź automatyczną.

Automatyczne rejestrowanie odpowiedzi 400

Aby zarejestrować automatyczne odpowiedzi 400, ustaw właściwość delegata InvalidModelStateResponseFactory na wykonywanie przetwarzania niestandardowego. Domyślnie InvalidModelStateResponseFactory używa ProblemDetailsFactory do utworzenia wystąpienia ValidationProblemDetails.

W poniższym przykładzie pokazano, jak pobrać wystąpienie ILogger<TCategoryName>, aby zarejestrować informacje o odpowiedzi automatycznej 400:

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();

Wyłącz automatyczną odpowiedź 400

Aby wyłączyć automatyczne zachowanie 400, ustaw właściwość SuppressModelStateInvalidFilter na true. Dodaj następujący wyróżniony kod:

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();

Wnioskowanie parametru źródła powiązania

Atrybut obiektu źródłowego powiązania definiuje lokalizację, w której znajduje się wartość parametru akcji. Istnieją następujące atrybuty obiektu źródłowego powiązania:

Attribute Źródło powiązania
[FromBody] Ciało żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Przekazywanie danych z bieżącego żądania
[FromServices] Usługa żądania zastosowana jako parametr akcji
[AsParameters] Parametry metody

Warning

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie zostanie przekształcone na /. Użyj [FromQuery], jeśli wartość może zawierać %2f.

Bez atrybutu [ApiController] lub atrybutów źródłowych wiązania, takich jak [FromQuery], środowisko uruchomieniowe ASP.NET Core próbuje użyć mechanizmu wiązania złożonego modelu obiektowego. Integrator modelu obiektów złożonych ściąga dane od dostawców wartości w zdefiniowanej kolejności.

W poniższym przykładzie atrybut [FromQuery] wskazuje, że wartość parametru discontinuedOnly jest podana w ciągu zapytania adresu URL żądania:

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

Atrybut [ApiController] stosuje reguły wnioskowania dla domyślnych źródeł danych parametrów akcji. Te reguły eliminują konieczność ręcznego identyfikowania źródeł powiązań przez stosowanie atrybutów do parametrów akcji. Reguły wnioskowania źródła powiązania zachowują się w następujący sposób:

  • [FromServices] jest wnioskowane dla parametrów typu złożonego zarejestrowanych w kontenerze DI.
  • [FromBody] jest inferowane dla parametrów typu złożonego, które nie zostały zarejestrowane w kontenerze DI. Wyjątkiem od reguły wnioskowania [FromBody] jest dowolny złożony typ wbudowany ze specjalnym znaczeniem, taki jak IFormCollection i CancellationToken. Kod wnioskowania dla źródła wiązania ignoruje te specjalne typy.
  • [FromForm] jest wnioskowane dla parametrów akcji typu IFormFile i IFormFileCollection. To wnioskowanie nie jest realizowane dla żadnych typów prostych ani zdefiniowanych przez użytkownika.
  • [FromRoute] jest wnioskowane dla dowolnej nazwy parametru akcji zgodnej z parametrem w szablonie trasy. Gdy więcej niż jedna trasa jest zgodna z parametrem akcji, dowolna wartość trasy jest uznawana za [FromRoute].
  • [FromQuery] jest wywnioskowane dla każdego innego parametru akcji.

Uwagi dotyczące wnioskowania FromBody

[FromBody] nie jest wnioskowane dla typów prostych, takich jak string lub int. W związku z tym w przypadku typów prostych, gdy ta funkcja jest potrzebna, powinien być używany atrybut [FromBody].

Jeśli akcja ma więcej niż jeden parametr powiązany z treścią żądania, zgłaszany jest wyjątek. Na przykład wszystkie następujące sygnatury metod akcji powodują wyjątek:

  • [FromBody] wywnioskowane w obu przypadkach, ponieważ są to typy złożone.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atrybut [FromBody] dla jednego, wywnioskowany dla drugiego ze względu na złożoność typu.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atrybut [FromBody] w obu przypadkach.

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

Uwagi dotyczące wnioskowania FromServices

Powiązanie parametrów za pośrednictwem wstrzykiwania zależności występuje, gdy typ jest skonfigurowany jako usługa. Oznacza to, że nie jest wymagane jawne zastosowanie atrybutu [FromServices] do parametru. W poniższym kodzie obie akcje zwracają czas:

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

W rzadkich przypadkach automatyczne wstrzykiwanie zależności (DI) może przerwać działanie aplikacji, które mają typ DI akceptowany również w metodach akcji kontrolera API. Nie jest powszechne, aby mieć typ w DI i jako argument w akcji kontrolera API.

Aby wyłączyć wnioskowanie [FromServices] dla pojedynczego parametru akcji, zastosuj do parametru żądany atrybut obiektu źródłowego powiązania. Na przykład zastosuj atrybut [FromBody] do parametru akcji, który powinien być powiązany z treścią żądania.

Aby wyłączyć [FromServices] wnioskowanie globalnie, ustaw wartość DisableImplicitFromServicesParameters na 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();

Typy są sprawdzane podczas uruchamiania aplikacji z użyciem IServiceProviderIsService w celu określenia, czy argument w akcji kontrolera interfejsu API pochodzi z DI lub z innych źródeł.

Mechanizm wnioskowania źródła powiązania parametrów akcji kontrolera interfejsu API używa następujących reguł:

Wyłączanie reguł wnioskowania

Aby wyłączyć wnioskowanie źródła powiązania, ustaw SuppressInferBindingSourcesForParameters na 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();

Wnioskowanie żądania multipart/form-data

Atrybut [ApiController] stosuje regułę wnioskowania dla parametrów akcji typu IFormFile i IFormFileCollection. Dla tych typów jest wnioskowany typ zawartości żądania multipart/form-data.

Aby wyłączyć zachowanie domyślne, ustaw właściwość SuppressConsumesConstraintForFormFileParameters na 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();

Szczegóły problemów dotyczących kodów stanu błędu

MVC przekształca wynik błędu (wynik z kodem stanu 400 lub wyższym) na wynik z ProblemDetails. Typ ProblemDetails jest oparty na specyfikacji RFC 7807 w celu zapewnienia w odpowiedzi HTTP szczegółów błędu czytelnych dla komputera.

Rozważ następujący kod w akcji kontrolera:

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

Metoda NotFound tworzy kod stanu HTTP 404 z treścią ProblemDetails. Przykład:

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

Wyłącz odpowiedź ProblemDetails

Automatyczne tworzenie informacji ProblemDetails dla kodu stanu błędu jest wyłączone, gdy właściwość SuppressMapClientErrors jest ustawiona na true. Dodaj następujący kod:

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();

Definiowanie obsługiwanych typów zawartości żądań za pomocą atrybutu [Consumes]

Domyślnie akcja obsługuje wszystkie dostępne typy zawartości żądań. Jeśli na przykład aplikacja jest skonfigurowana do obsługi zarówno formatów JSON, jak i XML, akcja obsługuje wiele typów zawartości, w tym application/json i application/xml.

Atrybut [Consumes] umożliwia akcji ograniczenie obsługiwanych typów zawartości żądania. Zastosuj atrybut [Consumes] do akcji lub kontrolera, określając co najmniej jeden typ zawartości:

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

W poprzednim kodzie akcja CreateProduct określa typ zawartości application/xml. Żądania kierowane do tej akcji muszą określać nagłówek Content-Type dla application/xml. Żądania, które nie określają nagłówka Content-Type dla application/xml, powodują zwrócenie odpowiedzi 415 Nieobsługiwany typ nośnika.

Atrybut [Consumes] umożliwia również akcji wpływanie na wybór na podstawie typu zawartości żądania przychodzącego, stosując ograniczenie typu. Rozważmy następujący przykład:

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

W poprzednim kodzie skonfigurowano ConsumesController pod kątem obsługi żądań wysyłanych na adres URL https://localhost:5001/api/Consumes. Obie akcje kontrolera, PostJson i PostForm, obsługują żądania POST przy użyciu tego samego adresu URL. Przy braku atrybutu [Consumes] stosującego ograniczenie typu zgłaszany jest wyjątek niejasności dopasowania.

Atrybut [Consumes] jest stosowany do obu akcji. Akcja PostJson obsługuje żądania wysyłane z nagłówkiem Content-Type o wartości application/json. Akcja PostForm obsługuje żądania wysyłane z nagłówkiem Content-Type o wartości application/x-www-form-urlencoded.

Dodatkowe zasoby

ASP.NET Core obsługuje tworzenie internetowych interfejsów API przy użyciu kontrolerów lub minimalnych interfejsów API. Kontrolery w internetowym interfejsie API to klasy pochodne klasy ControllerBase. W tym artykule pokazano, jak używać kontrolerów do obsługi żądań internetowego interfejsu API. Aby uzyskać informacje na temat tworzenia internetowych interfejsów API bez kontrolerów, zobacz Samouczek: tworzenie minimalnego interfejsu API przy użyciu platformy ASP.NET Core.

Klasa ControllerBase

Internetowy interfejs API oparty na kontrolerze składa się z co najmniej jednej klasy kontrolera pochodnej od klasy ControllerBase. Szablon projektu internetowego interfejsu API udostępnia kontroler startowy:

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

Kontrolery internetowego interfejsu API powinny zwykle być pochodnymi klasy ControllerBase, a nie Controller. Klasa Controller jest pochodną klasy ControllerBase i dodano w niej obsługę widoków, dlatego jest przeznaczona do obsługi stron internetowych, a nie żądań internetowego interfejsu API. Jeśli ten sam kontroler musi obsługiwać widoki i internetowe interfejsy API, powinien być pochodną klasy Controller.

Klasa ControllerBase udostępnia wiele właściwości i metod, które są przydatne do obsługi żądań HTTP. Na przykład CreatedAtAction zwraca kod stanu 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);
}

Poniższa tabela zawiera przykłady metod w klasie ControllerBase.

Method Notes
BadRequest Zwraca kod stanu 400.
NotFound Zwraca kod stanu 404.
PhysicalFile Zwraca plik.
TryUpdateModelAsync Wywołuje powiązanie modelu.
TryValidateModel Wywołuje weryfikację modelu.

Aby uzyskać listę wszystkich dostępnych metod i właściwości, zobacz ControllerBase.

Attributes

Przestrzeń nazw Microsoft.AspNetCore.Mvc udostępnia atrybuty, których można użyć do skonfigurowania zachowania kontrolerów internetowego interfejsu API i metod akcji. W poniższym przykładzie użyto atrybutów do określenia obsługiwanego polecenia akcji HTTP i wszystkich znanych kodów stanu HTTP, które mogą zostać zwrócone:

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

Poniżej przedstawiono więcej przykładów dostępnych atrybutów.

Attribute Notes
[Route] Określa wzorzec adresu URL dla kontrolera lub akcji.
[Bind] Określa prefiks i właściwości do uwzględnienia dla powiązania modelu.
[HttpGet] Identyfikuje akcję, która obsługuje polecenie akcji HTTP GET.
[Consumes] Określa typy danych, które akceptuje akcja.
[Produces] Określa typy danych zwracane przez akcję.

Aby uzyskać listę zawierającą dostępne atrybuty, zobacz przestrzeń nazw Microsoft.AspNetCore.Mvc.

Atrybut ApiController

Atrybut [ApiController] można zastosować do klasy kontrolera w celu umożliwienia następujących zachowań specyficznych dla interfejsu API:

Atrybut w przypadku określonych kontrolerów

Atrybut [ApiController] można zastosować do określonych kontrolerów, jak w poniższym przykładzie z szablonu projektu:

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

Atrybut w przypadku wielu kontrolerów

Jednym z rozwiązań pozwalających na używanie atrybutu na więcej niż jednym kontrolerze jest utworzenie niestandardowej klasy kontrolera podstawowego oznaczonej atrybutem [ApiController]. W poniższym przykładzie przedstawiono niestandardową klasę bazową i kontroler, który jest jej pochodną:

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

Atrybut zestawu

Atrybut [ApiController] można zastosować do zestawu. Po zastosowaniu atrybutu [ApiController] do zestawu wszystkie kontrolery w zestawie mają zastosowany atrybut [ApiController]. Nie ma możliwości wyłączenie z tego poszczególnych kontrolerów. Zastosuj atrybut na poziomie zestawu do pliku 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();

Wymaganie dotyczące routingu atrybutów

Atrybut [ApiController] wymusza użycie routingu atrybutów. Przykład:

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

Akcje są niedostępne za pośrednictwem konwencjonalnych tras zdefiniowanych przez UseEndpoints, UseMvc lub UseMvcWithDefaultRoute.

Automatyczne odpowiedzi HTTP 400

Atrybut [ApiController] sprawia, że błędy weryfikacji modelu automatycznie wyzwalają odpowiedź HTTP 400. W związku z tym następujący kod jest niepotrzebny w metodzie akcji:

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

ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do sprawdzenia poprzednich warunków.

Domyślna odpowiedź BadRequest

Następująca treść odpowiedzi jest przykładem typu serializowanego:

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

Domyślnym typem odpowiedzi dla odpowiedzi HTTP 400 jest ValidationProblemDetails. Następująca treść odpowiedzi jest przykładem typu serializowanego:

{
  "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."
    ]
  }
}

Typ ValidationProblemDetails:

  • Udostępnia format czytelny dla komputera do określania błędów w odpowiedziach internetowego interfejsu API.
  • Jest zgodny ze specyfikacją RFC 7807.

Aby zapewnić spójność odpowiedzi automatycznych i niestandardowych, wywołaj metodę ValidationProblem zamiast BadRequest. ValidationProblem zwraca obiekt ValidationProblemDetails, a także odpowiedź automatyczną.

Automatyczne rejestrowanie odpowiedzi 400

Aby zarejestrować automatyczne odpowiedzi 400, ustaw właściwość delegata InvalidModelStateResponseFactory na wykonywanie przetwarzania niestandardowego. Domyślnie InvalidModelStateResponseFactory używa ProblemDetailsFactory do utworzenia wystąpienia ValidationProblemDetails.

W poniższym przykładzie pokazano, jak pobrać wystąpienie ILogger<TCategoryName>, aby zarejestrować informacje o odpowiedzi automatycznej 400:

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();

Wyłącz automatyczną odpowiedź 400

Aby wyłączyć automatyczne zachowanie 400, ustaw właściwość SuppressModelStateInvalidFilter na true. Dodaj następujący wyróżniony kod:

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();

Wnioskowanie parametru źródła powiązania

Atrybut obiektu źródłowego powiązania definiuje lokalizację, w której znajduje się wartość parametru akcji. Istnieją następujące atrybuty obiektu źródłowego powiązania:

Attribute Źródło powiązania
[FromBody] Ciało żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Przekazywanie danych z bieżącego żądania
[FromServices] Usługa żądania zastosowana jako parametr akcji

Warning

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie zostanie przekształcone na /. Użyj [FromQuery], jeśli wartość może zawierać %2f.

Bez atrybutu [ApiController] lub atrybutów źródłowych wiązania, takich jak [FromQuery], środowisko uruchomieniowe ASP.NET Core próbuje użyć mechanizmu wiązania złożonego modelu obiektowego. Integrator modelu obiektów złożonych ściąga dane od dostawców wartości w zdefiniowanej kolejności.

W poniższym przykładzie atrybut [FromQuery] wskazuje, że wartość parametru discontinuedOnly jest podana w ciągu zapytania adresu URL żądania:

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

Atrybut [ApiController] stosuje reguły wnioskowania dla domyślnych źródeł danych parametrów akcji. Te reguły eliminują konieczność ręcznego identyfikowania źródeł powiązań przez stosowanie atrybutów do parametrów akcji. Reguły wnioskowania źródła powiązania zachowują się w następujący sposób:

  • [FromBody] jest inferowane dla parametrów typu złożonego, które nie zostały zarejestrowane w kontenerze DI. Wyjątkiem od reguły wnioskowania [FromBody] jest dowolny złożony typ wbudowany ze specjalnym znaczeniem, taki jak IFormCollection i CancellationToken. Kod wnioskowania dla źródła wiązania ignoruje te specjalne typy.
  • [FromForm] jest wnioskowane dla parametrów akcji typu IFormFile i IFormFileCollection. To wnioskowanie nie jest realizowane dla żadnych typów prostych ani zdefiniowanych przez użytkownika.
  • [FromRoute] jest wnioskowane dla dowolnej nazwy parametru akcji zgodnej z parametrem w szablonie trasy. Gdy więcej niż jedna trasa jest zgodna z parametrem akcji, dowolna wartość trasy jest uznawana za [FromRoute].
  • [FromQuery] jest wywnioskowane dla każdego innego parametru akcji.

Uwagi dotyczące wnioskowania FromBody

[FromBody] nie jest wnioskowane dla typów prostych, takich jak string lub int. W związku z tym w przypadku typów prostych, gdy ta funkcja jest potrzebna, powinien być używany atrybut [FromBody].

Jeśli akcja ma więcej niż jeden parametr powiązany z treścią żądania, zgłaszany jest wyjątek. Na przykład wszystkie następujące podpisy metod akcji powodują wyjątek:

  • [FromBody] wywnioskowane w obu przypadkach, ponieważ są to typy złożone.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atrybut [FromBody] w jednym, wywnioskowany w przypadku drugiego, ponieważ jest to typ złożony.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atrybut [FromBody] w obu przypadkach.

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

Wyłączanie reguł wnioskowania

Aby wyłączyć wnioskowanie źródła powiązania, ustaw SuppressInferBindingSourcesForParameters na 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();

Wnioskowanie żądania typu multipart/form-data

Atrybut [ApiController] stosuje regułę wnioskowania dla parametrów akcji typu IFormFile i IFormFileCollection. Typ zawartości żądania multipart/form-data jest wnioskowany dla tych typów.

Aby wyłączyć zachowanie domyślne, ustaw właściwość SuppressConsumesConstraintForFormFileParameters na 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();

Szczegóły problemów dotyczących kodów stanu błędu

MVC przekształca rezultat błędu (rezultat z kodem stanu 400 lub wyższym) w wynik z ProblemDetails. Typ ProblemDetails jest oparty na specyfikacji RFC 7807 w celu zapewnienia w odpowiedzi HTTP szczegółów błędu czytelnych dla komputera.

Rozważ następujący kod w akcji kontrolera:

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

Metoda NotFound tworzy kod stanu HTTP 404 z treścią ProblemDetails. Przykład:

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

Wyłącz odpowiedź ProblemDetails

Automatyczne tworzenie informacji ProblemDetails dla kodu stanu błędu jest wyłączone, gdy właściwość SuppressMapClientErrors jest ustawiona na 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();

Definiowanie obsługiwanych typów zawartości żądań za pomocą atrybutu [Consumes]

Domyślnie akcja obsługuje wszystkie dostępne typy zawartości żądań. Jeśli na przykład aplikacja jest skonfigurowana do obsługi zarówno formatów JSON, jak i XML, akcja obsługuje wiele typów zawartości, w tym application/json i application/xml.

Atrybut [Consumes] umożliwia akcji ograniczenie obsługiwanych typów zawartości żądania. Zastosuj atrybut [Consumes] do akcji lub kontrolera, określając co najmniej jeden typ zawartości:

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

W poprzednim kodzie akcja CreateProduct określa typ zawartości application/xml. Żądania kierowane do tej akcji muszą określać nagłówek Content-Type o wartości application/xml. Żądania, które nie zawierają nagłówka Content-Typeapplication/xml, skutkują odpowiedzią 415 Nieobsługiwany typ nośnika.

Atrybut [Consumes] umożliwia również wpłynięcie na wybór akcji na podstawie typu treści żądania przychodzącego przez zastosowanie ograniczenia typu. Rozważmy następujący przykład:

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

W poprzednim kodzie skonfigurowano ConsumesController pod kątem obsługi żądań wysyłanych na adres URL https://localhost:5001/api/Consumes. Obie akcje kontrolera, PostJson i PostForm, obsługują żądania POST przy użyciu tego samego adresu URL. Przy braku atrybutu [Consumes] stosującego ograniczenie typu zgłaszany jest wyjątek niejasności dopasowania.

Atrybut [Consumes] jest stosowany do obu akcji. Akcja PostJson obsługuje żądania wysyłane z nagłówkiem Content-Type o wartości application/json. Akcja PostForm obsługuje żądania wysyłane z nagłówkiem Content-Type o wartości application/x-www-form-urlencoded.

Dodatkowe zasoby

Platforma ASP.NET Core obsługuje tworzenie usług RESTful, znanych także jako internetowe interfejsy API, za pomocą języka C#. Do obsługi żądań internetowy interfejs API używa kontrolerów. Kontrolery w internetowym interfejsie API to klasy pochodne klasy ControllerBase. W tym artykule pokazano, jak używać kontrolerów do obsługi żądań internetowego interfejsu API.

Wyświetl lub pobierz kod przykładowy. (Jak pobrać).

Klasa ControllerBase

Internetowy interfejs API składa się z co najmniej jednej klasy kontrolera pochodnej od klasy ControllerBase. Szablon projektu internetowego interfejsu API udostępnia kontroler startowy:

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

Nie twórz kontrolera interfejsu API sieci Web na podstawie klasy Controller. Klasa Controller jest pochodną klasy ControllerBase i dodano w niej obsługę widoków, dlatego jest przeznaczona do obsługi stron internetowych, a nie żądań internetowego interfejsu API. Istnieje wyjątek od tej reguły: jeśli ten sam kontroler będzie obsługiwać widoki i internetowe interfejsy API, powinien być pochodną klasy Controller.

Klasa ControllerBase udostępnia wiele właściwości i metod, które są przydatne do obsługi żądań HTTP. Na przykład ControllerBase.CreatedAtAction zwraca kod stanu 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);
}

Poniżej przedstawiono kilka przykładów metod klasy ControllerBase.

Method Notes
BadRequest Zwraca kod stanu 400.
NotFound Zwraca kod stanu 404.
PhysicalFile Zwraca plik.
TryUpdateModelAsync Wywołuje powiązanie modelu.
TryValidateModel Wywołuje weryfikację modelu.

Aby uzyskać listę wszystkich dostępnych metod i właściwości, zobacz ControllerBase.

Attributes

Przestrzeń nazw Microsoft.AspNetCore.Mvc udostępnia atrybuty, których można użyć do skonfigurowania zachowania kontrolerów internetowego interfejsu API i metod akcji. W poniższym przykładzie użyto atrybutów do określenia obsługiwanego polecenia akcji HTTP i wszystkich znanych kodów stanu HTTP, które mogą zostać zwrócone:

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

Poniżej przedstawiono więcej przykładów dostępnych atrybutów.

Attribute Notes
[Route] Określa wzorzec adresu URL dla kontrolera lub akcji.
[Bind] Określa prefiks i właściwości do uwzględnienia dla powiązania modelu.
[HttpGet] Identyfikuje akcję, która obsługuje polecenie akcji HTTP GET.
[Consumes] Określa typy danych, które akceptuje akcja.
[Produces] Określa typy danych zwracane przez akcję.

Aby uzyskać listę zawierającą dostępne atrybuty, zobacz przestrzeń nazw Microsoft.AspNetCore.Mvc.

Atrybut ApiController

Atrybut [ApiController] można zastosować do klasy kontrolera w celu umożliwienia następujących zachowań specyficznych dla interfejsu API:

Atrybut w przypadku określonych kontrolerów

Atrybut [ApiController] można zastosować do określonych kontrolerów, jak w poniższym przykładzie z szablonu projektu:

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

Atrybut w przypadku wielu kontrolerów

Jednym z rozwiązań pozwalających na używanie atrybutu na więcej niż jednym kontrolerze jest utworzenie niestandardowej klasy kontrolera podstawowego oznaczonej atrybutem [ApiController]. W poniższym przykładzie przedstawiono niestandardową klasę bazową i kontroler, który jest jej pochodną:

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

Atrybut zestawu

Atrybut [ApiController] można zastosować do zestawu. Taka adnotacja zapewnia zastosowanie zachowania internetowego interfejsu API do wszystkich kontrolerów w zestawie. Nie ma możliwości wyłączenie z tego poszczególnych kontrolerów. Zastosuj atrybut na poziomie zestawu do deklaracji przestrzeni nazw otaczającej klasę Startup:

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

Wymaganie dotyczące routingu atrybutów

Atrybut [ApiController] wymusza użycie routingu atrybutów. Przykład:

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

Akcje są niedostępne za pośrednictwem konwencjonalnych tras zdefiniowanych przez UseEndpoints, UseMvc lub UseMvcWithDefaultRoute w Startup.Configure.

Automatyczne odpowiedzi HTTP 400

Atrybut [ApiController] sprawia, że błędy weryfikacji modelu automatycznie wyzwalają odpowiedź HTTP 400. W związku z tym następujący kod jest niepotrzebny w metodzie akcji:

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

ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do sprawdzenia poprzednich warunków.

Domyślna odpowiedź BadRequest

Następująca treść żądania jest przykładem typu serializowanego:

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

Domyślnym typem odpowiedzi dla odpowiedzi HTTP 400 jest ValidationProblemDetails. Następująca treść żądania jest przykładem typu serializowanego:

{
  "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."
    ]
  }
}

Typ ValidationProblemDetails:

  • Udostępnia format czytelny dla komputera do określania błędów w odpowiedziach internetowego interfejsu API.
  • Jest zgodny ze specyfikacją RFC 7807.

Aby zapewnić spójność odpowiedzi automatycznych i niestandardowych, wywołaj metodę ValidationProblem zamiast BadRequest. ValidationProblem zwraca obiekt ValidationProblemDetails, a także odpowiedź automatyczną.

Automatyczne rejestrowanie odpowiedzi 400

Aby rejestrować odpowiedzi automatyczne 400, ustaw właściwość delegata InvalidModelStateResponseFactory na wykonywanie przetwarzania niestandardowego w Startup.ConfigureServices. Domyślnie InvalidModelStateResponseFactory używa ProblemDetailsFactory do utworzenia wystąpienia ValidationProblemDetails.

W poniższym przykładzie pokazano, jak pobrać wystąpienie ILogger<TCategoryName>, aby zarejestrować informacje o odpowiedzi automatycznej 400:

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

Wyłącz automatyczną odpowiedź 400

Aby wyłączyć automatyczne zachowanie 400, ustaw właściwość SuppressModelStateInvalidFilter na true. Dodaj następujący wyróżniony kod w 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;
    });

Wnioskowanie parametru źródła powiązania

Atrybut obiektu źródłowego powiązania definiuje lokalizację, w której znajduje się wartość parametru akcji. Istnieją następujące atrybuty obiektu źródłowego powiązania:

Attribute Źródło powiązania
[FromBody] Ciało żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Przekazywanie danych z bieżącego żądania
[FromServices] Usługa żądania zastosowana jako parametr akcji

Warning

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie zostanie przekształcone na /. Użyj [FromQuery], jeśli wartość może zawierać %2f.

Bez atrybutu [ApiController] lub atrybutów źródłowych wiązania, takich jak [FromQuery], środowisko uruchomieniowe ASP.NET Core próbuje użyć mechanizmu wiązania złożonego modelu obiektowego. Integrator modelu obiektów złożonych ściąga dane od dostawców wartości w zdefiniowanej kolejności.

W poniższym przykładzie atrybut [FromQuery] wskazuje, że wartość parametru discontinuedOnly jest podana w ciągu zapytania adresu URL żądania:

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

Atrybut [ApiController] stosuje reguły wnioskowania dla domyślnych źródeł danych parametrów akcji. Te reguły eliminują konieczność ręcznego identyfikowania źródeł powiązań przez stosowanie atrybutów do parametrów akcji. Reguły wnioskowania źródła powiązania zachowują się w następujący sposób:

  • [FromBody] jest wnioskowane dla parametrów typu złożonego. Wyjątkiem od reguły wnioskowania [FromBody] jest dowolny złożony typ wbudowany ze specjalnym znaczeniem, taki jak IFormCollection i CancellationToken. Kod wnioskowania dla źródła wiązania ignoruje te specjalne typy.
  • [FromForm] jest wnioskowane dla parametrów akcji typu IFormFile i IFormFileCollection. To wnioskowanie nie jest realizowane dla żadnych typów prostych ani zdefiniowanych przez użytkownika.
  • [FromRoute] jest wnioskowane dla dowolnej nazwy parametru akcji zgodnej z parametrem w szablonie trasy. Gdy więcej niż jedna trasa jest zgodna z parametrem akcji, dowolna wartość trasy jest uznawana za [FromRoute].
  • [FromQuery] jest wywnioskowane dla każdego innego parametru akcji.

Uwagi dotyczące wnioskowania FromBody

[FromBody] nie jest wnioskowane dla typów prostych, takich jak string lub int. W związku z tym w przypadku typów prostych, gdy ta funkcja jest potrzebna, powinien być używany atrybut [FromBody].

Jeśli akcja ma więcej niż jeden parametr powiązany z treścią żądania, zgłaszany jest wyjątek. Na przykład wszystkie następujące podpisy metod akcji powodują wyjątek:

  • [FromBody] wywnioskowane w obu przypadkach, ponieważ są to typy złożone.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atrybut [FromBody] w jednym, wywnioskowany w przypadku drugiego, ponieważ jest to typ złożony.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atrybut [FromBody] w obu przypadkach.

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

Wyłączanie reguł wnioskowania

Aby wyłączyć wnioskowanie źródła powiązania, ustaw SuppressInferBindingSourcesForParameters na true. Dodaj następujący kod w 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;
    });

Wnioskowanie żądania typu multipart/form-data

Atrybut [ApiController] stosuje regułę wnioskowania dla parametrów akcji typu IFormFile i IFormFileCollection. Typ zawartości żądania multipart/form-data jest wnioskowany dla tych typów.

Aby wyłączyć zachowanie domyślne, ustaw właściwość SuppressConsumesConstraintForFormFileParameters na true w 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;
    });

Szczegóły problemów dotyczących kodów stanu błędu

MVC przekształca rezultat błędu (rezultat z kodem stanu 400 lub wyższym) w wynik z ProblemDetails. Typ ProblemDetails jest oparty na specyfikacji RFC 7807 w celu zapewnienia w odpowiedzi HTTP szczegółów błędu czytelnych dla komputera.

Rozważ następujący kod w akcji kontrolera:

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

Metoda NotFound tworzy kod stanu HTTP 404 z treścią ProblemDetails. Przykład:

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

Wyłącz odpowiedź ProblemDetails

Automatyczne tworzenie informacji ProblemDetails dla kodu stanu błędu jest wyłączone, gdy właściwość SuppressMapClientErrors jest ustawiona na true. Dodaj następujący kod w 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;
    });

Definiowanie obsługiwanych typów zawartości żądań za pomocą atrybutu [Consumes]

Domyślnie akcja obsługuje wszystkie dostępne typy zawartości żądań. Jeśli na przykład aplikacja jest skonfigurowana do obsługi zarówno formatów JSON, jak i XML, akcja obsługuje wiele typów zawartości, w tym application/json i application/xml.

Atrybut [Consumes] umożliwia akcji ograniczenie obsługiwanych typów zawartości żądania. Zastosuj atrybut [Consumes] do akcji lub kontrolera, określając co najmniej jeden typ zawartości:

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

W poprzednim kodzie akcja CreateProduct określa typ zawartości application/xml. Żądania kierowane do tej akcji muszą określać nagłówek Content-Type o wartości application/xml. Żądania, które nie zawierają nagłówka Content-Typeapplication/xml, skutkują odpowiedzią 415 Nieobsługiwany typ nośnika.

Atrybut [Consumes] umożliwia również wpłynięcie na wybór akcji na podstawie typu treści żądania przychodzącego przez zastosowanie ograniczenia typu. Rozważmy następujący przykład:

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

W poprzednim kodzie skonfigurowano ConsumesController pod kątem obsługi żądań wysyłanych na adres URL https://localhost:5001/api/Consumes. Obie akcje kontrolera, PostJson i PostForm, obsługują żądania POST przy użyciu tego samego adresu URL. Bez atrybutu [Consumes] stosującego ograniczenie typu wyrzucany jest wyjątek niejednoznaczności dopasowania.

Atrybut [Consumes] jest stosowany do obu akcji. Akcja PostJson obsługuje żądania wysyłane z nagłówkiem Content-Type dla application/json. Akcja PostForm obsługuje żądania wysyłane z nagłówkiem Content-Type dla application/x-www-form-urlencoded.

Dodatkowe zasoby

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

Nie twórz kontrolera interfejsu API sieci Web na podstawie klasy Controller. Klasa Controller jest pochodną klasy ControllerBase i dodano w niej obsługę widoków, dlatego jest przeznaczona do obsługi stron internetowych, a nie żądań internetowego interfejsu API. Istnieje wyjątek od tej reguły: jeśli ten sam kontroler będzie obsługiwać widoki i internetowe interfejsy API, powinien być pochodną klasy Controller. Klasa ControllerBase udostępnia wiele właściwości i metod, które są przydatne do obsługi żądań HTTP. Na przykład ControllerBase.CreatedAtAction zwraca kod stanu 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);
}

Poniżej przedstawiono kilka przykładów metod klasy ControllerBase:

Method Notes
BadRequest Zwraca kod stanu 400.
NotFound Zwraca kod stanu 404.
PhysicalFile Zwraca plik.
TryUpdateModelAsync Wywołuje powiązanie modelu.
TryValidateModel Wywołuje weryfikację modelu.

Aby uzyskać listę wszystkich dostępnych metod i właściwości, zobacz ControllerBase.

Attributes

Przestrzeń nazw Microsoft.AspNetCore.Mvc udostępnia atrybuty, których można użyć do skonfigurowania zachowania kontrolerów internetowego interfejsu API i metod akcji. W poniższym przykładzie użyto atrybutów do określenia obsługiwanego polecenia akcji HTTP i wszystkich znanych kodów stanu HTTP, które mogą zostać zwrócone:

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

Poniżej przedstawiono więcej przykładów dostępnych atrybutów:

Attribute Notes
[Route] Określa wzorzec adresu URL dla kontrolera lub akcji.
[Bind] Określa prefiks i właściwości do uwzględnienia dla powiązania modelu.
[HttpGet] Identyfikuje akcję, która obsługuje polecenie akcji HTTP GET.
[Consumes] Określa typy danych, które akceptuje akcja.
[Produces] Określa typy danych zwracane przez akcję.

Aby uzyskać listę zawierającą dostępne atrybuty, zobacz przestrzeń nazw Microsoft.AspNetCore.Mvc.

Atrybut ApiController

Atrybut [ApiController] można zastosować do klasy kontrolera w celu umożliwienia następujących zachowań specyficznych dla interfejsu API:

Atrybut w przypadku określonych kontrolerów

Atrybut [ApiController] można zastosować do określonych kontrolerów, jak w poniższym przykładzie z szablonu projektu:

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

Atrybut w przypadku wielu kontrolerów

Jednym z rozwiązań pozwalających na używanie atrybutu na więcej niż jednym kontrolerze jest utworzenie niestandardowej klasy kontrolera podstawowego oznaczonej atrybutem [ApiController]. W poniższym przykładzie przedstawiono niestandardową klasę bazową i kontroler, który jest jej pochodną:

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

Atrybut zestawu

Jeśli wersja zgodności jest ustawiona na 2.2 lub nowszą, atrybut [ApiController] można zastosować do zestawu. Taka adnotacja zapewnia zastosowanie zachowania internetowego interfejsu API do wszystkich kontrolerów w zestawie. Nie ma możliwości wyłączenie z tego poszczególnych kontrolerów. Zastosuj atrybut na poziomie zestawu do deklaracji przestrzeni nazw otaczającej klasę Startup:

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

Wymaganie dotyczące routingu atrybutów

Atrybut [ApiController] wymusza użycie routingu atrybutów. Przykład:

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

Akcje są niedostępne za pośrednictwem konwencjonalnych tras zdefiniowanych przez UseMvc lub UseMvcWithDefaultRoute w Startup.Configure.

Automatyczne odpowiedzi HTTP 400

Atrybut [ApiController] sprawia, że błędy weryfikacji modelu automatycznie wyzwalają odpowiedź HTTP 400. W związku z tym następujący kod jest niepotrzebny w metodzie akcji:

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

ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do sprawdzenia poprzednich warunków.

Domyślna odpowiedź BadRequest

W przypadku wersji zgodności 2.1 domyślny typ odpowiedzi dla odpowiedzi HTTP 400 to SerializableError. Następująca treść żądania jest przykładem typu serializowanego:

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

W przypadku wersji zgodności 2.2 lub nowszej domyślny typ odpowiedzi dla odpowiedzi HTTP 400 to ValidationProblemDetails. Następująca treść żądania jest przykładem typu serializowanego:

{
  "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."
    ]
  }
}

Typ ValidationProblemDetails:

  • Udostępnia format czytelny dla komputera do określania błędów w odpowiedziach internetowego interfejsu API.
  • Jest zgodny ze specyfikacją RFC 7807.

Aby zapewnić spójność odpowiedzi automatycznych i niestandardowych, wywołaj metodę ValidationProblem zamiast BadRequest. ValidationProblem zwraca obiekt ValidationProblemDetails, a także odpowiedź automatyczną.

Automatyczne rejestrowanie odpowiedzi 400

Zobacz Jak rejestrować automatyczne odpowiedzi 400 w przypadku błędów weryfikacji modelu (dotnet/AspNetCore.Docs#12157).

Wyłącz automatyczną odpowiedź 400

Aby wyłączyć automatyczne zachowanie 400, ustaw właściwość SuppressModelStateInvalidFilter na true. Dodaj następujący wyróżniony kod w Startup.ConfigureServices:

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

Wnioskowanie parametru źródła powiązania

Atrybut obiektu źródłowego powiązania definiuje lokalizację, w której znajduje się wartość parametru akcji. Istnieją następujące atrybuty obiektu źródłowego powiązania:

Attribute Źródło powiązania
[FromBody] Ciało żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Przekazywanie danych z bieżącego żądania
[FromServices] Usługa żądania zastosowana jako parametr akcji

Warning

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie zostanie przekształcone na /. Użyj [FromQuery], jeśli wartość może zawierać %2f. Bez atrybutu [ApiController] lub atrybutów źródłowych wiązania, takich jak [FromQuery], środowisko uruchomieniowe ASP.NET Core próbuje użyć mechanizmu wiązania złożonego modelu obiektowego. Integrator modelu obiektów złożonych ściąga dane od dostawców wartości w zdefiniowanej kolejności.

W poniższym przykładzie atrybut [FromQuery] wskazuje, że wartość parametru discontinuedOnly jest podana w ciągu zapytania adresu URL żądania:

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

Atrybut [ApiController] stosuje reguły wnioskowania dla domyślnych źródeł danych parametrów akcji. Te reguły eliminują konieczność ręcznego identyfikowania źródeł powiązań przez stosowanie atrybutów do parametrów akcji. Reguły wnioskowania źródła powiązania zachowują się w następujący sposób:

  • [FromBody] jest wnioskowane dla parametrów typu złożonego. Wyjątkiem od reguły wnioskowania [FromBody] jest dowolny złożony typ wbudowany ze specjalnym znaczeniem, taki jak IFormCollection i CancellationToken. Kod wnioskowania dla źródła wiązania ignoruje te specjalne typy.
  • [FromForm] jest wnioskowane dla parametrów akcji typu IFormFile i IFormFileCollection. To wnioskowanie nie jest realizowane dla żadnych typów prostych ani zdefiniowanych przez użytkownika.
  • [FromRoute] jest wnioskowane dla dowolnej nazwy parametru akcji zgodnej z parametrem w szablonie trasy. Gdy więcej niż jedna trasa jest zgodna z parametrem akcji, dowolna wartość trasy jest uznawana za [FromRoute].
  • [FromQuery] jest wywnioskowane dla każdego innego parametru akcji.

Uwagi dotyczące wnioskowania FromBody

[FromBody] nie jest wnioskowane dla typów prostych, takich jak string lub int. W związku z tym w przypadku typów prostych, gdy ta funkcja jest potrzebna, powinien być używany atrybut [FromBody].

Jeśli akcja ma więcej niż jeden parametr powiązany z treścią żądania, zgłaszany jest wyjątek. Na przykład wszystkie następujące podpisy metod akcji powodują wyjątek:

  • [FromBody] wywnioskowane w obu przypadkach, ponieważ są to typy złożone.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atrybut [FromBody] w jednym, wywnioskowany w przypadku drugiego, ponieważ jest to typ złożony.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atrybut [FromBody] w obu przypadkach.

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

Note

Na platformie ASP.NET Core 2.1 parametry typu „kolekcja”, takie jak listy i tablice, są niepoprawnie wnioskowane jako [FromQuery]. Jeśli te parametry mają być powiązane z poziomu treści żądania powinien być w ich przypadku używany atrybut [FromBody]. To zachowanie poprawiono w ASP.NET Core 2.2 i nowszych wersjach, gdzie parametry typu kolekcji są domyślnie wnioskowane jako powiązane z ciałem żądania.

Wyłączanie reguł wnioskowania

Aby wyłączyć wnioskowanie źródła powiązania, ustaw SuppressInferBindingSourcesForParameters na true. Dodaj następujący kod w Startup.ConfigureServices:

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

Wnioskowanie żądania typu multipart/form-data

Atrybut [ApiController] stosuje regułę wnioskowania dla parametrów akcji typu IFormFile i IFormFileCollection. Typ zawartości żądania multipart/form-data jest wnioskowany dla tych typów. Aby wyłączyć zachowanie domyślne, ustaw właściwość SuppressConsumesConstraintForFormFileParameters na true w Startup.ConfigureServices:

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

Szczegóły problemów dotyczących kodów stanu błędu

Jeśli wersja zgodności to 2.2 lub nowsza, model MVC przekształca wynik błędu (wynik z kodem stanu 400 lub wyższym) w wynik z ProblemDetails. Typ ProblemDetails jest oparty na specyfikacji RFC 7807 w celu zapewnienia w odpowiedzi HTTP szczegółów błędu czytelnych dla komputera. Rozważ następujący kod w akcji kontrolera:

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

Metoda NotFound tworzy kod stanu HTTP 404 z treścią ProblemDetails. Przykład:

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

Wyłącz odpowiedź ProblemDetails

Automatyczne tworzenie informacji ProblemDetails dla kodu stanu błędu jest wyłączone, gdy właściwość SuppressMapClientErrors jest ustawiona na true. Dodaj następujący kod w Startup.ConfigureServices:

Definiowanie obsługiwanych typów zawartości żądań za pomocą atrybutu [Consumes]

Domyślnie akcja obsługuje wszystkie dostępne typy zawartości żądań. Jeśli na przykład aplikacja jest skonfigurowana do obsługi zarówno formatów JSON, jak i XML, akcja obsługuje wiele typów zawartości, w tym application/json i application/xml.

Atrybut [Consumes] umożliwia akcji ograniczenie obsługiwanych typów zawartości żądania. Zastosuj atrybut [Consumes] do akcji lub kontrolera, określając co najmniej jeden typ zawartości:

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

W poprzednim kodzie akcja CreateProduct określa typ zawartości application/xml. Żądania kierowane do tej akcji muszą określać nagłówek Content-Type o wartości application/xml. Żądania, które nie zawierają nagłówka Content-Typeapplication/xml, skutkują odpowiedzią 415 Nieobsługiwany typ nośnika. Atrybut [Consumes] umożliwia również wpłynięcie na wybór akcji na podstawie typu treści żądania przychodzącego przez zastosowanie ograniczenia typu. Rozważmy następujący przykład:

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

W poprzednim kodzie skonfigurowano ConsumesController pod kątem obsługi żądań wysyłanych na adres URL https://localhost:5001/api/Consumes. Obie akcje kontrolera, PostJson i PostForm, obsługują żądania POST przy użyciu tego samego adresu URL. Bez atrybutu [Consumes] stosującego ograniczenie typu wyrzucany jest wyjątek niejednoznaczności dopasowania. Atrybut [Consumes] jest stosowany do obu akcji. Akcja PostJson obsługuje żądania wysyłane z nagłówkiem Content-Type dla application/json. Akcja PostForm obsługuje żądania wysyłane z nagłówkiem Content-Type dla application/x-www-form-urlencoded.

Dodatkowe zasoby