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

Platforma ASP.NET Core obsługuje tworzenie internetowych interfejsów API przy użyciu kontrolerów lub korzystanie z minimalnych interfejsów API. Kontrolery w internetowym interfejsie API to klasy pochodne klasy ControllerBase. Kontrolery są aktywowane i usuwane dla poszczególnych żądań.

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.

Metoda Uwagi
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.

Atrybuty

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.

Atrybut Uwagi
[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] sprawia, że jest wymagany routing 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);
}

Model ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do wykonania wcześniejszego sprawdzenia.

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ą.

Rejestrowanie odpowiedzi automatycznych 400

Aby rejestrować odpowiedzi automatyczne 400, ustaw właściwość delegata InvalidModelStateResponseFactory na wykonywanie przetwarzania niestandardowego. Domyślnie InvalidModelStateResponseFactory tworzy wystąpienie ValidationProblemDetails za pomocą ProblemDetailsFactory.

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łączanie odpowiedzi automatycznej 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 obiektu źródłowego 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:

Atrybut Obiekt źródłowy powiązania
[FromBody] Treść żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Kierowanie danych z bieżącego żądania
[FromServices] Usługa żądania wstrzyknięta jako parametr akcji
[AsParameters] Parametry metody

Ostrzeżenie

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie będzie mieć zmienionego znaczenia na /. Użyj [FromQuery], jeśli wartość może zawierać %2f.

Bez atrybutu [ApiController] lub atrybutów obiektu źródłowego powiązania, takich jak [FromQuery], środowisko uruchomieniowe platformy ASP.NET Core próbuje użyć integratora modelu obiektów złożonych. 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 obiektu źródłowego powiązania zachowują się w następujący sposób:

  • [FromServices] jest wnioskowane dla parametrów typu złożonego, które zarejestrowano w kontenerze wstrzykiwania zależności.
  • [FromBody] jest wnioskowane dla parametrów typu złożonego, które nie zostały zarejestrowane w kontenerze wstrzykiwania zależności. Wyjątkiem od reguły wnioskowania [FromBody] jest dowolny złożony typ wbudowany ze specjalnym znaczeniem, taki jak IFormCollection i CancellationToken. Kod wnioskowania obiektu źródłowego powiązania ignoruje te typy specjalne.
  • [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 wnioskowane dla innych parametrów 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)
    

Uwagi dotyczące wnioskowania FromServices

Powiązanie parametrów wiąże parametry za pośrednictwem wstrzykiwania zależności, 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 di może przerwać aplikacje, które mają typ di, który jest również akceptowany w metodach akcji kontrolera interfejsu API. Typ di i argument w akcji kontrolera interfejsu API nie jest często spotykany.

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 za pomocą IServiceProviderIsService polecenia , aby określić, 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 obiektu źródłowego powiązania, ustaw dla SuppressInferBindingSourcesForParameters wartość 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 danych wieloczęściowych/formularza

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

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łączanie odpowiedzi 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 elementów formatujących dane wejściowe zarówno 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 wywieranie wpływu na jej wybranie na podstawie typu zawartoś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 zgłaszany 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

Platforma ASP.NET Core obsługuje tworzenie internetowych interfejsów API przy użyciu kontrolerów lub korzystanie z 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.

Metoda Uwagi
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.

Atrybuty

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.

Atrybut Uwagi
[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] sprawia, że jest wymagany routing 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);
}

Model ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do wykonania wcześniejszego sprawdzenia.

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ą.

Rejestrowanie odpowiedzi automatycznych 400

Aby rejestrować odpowiedzi automatyczne 400, ustaw właściwość delegata InvalidModelStateResponseFactory na wykonywanie przetwarzania niestandardowego. Domyślnie InvalidModelStateResponseFactory tworzy wystąpienie ValidationProblemDetails za pomocą ProblemDetailsFactory.

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łączanie odpowiedzi automatycznej 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 obiektu źródłowego 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:

Atrybut Obiekt źródłowy powiązania
[FromBody] Treść żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Kierowanie danych z bieżącego żądania
[FromServices] Usługa żądania wstrzyknięta jako parametr akcji

Ostrzeżenie

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie będzie mieć zmienionego znaczenia na /. Użyj [FromQuery], jeśli wartość może zawierać %2f.

