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
.
Method | 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:
- Wymaganie dotyczące routingu atrybutów
- Automatyczne odpowiedzi HTTP 400
- Wnioskowanie parametru obiektu źródłowego powiązania
- Wnioskowanie żądania danych wieloczęściowych/formularza
- Szczegóły problemów dotyczących kodów stanu błędu
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. Na 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ł:
- Wcześniej określony
BindingInfo.BindingSource
element nigdy nie został zastąpiony. - Przypisano
BindingSource.Services
parametr typu złożonego zarejestrowanego w kontenerze DI . - Przypisano
BindingSource.Body
parametr typu złożonego, który nie został zarejestrowany w kontenerze DI. - Parametr o nazwie, która jest wyświetlana jako wartość trasy w dowolnym szablonie trasy, jest przypisany
BindingSource.Path
. - Wszystkie inne parametry to
BindingSource.Query
.
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
. Na 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
- Wyświetl lub pobierz kod przykładowy. (Jak pobrać).
- Zwracane typy akcji kontrolera w internetowym interfejsie API platformy ASP.NET Core
- Obsługa błędów w internetowych interfejsach API opartych na kontrolerze ASP.NET Core
- Niestandardowe elementy formatujące w internetowym interfejsie API platformy ASP.NET Core
- Formatowanie danych odpowiedzi w internetowym interfejsie API platformy ASP.NET Core
- Dokumentacja internetowego interfejsu API platformy ASP.NET Core ze strukturą Swagger/interfejsem OpenAPI
- Routing do akcji kontrolera na platformie ASP.NET Core
- Debugowanie internetowych interfejsów API przy użyciu tunelowania portów programu Visual Studio
- Tworzenie internetowego interfejsu API przy użyciu 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. 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 | 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:
- Wymaganie dotyczące routingu atrybutów
- Automatyczne odpowiedzi HTTP 400
- Wnioskowanie parametru obiektu źródłowego powiązania
- Wnioskowanie żądania danych wieloczęściowych/formularza
- Szczegóły problemów dotyczących kodów stanu błędu
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. Na 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
. Na 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
- Wyświetl lub pobierz kod przykładowy. (Jak pobrać).
- Zwracane typy akcji kontrolera w internetowym interfejsie API platformy ASP.NET Core
- Obsługa błędów w internetowych interfejsach API opartych na kontrolerze ASP.NET Core
- Niestandardowe elementy formatujące w internetowym interfejsie API platformy ASP.NET Core
- Formatowanie danych odpowiedzi w internetowym interfejsie API platformy ASP.NET Core
- Dokumentacja internetowego interfejsu API platformy ASP.NET Core ze strukturą Swagger/interfejsem OpenAPI
- Routing do akcji kontrolera na platformie ASP.NET Core
- Debugowanie internetowych interfejsów API przy użyciu tunelowania portów programu Visual Studio
- Tworzenie internetowego interfejsu API przy użyciu platformy ASP.NET Core
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
.
Method | 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:
- Wymaganie dotyczące routingu atrybutów
- Automatyczne odpowiedzi HTTP 400
- Wnioskowanie parametru obiektu źródłowego powiązania
- Wnioskowanie żądania danych wieloczęściowych/formularza
- Szczegóły problemów dotyczących kodów stanu błędu
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. Na 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
. Na 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
- Zwracane typy akcji kontrolera w internetowym interfejsie API platformy ASP.NET Core
- Obsługa błędów w internetowych interfejsach API opartych na kontrolerze ASP.NET Core
- Niestandardowe elementy formatujące w internetowym interfejsie API platformy ASP.NET Core
- Formatowanie danych odpowiedzi w internetowym interfejsie API platformy ASP.NET Core
- Dokumentacja internetowego interfejsu API platformy ASP.NET Core ze strukturą Swagger/interfejsem OpenAPI
- Routing do akcji kontrolera na platformie ASP.NET Core
- Tworzenie internetowego interfejsu API przy użyciu platformy ASP.NET Core
[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
:
Method | 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:
- Wymaganie dotyczące routingu atrybutów
- Automatyczne odpowiedzi HTTP 400
- Wnioskowanie parametru obiektu źródłowego powiązania
- Wnioskowanie żądania danych wieloczęściowych/formularza
- Szczegóły problemu dotyczące kodów stanu błędu Funkcja Szczegóły problemu dotyczące kodów stanu błędu wymaga wersji zgodności 2.2 lub nowszej. Inne funkcje wymagają wersji zgodności 2.1 lub nowszej.
- Wymaganie dotyczące routingu atrybutów
- Automatyczne odpowiedzi HTTP 400
- Wnioskowanie parametru obiektu źródłowego powiązania
- Wnioskowanie żądania danych wieloczęściowych/formularza Te funkcje wymagają wersji zgodności 2.1 lub nowszej.
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. Na 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
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
. Na 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
- Zwracane typy akcji kontrolera w internetowym interfejsie API platformy ASP.NET Core
- Obsługa błędów w internetowych interfejsach API opartych na kontrolerze ASP.NET Core
- Niestandardowe elementy formatujące w internetowym interfejsie API platformy ASP.NET Core
- Formatowanie danych odpowiedzi w internetowym interfejsie API platformy ASP.NET Core
- Dokumentacja internetowego interfejsu API platformy ASP.NET Core ze strukturą Swagger/interfejsem OpenAPI
- Routing do akcji kontrolera na platformie ASP.NET Core
- Tworzenie internetowego interfejsu API przy użyciu platformy ASP.NET Core