Bez atrybutu [ApiController] lub atrybutów obiektu źródłowego powiązania, takich jak [FromQuery], środowisko uruchomieniowe platformy ASP.NET Core próbuje użyć integratora modelu obiektów złożonych. 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 obiektu źródłowego powiązania zachowują się w następujący sposób:

  • [FromBody] jest wnioskowane dla parametrów typu złożonego, które nie zostały zarejestrowane w kontenerze wstrzykiwania zależności. Wyjątkiem od reguły wnioskowania [FromBody] jest dowolny złożony typ wbudowany ze specjalnym znaczeniem, taki jak IFormCollection i CancellationToken. Kod wnioskowania obiektu źródłowego powiązania ignoruje te typy specjalne.
  • [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 wnioskowane dla innych parametrów 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 obiektu źródłowego powiązania, ustaw dla SuppressInferBindingSourcesForParameters wartość 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 danych wieloczęściowych/formularza

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

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łączanie odpowiedzi 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 elementów formatujących dane wejściowe zarówno 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 wywieranie wpływu na jej wybranie na podstawie typu zawartoś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 zgłaszany 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

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 internetowego interfejsu API pochodnego od 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.

Metoda Uwagi
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.

Atrybuty

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.

Atrybut Uwagi
[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] sprawia, że jest wymagany routing 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);
}

Model ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do wykonania wcześniejszego sprawdzenia.

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ą.

Rejestrowanie odpowiedzi automatycznych 400

Aby rejestrować odpowiedzi automatyczne 400, ustaw właściwość delegata InvalidModelStateResponseFactory na wykonywanie przetwarzania niestandardowego w Startup.ConfigureServices. Domyślnie InvalidModelStateResponseFactory tworzy wystąpienie ValidationProblemDetails za pomocą ProblemDetailsFactory.

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łączanie odpowiedzi automatycznej 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 obiektu źródłowego 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:

Atrybut Obiekt źródłowy powiązania
[FromBody] Treść żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Kierowanie danych z bieżącego żądania
[FromServices] Usługa żądania wstrzyknięta jako parametr akcji

Ostrzeżenie

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie będzie mieć zmienionego znaczenia na /. Użyj [FromQuery], jeśli wartość może zawierać %2f.

Bez atrybutu [ApiController] lub atrybutów obiektu źródłowego powiązania, takich jak [FromQuery], środowisko uruchomieniowe platformy ASP.NET Core próbuje użyć integratora modelu obiektów złożonych. 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 obiektu źródłowego 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 obiektu źródłowego powiązania ignoruje te typy specjalne.
  • [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 wnioskowane dla innych parametrów 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 obiektu źródłowego powiązania, ustaw dla SuppressInferBindingSourcesForParameters wartość 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 danych wieloczęściowych/formularza

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 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

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łączanie odpowiedzi 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 elementów formatujących dane wejściowe zarówno 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 wywieranie wpływu na jej wybranie na podstawie typu zawartoś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 zgłaszany 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 internetowego interfejsu API pochodnego od 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:

Metoda Uwagi
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.

Atrybuty

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:

Atrybut Uwagi
[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] sprawia, że jest wymagany routing 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);
}

Model ASP.NET Core MVC używa filtru akcji ModelStateInvalidFilter do wykonania wcześniejszego sprawdzenia.

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ą.

Rejestrowanie odpowiedzi automatycznych 400

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

Wyłączanie odpowiedzi automatycznej 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 obiektu źródłowego 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:

Atrybut Obiekt źródłowy powiązania
[FromBody] Treść żądania
[FromForm] Dane formularza w treści żądania
[FromHeader] Nagłówek żądania
[FromQuery] Parametr ciągu zapytania żądania
[FromRoute] Kierowanie danych z bieżącego żądania
[FromServices] Usługa żądania wstrzyknięta jako parametr akcji

Ostrzeżenie

Nie używaj [FromRoute], gdy wartości mogą zawierać %2f (czyli /). %2f nie będzie mieć zmienionego znaczenia na /. Użyj [FromQuery], jeśli wartość może zawierać %2f. Bez atrybutu [ApiController] lub atrybutów obiektu źródłowego powiązania, takich jak [FromQuery], środowisko uruchomieniowe platformy ASP.NET Core próbuje użyć integratora modelu obiektów złożonych. 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 obiektu źródłowego 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 obiektu źródłowego powiązania ignoruje te typy specjalne.
  • [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 wnioskowane dla innych parametrów 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)
    

Uwaga

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 na platformie ASP.NET Core 2.2 i w nowszych wersjach — parametry typu „kolekcja” są w tych środowiskach domyślnie wnioskowane jako powiązane z poziomu treści żądania.

Wyłączanie reguł wnioskowania

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

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

Wnioskowanie żądania danych wieloczęściowych/formularza

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 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łączanie odpowiedzi 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 elementów formatujących dane wejściowe zarówno 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 wywieranie wpływu na jej wybranie na podstawie typu zawartoś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 zgłaszany 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