Vytváření webových rozhraní API pomocí ASP.NET Core

ASP.NET Core podporuje vytváření webových rozhraní API pomocí kontrolerů nebo použití minimálních rozhraní API. Kontrolery ve webovém rozhraní API jsou třídy, které odvozují z ControllerBase. Kontrolery se aktivují a likvidují na základě každého požadavku.

Tento článek ukazuje, jak kontrolery využívat ke zpracování požadavků webového rozhraní API. Informace o vytváření webových rozhraní API bez kontrolerů najdete v kurzu: Vytvoření minimálního rozhraní API s ASP.NET Core.

Důležité

Počínaje ASP.NET Core 10 už známé koncové body rozhraní API při použití cookie ověřování nepřesměrovávají na přihlašovací stránky. Místo toho vrátí stavové kódy 401/403. Podrobnosti najdete v tématu Chování ověřování koncových bodů rozhraní API v ASP.NET Core.

ControllerBase class

Webové rozhraní API založené na kontroleru se skládá z jedné nebo několika tříd kontrolerů, které odvozují z ControllerBase. Šablona projektu webového rozhraní API poskytuje počáteční kontroler:

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

Kontrolery webového rozhraní API by obvykle měly odvozovat spíše z ControllerBase než z Controller. Controller odvozuje z ControllerBase a přidává podporu zobrazení. Je tedy určený pro zpracování webových stránek, nikoli požadavků webového rozhraní API. Pokud stejný kontroler musí podporovat zobrazení i webová rozhraní API, odvozujte z Controller.

Třída ControllerBase poskytuje mnoho vlastností a metod, které jsou užitečné pro zpracování požadavků HTTP. Například CreatedAtAction vrátí stavový kód 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);
}

Následující tabulka obsahuje příklady metod v ControllerBase.

Method Notes
BadRequest Vrátí stavový kód 400.
NotFound Vrátí stavový kód 404.
PhysicalFile Vrátí soubor.
TryUpdateModelAsync Vyvolá vazbu modelu.
TryValidateModel Vyvolá ověření modelu.

Seznam všech dostupných metod a vlastností najdete v tématu ControllerBase.

Attributes

Obor názvů Microsoft.AspNetCore.Mvc poskytuje atributy, které lze použít ke konfiguraci chování kontrolerů webového rozhraní API a metod akcí. Následující příklad používá atributy k určení podporované operace akce HTTP a všech známých stavových kódů HTTP, které by mohly být vráceny:

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

Tady je několik dalších příkladů atributů, které jsou k dispozici.

Attribute Notes
[Route] Určuje vzor adresy URL pro kontroler nebo akci.
[Bind] Určuje předponu a vlastnosti, které se mají zahrnout pro vazbu modelu.
[HttpGet] Identifikuje akci, která podporuje operaci akce HTTP GET.
[Consumes] Určuje datové typy, které akce přijímá.
[Produces] Určuje datové typy, které akce vrací.

Seznam, který obsahuje dostupné atributy, najdete v oboru názvů Microsoft.AspNetCore.Mvc.

Atribut ApiController

Atribut [ApiController] lze použít u třídy kontroleru k povolení následujícího názorného chování specifického pro rozhraní API:

Atribut u konkrétních kontrolerů

Atribut [ApiController] lze použít pro konkrétní kontrolery, jako v následujícím příkladu ze šablony projektu:

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

Atribut u několika kontrolerů

Jedním z přístupů k použití atributu ve více než jednom kontroleru je vytvoření vlastní základní třídy kontroleru, která je označená atributem [ApiController]. Následující příklad ukazuje vlastní základní třídu a kontroler, který se z ní odvozuje:

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

Atribut u sestavení

Atribut [ApiController] lze použít pro sestavení. Při použití atributu [ApiController] u sestavení je pro všechny kontrolery v sestavení použitý atribut [ApiController]. Pro jednotlivé ovladače neexistuje možnost výslovně nesouhlasit. Pro soubor Program.cs použijte atribut na úrovni sestavení:

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

Požadavek na směrování atributů

Atribut [ApiController] vyžaduje použití směrování atributů. Například:

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

Akce jsou nepřístupné prostřednictvím konvenčních tras definovaných pomocí UseEndpoints, UseMvc nebo UseMvcWithDefaultRoute.

Automatické odpovědi HTTP 400

Atribut [ApiController] zajistí, že chyby ověření modelu automaticky aktivují odpověď HTTP 400. V důsledku toho je následující kód v metodě akce nepotřebný:

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

ASP.NET Core MVC k provedení předchozí kontroly používá filtr akcí ModelStateInvalidFilter.

Výchozí odpověď „BadRequest“

Výchozí typ odpovědi pro odpověď HTTP 400 je ValidationProblemDetails. Následující text odpovědi je příkladem serializovaného typu:

{
  "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:

  • Poskytuje strojově čitelný formát pro určení chyb v odpovědích webového rozhraní API.
  • Splňuje specifikaci RFC 7807.

Pokud chcete, aby automatické a vlastní odpovědi byly konzistentní, volejte metodu ValidationProblem místo BadRequest. ValidationProblem vrátí objekt ValidationProblemDetails i automatickou odpověď.

Zaznamenávání automatických odpovědí 400

Pokud chcete protokolovat automatické odpovědi 400, nastavte vlastnost delegáta InvalidModelStateResponseFactory tak, aby prováděla vlastní zpracování. Ve výchozím nastavení InvalidModelStateResponseFactory využívá ProblemDetailsFactory k vytvoření instance ValidationProblemDetails.

Následující příklad ukazuje, jak načíst instanci ILogger<TCategoryName> pro protokolování informací o automatické odpovědi 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();

Vypnutí automatické odpovědi 400

Chcete-li zakázat automatické chování 400, nastavte vlastnost SuppressModelStateInvalidFilter na true. Přidejte následující zvýrazněný kód:

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

Odvozování parametrů zdroje vazby

Atribut zdroje vazby definuje umístění, ve kterém se nachází hodnota parametru akce. Existují následující zdrojové atributy vazby:

Attribute Zdroj vazby
[FromBody] Obsah požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr dotazu v řetězci požadavku
[FromRoute] Přesměrovat data z aktuálního požadavku
[FromServices] Požadovaná služba vložená jako parametr akce
[AsParameters] Parametry metody

Warning

Nepoužívejte [FromRoute], pokud hodnoty mohou obsahovat %2f (to znamená /). %2f se nebude převést na /. Pokud hodnota může obsahovat [FromQuery], použijte %2f.

Bez atributu [ApiController] nebo atributů zdroje vazby, jako je [FromQuery], se modul runtime ASP.NET Core pokusí použít komplexní objektový vazač modelů. Komplexní objektový vazač modelů načítá data z poskytovatelů hodnot v definovaném pořadí.

V následujícím příkladu atribut [FromQuery] označuje, že hodnota parametru discontinuedOnly je poskytnuta v řetězci dotazu adresy URL požadavku:

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

Atribut [ApiController] používá odvozená pravidla pro výchozí zdroje dat parametrů akce. Tato pravidla vám ušetří nutnost ručně identifikovat zdroje vazeb použitím atributů na parametry akce. Pravidla funkce zdroje vazby se řídí následovně:

  • [FromServices] se odvozuje pro parametry komplexního typu, které jsou registrované v kontejneru závislostí.
  • [FromBody] se odvozuje pro parametry komplexního typu, které nejsou registrované v kontejneru injektáže závislostí (DI). Výjimkou pro odvozené pravidlo [FromBody] je libovolný komplexní předdefinovaný typ se speciálním významem, jako je IFormCollection a CancellationToken. Kód pro odvození zdroje vazby ignoruje tyto speciální typy.
  • [FromForm] se odvozuje pro parametry typu IFormFile a IFormFileCollection. Neodvozuje se pro žádné jednoduché nebo uživatelsky definované typy.
  • [FromRoute] se odvozuje pro libovolný název parametru akce odpovídající parametru v šabloně trasy. Pokud parametru akce odpovídá více než jedna trasa, za [FromRoute] se považuje libovolná hodnota trasy.
  • [FromQuery] je odvozený pro všechny ostatní parametry akcí.

Poznámky k odvozování FromBody

[FromBody] se neodvozuje pro jednoduché typy, jako je string nebo int. Proto by se atribut [FromBody] měl pro jednoduché typy používat, pokud je tato funkce potřebná.

Pokud má akce více parametrů vázaných z textu požadavku, vyvolá se výjimka. Například všechny následující podpisy akčních metod způsobují výjimku:

  • [FromBody] se odvozuje v obou případech, protože jde o komplexní typy.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atribut [FromBody] v jednom případě, odvozený v druhém, protože jde o komplexní typ.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atribut [FromBody] v obou případech.

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

Poznámky k odvozování FromServices

Když je typ nakonfigurován jako služba, vazba parametrů prostřednictvím injektování závislostí je použita. To znamená, že není nutné explicitně použít [FromServices] atribut na parametr. V následujícím kódu vrátí obě akce čas:

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

Ve výjimečných případech může automatické DI způsobit problémy v aplikacích, které mají typ v DI, který je také přijímán v metodách akcí API kontroleru. Není běžné mít typ v DI a jako argument v akci kontroleru rozhraní API.

Pokud chcete zakázat odvozování [FromServices] pro jeden parametr akce, použijte u parametru požadovaný atribut zdroje vazby. Použijte například atribut [FromBody] pro parametr akce, který by měl být vázaný z textu požadavku.

Pokud chcete zakázat [FromServices] odvozování globálně, nastavte 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 se kontrolují při spuštění aplikace s IServiceProviderIsService cílem určit, jestli argument v akci kontroleru rozhraní API pochází z DI nebo z jiných zdrojů.

Mechanismus odvození zdroje vazby parametrů akce kontroleru rozhraní API používá následující pravidla:

Zákaz odvozených pravidel

Pokud chcete zakázat odvozování zdroje vazby, nastavte SuppressInferBindingSourcesForParameters na true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
        options.DisableImplicitFromServicesParameters = true;
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Odvozování požadavků typu multipart/form-data

Atribut [ApiController] použije odvozené pravidlo pro parametry akce typu IFormFile a IFormFileCollection. Typ obsahu požadavku multipart/form-data je odvozený pro tyto typy.

Pokud chcete zakázat výchozí chování, nastavte vlastnost 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();

Podrobnosti o problému se stavovými kódy chyb

MVC transformuje výsledek chyby (výsledek se stavovým kódem 400 nebo vyšší) na výsledek s typem ProblemDetails. Typ ProblemDetails je založený na specifikaci RFC 7807 pro poskytování strojově čitelných podrobností o chybě v odpovědi HTTP.

Zvažte použití následujícího kódu v akci kontroleru:

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

Metoda NotFound vytvoří stavový kód HTTP 404 s textem ProblemDetails. Například:

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

Zakázat odpověď ProblemDetails

Automatické generování ProblemDetails pro chybové stavové kódy je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavena na true. Přidejte následující kód:

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

Definování podporovaných typů obsahu požadavku s atributem [Consumes]

Akce ve výchozím nastavení podporuje všechny dostupné typy obsahu požadavku. Pokud je například aplikace nakonfigurovaná tak, aby podporovala vstupní formátory JSON i XML, akce podporuje více typů obsahu, včetně application/json a application/xml.

Atribut [Consumes] umožňuje akci omezit podporované typy obsahu požadavku. Atribut [Consumes] použijte u akce nebo kontroleru s určením jednoho nebo několika typů obsahu:

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

Akce CreateProduct v předchozím kódu určuje typ obsahu application/xml. Požadavky směrované na tuto akci musí zadat hlavičku Content-Type typu application/xml. Požadavky, které neurčují hlavičku Content-Type typu application/xml, vedou k odpovědi 415 Nepodporovaný typ média.

Atribut [Consumes] také akci umožňuje ovlivnit její výběr na základě typu obsahu příchozího požadavku, a to použitím omezení typu. Představte si následující příklad:

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

V předchozím kódu je třída ConsumesController nakonfigurovaná tak, aby zpracovávala požadavky odeslané na adresu URL https://localhost:5001/api/Consumes. Obě akce kontroleru, PostJson i PostForm, zpracovávají požadavky POST se stejnou adresou URL. Bez atributu [Consumes] aplikujícího omezení typu se vyvolá výjimka nejednoznačné shody.

Atribut [Consumes] se použije u obou akcí. Akce PostJson zpracovává požadavky odeslané s hlavičkou Content-Type typu application/json. Akce PostForm zpracovává požadavky odeslané s hlavičkou Content-Type typu application/x-www-form-urlencoded.

Dodatečné zdroje

ASP.NET Core podporuje vytváření webových rozhraní API pomocí kontrolerů nebo použití minimálních rozhraní API. Kontrolery ve webovém rozhraní API jsou třídy, které odvozují z ControllerBase. Tento článek ukazuje, jak kontrolery využívat ke zpracování požadavků webového rozhraní API. Informace o vytváření webových rozhraní API bez kontrolerů najdete v kurzu: Vytvoření minimálního rozhraní API s ASP.NET Core.

ControllerBase třída

Webové rozhraní API založené na kontroleru se skládá z jedné nebo několika tříd kontrolerů, které odvozují z ControllerBase. Šablona projektu webového rozhraní API poskytuje počáteční kontroler:

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

Kontrolery webového rozhraní API by obvykle měly odvozovat spíše z ControllerBase než z Controller. Controller odvozuje z ControllerBase a přidává podporu zobrazení. Je tedy určený pro zpracování webových stránek, nikoli požadavků webového rozhraní API. Pokud stejný kontroler musí podporovat zobrazení i webová rozhraní API, odvozujte z Controller.

Třída ControllerBase poskytuje mnoho vlastností a metod, které jsou užitečné pro zpracování požadavků HTTP. Například CreatedAtAction vrátí stavový kód 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);
}

Následující tabulka obsahuje příklady metod v ControllerBase.

Method Notes
BadRequest Vrátí stavový kód 400.
NotFound Vrátí stavový kód 404.
PhysicalFile Vrátí soubor.
TryUpdateModelAsync Vyvolá vazbu modelu.
TryValidateModel Vyvolá ověření modelu.

Seznam všech dostupných metod a vlastností najdete v tématu ControllerBase.

Attributes

Obor názvů Microsoft.AspNetCore.Mvc poskytuje atributy, které lze použít ke konfiguraci chování kontrolerů webového rozhraní API a metod akcí. Následující příklad používá atributy k určení podporované operace akce HTTP a všech známých stavových kódů HTTP, které by mohly být vráceny:

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

Tady je několik dalších příkladů atributů, které jsou k dispozici.

Attribute Notes
[Route] Určuje vzor adresy URL pro kontroler nebo akci.
[Bind] Určuje předponu a vlastnosti, které se mají zahrnout pro vazbu modelu.
[HttpGet] Identifikuje akci, která podporuje operaci akce HTTP GET.
[Consumes] Určuje datové typy, které akce přijímá.
[Produces] Určuje datové typy, které akce vrací.

Seznam, který obsahuje dostupné atributy, najdete v oboru názvů Microsoft.AspNetCore.Mvc.

Atribut ApiController

Atribut [ApiController] lze použít u třídy kontroleru k povolení následujícího názorného chování specifického pro rozhraní API:

Atribut u konkrétních kontrolerů

Atribut [ApiController] lze použít pro konkrétní kontrolery, jako v následujícím příkladu ze šablony projektu:

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

Atribut u několika kontrolerů

Jedním z přístupů k použití atributu ve více než jednom kontroleru je vytvoření vlastní základní třídy kontroleru, která je označená atributem [ApiController]. Následující příklad ukazuje vlastní základní třídu a kontroler, který se z ní odvozuje:

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

Atribut u sestavení

Atribut [ApiController] lze použít pro sestavení. Při použití atributu [ApiController] u sestavení je pro všechny kontrolery v sestavení použitý atribut [ApiController]. Pro jednotlivé ovladače neexistuje možnost výslovně nesouhlasit. Pro soubor Program.cs použijte atribut na úrovni sestavení:

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

Požadavek na směrování atributů

Příznak [ApiController] činí směrování na základě atributů povinným. Například:

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

Akce jsou nepřístupné prostřednictvím konvenčních tras definovaných pomocí UseEndpoints, UseMvc nebo UseMvcWithDefaultRoute.

Automatické odpovědi HTTP 400

Atribut [ApiController] zajistí, že chyby ověření modelu automaticky aktivují odpověď HTTP 400. V důsledku toho je následující kód v metodě akce nepotřebný:

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

ASP.NET Core MVC k provedení předchozí kontroly používá filtr akcí ModelStateInvalidFilter.

Výchozí odpověď BadRequest

Následující text odpovědi je příkladem serializovaného typu:

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

Výchozí typ odpovědi pro odpověď HTTP 400 je ValidationProblemDetails. Následující text odpovědi je příkladem serializovaného typu:

{
  "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:

  • Poskytuje strojově čitelný formát pro určení chyb v odpovědích webového rozhraní API.
  • Splňuje specifikaci RFC 7807.

Pokud chcete, aby automatické a vlastní odpovědi byly konzistentní, volejte metodu ValidationProblem místo BadRequest. ValidationProblem vrátí objekt ValidationProblemDetails i automatickou odpověď.

Záznam automatických odpovědí 400

Pokud chcete protokolovat automatické odpovědi 400, nastavte vlastnost delegáta InvalidModelStateResponseFactory tak, aby prováděla vlastní zpracování. Ve výchozím nastavení InvalidModelStateResponseFactory využívá ProblemDetailsFactory k vytvoření instance ValidationProblemDetails.

Následující příklad ukazuje, jak načíst instanci ILogger<TCategoryName> pro protokolování informací o automatické odpovědi 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();

Zakázat automatickou odpověď 400

Chcete-li zakázat automatické chování 400, nastavte vlastnost SuppressModelStateInvalidFilter na true. Přidejte následující zvýrazněný kód:

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

Odvozování parametrů zdroje vazby

Atribut zdroje vazby definuje umístění, ve kterém se nachází hodnota parametru akce. Existují následující zdrojové atributy vazby:

Attribute Vazební zdroj
[FromBody] Obsah požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Dotazovací parametr řetězce
[FromRoute] Směrování dat z aktuálního požadavku
[FromServices] Služba požadavku vložená jako parametr pro akci

Warning

Nepoužívejte [FromRoute], pokud hodnoty mohou obsahovat %2f (to znamená /). %2f se nepřevedou na /. Pokud hodnota může obsahovat [FromQuery], použijte %2f.

Bez atributu [ApiController] nebo atributů zdroje vazby, jako je [FromQuery], se modul runtime ASP.NET Core pokusí použít komplexní objektový vazač modelů. Komplexní objektový vazač modelů načítá data z poskytovatelů hodnot v definovaném pořadí.

V následujícím příkladu atribut [FromQuery] označuje, že hodnota parametru discontinuedOnly je poskytnuta v řetězci dotazu adresy URL požadavku:

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

Atribut [ApiController] používá odvozená pravidla pro výchozí zdroje dat parametrů akce. Tato pravidla vám ušetří nutnost ručně identifikovat zdroje vazeb použitím atributů na parametry akce. Pravidla pro odvozování zdrojů vazby se chovají následujícím způsobem:

  • [FromBody] se odvozuje pro parametry komplexního typu, které nejsou registrované v kontejneru injektáže závislostí. Výjimkou pro odvozené pravidlo [FromBody] je libovolný komplexní předdefinovaný typ se speciálním významem, jako je IFormCollection a CancellationToken. Kód pro odvození zdroje vazby ignoruje tyto speciální typy.
  • [FromForm] se odvozuje pro parametry typu IFormFile a IFormFileCollection. Neodvozuje se pro žádné jednoduché nebo uživatelsky definované typy.
  • [FromRoute] je automaticky určován pro jakýkoli název parametru akce, který odpovídá parametru v šabloně trasy. Pokud parametru akce odpovídá více než jedna trasa, za [FromRoute] se považuje libovolná hodnota trasy.
  • [FromQuery] je odvozován pro všechny ostatní parametry akcí.

Poznámky k inferenci FromBody

[FromBody] se neodvozuje pro jednoduché typy, jako je string nebo int. Proto by se atribut [FromBody] měl pro jednoduché typy používat, pokud je tato funkce potřebná.

Pokud má akce více parametrů vázaných z textu požadavku, vyvolá se výjimka. Například všechny následující podpisy metody akce způsobují výjimku:

  • [FromBody] se odvozuje v obou případech, protože jde o komplexní typy.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atribut [FromBody] v jednom případě, odvozený v druhém, protože jde o komplexní typ.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atribut [FromBody] v obou případech.

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

Zákaz odvozených pravidel

Pokud chcete zakázat odvozování zdroje vazby, nastavte SuppressInferBindingSourcesForParameters na true:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Inferenční zpracování požadavků multipart/form-data

Atribut [ApiController] použije odvozené pravidlo pro parametry akce typu IFormFile a IFormFileCollection. Typ obsahu požadavku multipart/form-data je odvozený pro tyto typy.

Pokud chcete zakázat výchozí chování, nastavte vlastnost 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();

Podrobnosti o problému se stavovými kódy chyb

MVC transformuje výsledek chyby (výsledek se stavovým kódem 400 nebo vyšší) na výsledek s typem ProblemDetails. Typ ProblemDetails je založený na specifikaci RFC 7807 pro poskytování strojově čitelných podrobností o chybě v odpovědi HTTP.

Zvažte použití následujícího kódu v akci kontroleru:

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

Metoda NotFound vytvoří stavový kód HTTP 404 s textem ProblemDetails. Například:

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

Vypnout odpověď ProblemDetails

Automatické vytvoření ProblemDetails pro stavové kódy chyb je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavena 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();

Definování podporovaných typů obsahu požadavku s atributem [Consumes]

Akce ve výchozím nastavení podporuje všechny dostupné typy obsahu požadavku. Pokud je například aplikace nakonfigurována tak, aby podporovala vstupní formátovací moduly pro JSON i XML, akce podporuje více typů obsahu, včetně application/json a application/xml.

Atribut [Consumes] umožňuje akci omezit podporované typy obsahu požadavku. Atribut [Consumes] použijte u akce nebo kontroleru s určením jednoho nebo několika typů obsahu:

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

Akce CreateProduct v předchozím kódu určuje typ obsahu application/xml. Požadavky směrované na tuto akci musí uvést hlavičku Content-Type typu application/xml. Požadavky, které neurčují hlavičku Content-Type typu application/xml, vedou k odpovědi 415 Nepodporovaný typ média.

Atribut [Consumes] také akci umožňuje ovlivnit její výběr na základě typu obsahu příchozího požadavku, a to použitím omezení typu. Představte si následující příklad:

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

V předchozím kódu je třída ConsumesController nakonfigurovaná tak, aby zpracovávala požadavky odeslané na adresu URL https://localhost:5001/api/Consumes. Obě akce kontroleru, PostJson i PostForm, zpracovávají požadavky POST se stejnou adresou URL. Bez atributu [Consumes] aplikujícího omezení typu se vyvolá výjimka nejednoznačné shody.

Atribut [Consumes] se použije u obou akcí. Akce PostJson zpracovává požadavky odeslané s hlavičkou Content-Type typu application/json. Akce PostForm zpracovává požadavky odeslané s hlavičkou Content-Type typu application/x-www-form-urlencoded.

Dodatečné zdroje

ASP.NET Core podporuje vytváření služeb RESTful v jazyce C# (služby RESTful se označují také jako webová rozhraní API). Webové rozhraní API používá ke zpracování požadavků kontrolery. Kontrolery ve webovém rozhraní API jsou třídy, které odvozují z ControllerBase. Tento článek ukazuje, jak kontrolery využívat ke zpracování požadavků webového rozhraní API.

Zobrazení nebo stažení vzorového kódu (postup stahování).

ControllerBase class

Webové rozhraní API se skládá z jedné nebo několika tříd kontrolerů, které odvozují z ControllerBase. Šablona projektu webového rozhraní API poskytuje počáteční kontroler:

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

Nevytvářejte kontroler webového rozhraní API odvozením z třídy Controller. Controller odvozuje z ControllerBase a přidává podporu zobrazení. Je tedy určený pro zpracování webových stránek, nikoli požadavků webového rozhraní API. Toto pravidlo má výjimku: Pokud plánujete použít stejný kontroler pro zobrazení i webová rozhraní API, odvozujte ho z třídy Controller.

Třída ControllerBase poskytuje mnoho vlastností a metod, které jsou užitečné pro zpracování požadavků HTTP. Například ControllerBase.CreatedAtAction vrátí stavový kód 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);
}

Tady je několik dalších příkladů metod, které ControllerBase poskytuje.

Method Notes
BadRequest Vrátí stavový kód 400.
NotFound Vrátí stavový kód 404.
PhysicalFile Vrátí soubor.
TryUpdateModelAsync Vyvolá vazbu modelu.
TryValidateModel Vyvolá ověření modelu.

Seznam všech dostupných metod a vlastností najdete v tématu ControllerBase.

Attributes

Obor názvů Microsoft.AspNetCore.Mvc poskytuje atributy, které lze použít ke konfiguraci chování kontrolerů webového rozhraní API a metod akcí. Následující příklad používá atributy k určení podporované operace akce HTTP a všech známých stavových kódů HTTP, které by mohly být vráceny:

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

Tady je několik dalších příkladů atributů, které jsou k dispozici.

Attribute Notes
[Route] Určuje vzor adresy URL pro kontroler nebo akci.
[Bind] Určuje předponu a vlastnosti, které se mají zahrnout pro vazbu modelu.
[HttpGet] Identifikuje akci, která podporuje operaci akce HTTP GET.
[Consumes] Určuje datové typy, které akce přijímá.
[Produces] Určuje datové typy, které akce vrací.

Seznam, který obsahuje dostupné atributy, najdete v oboru názvů Microsoft.AspNetCore.Mvc.

Atribut ApiController

Atribut [ApiController] lze použít u třídy kontroleru k povolení následujícího názorného chování specifického pro rozhraní API:

Atribut u konkrétních kontrolerů

Atribut [ApiController] lze použít pro konkrétní kontrolery, jako v následujícím příkladu ze šablony projektu:

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

Atribut u několika kontrolerů

Jedním z přístupů k použití atributu ve více než jednom kontroleru je vytvoření vlastní základní třídy kontroleru, která je označená atributem [ApiController]. Následující příklad ukazuje vlastní základní třídu a kontroler, který se z ní odvozuje:

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

Atribut u sestavení

Atribut [ApiController] lze použít pro sestavení. Anotace tímto způsobem aplikuje chování webového rozhraní API na všechny kontrolery v sestavení. Pro jednotlivé ovladače neexistuje možnost výslovně nesouhlasit. Použijte atribut na úrovni sestavení ke deklaraci oboru názvů, která obklopuje třídu Startup:

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

Požadavek na směrování atributů

Příznak [ApiController] činí směrování na základě atributů povinným. Například:

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

Akce jsou nepřístupné prostřednictvím konvenčních tras definovaných pomocí UseEndpoints, UseMvc nebo UseMvcWithDefaultRoute v Startup.Configure.

Automatické odpovědi HTTP 400

Atribut [ApiController] zajistí, že chyby ověření modelu automaticky aktivují odpověď HTTP 400. V důsledku toho je následující kód v metodě akce nepotřebný:

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

ASP.NET Core MVC k provedení předchozí kontroly používá filtr akcí ModelStateInvalidFilter.

Výchozí odpověď BadRequest

Následující text požadavku je příkladem serializovaného typu:

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

Výchozí typ odpovědi pro odpověď HTTP 400 je ValidationProblemDetails. Následující text požadavku je příkladem serializovaného typu:

{
  "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:

  • Poskytuje strojově čitelný formát pro určení chyb v odpovědích webového rozhraní API.
  • Splňuje specifikaci RFC 7807.

Pokud chcete, aby automatické a vlastní odpovědi byly konzistentní, volejte metodu ValidationProblem místo BadRequest. ValidationProblem vrátí objekt ValidationProblemDetails i automatickou odpověď.

Protokolování 400 automatických odpovědí

Pokud chcete protokolovat automatické odpovědi 400, nastavte vlastnost delegáta InvalidModelStateResponseFactory tak, aby prováděla vlastní zpracování v Startup.ConfigureServices. Ve výchozím nastavení InvalidModelStateResponseFactory využívá ProblemDetailsFactory k vytvoření instance ValidationProblemDetails.

Následující příklad ukazuje, jak získat instanci ILogger<TCategoryName> pro zaznamenání informací o automatické odpovědi s chybovým kódem 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);
        };
    });

Zakázat automatickou odpověď 400

Chcete-li zakázat automatické chování 400, nastavte vlastnost SuppressModelStateInvalidFilter na true. Přidejte následující zvýrazněný kód v 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;
    });

Odvozování parametrů zdroje vazby

Atribut zdroje vazby definuje umístění, ve kterém se nachází hodnota parametru akce. Existují následující zdrojové atributy vazby:

Attribute Zdroj vazby
[FromBody] Obsah požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr dotazovacího řetězce požadavku
[FromRoute] Přesměrování dat z aktuálního požadavku
[FromServices] Služba zpracování požadavků je vkládána jako parametr akce

Warning

Nepoužívejte [FromRoute], pokud hodnoty mohou obsahovat %2f (to znamená /). %2f se nepřevedou na /. Pokud hodnota může obsahovat [FromQuery], použijte %2f.

Bez atributu [ApiController] nebo atributů zdroje vazby, jako je [FromQuery], se modul runtime ASP.NET Core pokusí použít komplexní objektový vazač modelů. Komplexní objektový vazač modelů načítá data z poskytovatelů hodnot v definovaném pořadí.

V následujícím příkladu atribut [FromQuery] označuje, že hodnota parametru discontinuedOnly je poskytnuta v řetězci dotazu adresy URL požadavku:

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

Atribut [ApiController] používá odvozená pravidla pro výchozí zdroje dat parametrů akce. Tato pravidla vám ušetří nutnost ručně identifikovat zdroje vazeb použitím atributů na parametry akce. Pravidla odvození zdroje přiřazení se chovají následovně:

  • [FromBody] se odvozuje pro parametry komplexního typu. Výjimkou pro odvozené pravidlo [FromBody] je libovolný komplexní předdefinovaný typ se speciálním významem, jako je IFormCollection a CancellationToken. Tyto speciální typy kód odvození zdroje vazby ignoruje.
  • [FromForm] se odvozuje pro parametry typu IFormFile a IFormFileCollection. Neodvozuje se pro žádné jednoduché nebo uživatelsky definované typy.
  • Parametr akce [FromRoute] se odvozuje, pokud nějaký jeho název odpovídá libovolnému parametru v šabloně trasy. Pokud parametru akce odpovídá více než jedna trasa, za [FromRoute] se považuje libovolná hodnota trasy.
  • [FromQuery] je odvozený pro všechny ostatní parametry akcí.

Poznámky k odvozování FromBody

[FromBody] se neodvozuje pro jednoduché typy, jako je string nebo int. Proto by se atribut [FromBody] měl pro jednoduché typy používat, pokud je tato funkce potřebná.

Pokud má akce více parametrů vázaných z textu požadavku, vyvolá se výjimka. Například všechny následující podpisy akčních metod způsobují výjimku:

  • [FromBody] se odvozuje v obou případech, protože jde o komplexní typy.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atribut [FromBody] v jednom případě, odvozený v druhém, protože jde o komplexní typ.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atribut [FromBody] v obou případech.

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

Zákaz odvozených pravidel

Pokud chcete zakázat odvozování zdroje vazby, nastavte SuppressInferBindingSourcesForParameters na true. V souboru Startup.ConfigureServices přidejte následující kód:

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

Odvozování požadavků typu multipart/form-data

Atribut [ApiController] použije odvozené pravidlo pro parametry akce typu IFormFile a IFormFileCollection. Typ obsahu požadavku multipart/form-data je odvozený pro tyto typy.

Pokud chcete zakázat výchozí chování, nastavte vlastnost SuppressConsumesConstraintForFormFileParameters na true v 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;
    });

Podrobnosti o problému se stavovými kódy chyb

MVC transformuje výsledek chyby (výsledek se stavovým kódem 400 nebo vyšší) na výsledek s typem ProblemDetails. Typ ProblemDetails je založený na specifikaci RFC 7807 pro poskytování strojově čitelných podrobností o chybě v odpovědi HTTP.

Zvažte použití následujícího kódu v akci kontroleru:

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

Metoda NotFound vytvoří stavový kód HTTP 404 s textem ProblemDetails. Například:

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

Zakázat odpověď ProblemDetails

Automatické generování ProblemDetails pro chybové stavové kódy je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavena na true. V souboru Startup.ConfigureServices přidejte následující kód:

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

Definování podporovaných typů obsahu požadavku s atributem [Consumes]

Akce ve výchozím nastavení podporuje všechny dostupné typy obsahu požadavku. Pokud je například aplikace nakonfigurovaná tak, aby podporovala vstupní formátory JSON i XML, akce podporuje více typů obsahu, včetně application/json a application/xml.

Atribut [Consumes] umožňuje akci omezit podporované typy obsahu požadavku. Atribut [Consumes] použijte u akce nebo kontroleru s určením jednoho nebo několika typů obsahu:

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

Akce CreateProduct v předchozím kódu určuje typ obsahu application/xml. Požadavky směrované na tuto akci musí zadat hlavičku Content-Type typu application/xml. Požadavky, které neurčují hlavičku Content-Type typu application/xml, vedou k odpovědi 415 Nepodporovaný typ média.

Atribut [Consumes] také akci umožňuje ovlivnit její výběr na základě typu obsahu příchozího požadavku, a to použitím omezení typu. Představte si následující příklad:

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

V předchozím kódu je třída ConsumesController nakonfigurovaná tak, aby zpracovávala požadavky odeslané na adresu URL https://localhost:5001/api/Consumes. Obě akce kontroleru, PostJson i PostForm, zpracovávají požadavky POST se stejnou adresou URL. Bez atributu [Consumes] aplikujícího omezení typu se vyvolá výjimka nejednoznačné shody.

Atribut [Consumes] se použije u obou akcí. Akce PostJson zpracovává požadavky odeslané s hlavičkou Content-Type typu application/json. Akce PostForm zpracovává požadavky odeslané s hlavičkou Content-Type typu application/x-www-form-urlencoded.

Dodatečné zdroje

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

Nevytvářejte kontroler webového rozhraní API odvozením z třídy Controller. Controller odvozuje z ControllerBase a přidává podporu zobrazení. Je tedy určený pro zpracování webových stránek, nikoli požadavků webového rozhraní API. Toto pravidlo má výjimku: Pokud plánujete použít stejný kontroler pro zobrazení i webová rozhraní API, odvozujte ho z třídy Controller. Třída ControllerBase poskytuje mnoho vlastností a metod, které jsou užitečné pro zpracování požadavků HTTP. Například ControllerBase.CreatedAtAction vrátí stavový kód 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);
}

Tady je několik dalších příkladů metod, které ControllerBase poskytuje:

Method Notes
BadRequest Vrátí stavový kód 400.
NotFound Vrátí stavový kód 404.
PhysicalFile Vrátí soubor.
TryUpdateModelAsync Vyvolá vazbu modelu.
TryValidateModel Vyvolá ověření modelu.

Seznam všech dostupných metod a vlastností najdete v tématu ControllerBase.

Attributes

Obor názvů Microsoft.AspNetCore.Mvc poskytuje atributy, které lze použít ke konfiguraci chování kontrolerů webového rozhraní API a metod akcí. Následující příklad používá atributy k určení podporované operace akce HTTP a všech známých stavových kódů HTTP, které by mohly být vráceny:

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

Tady je několik dalších příkladů atributů, které jsou k dispozici:

Attribute Notes
[Route] Určuje vzor adresy URL pro kontroler nebo akci.
[Bind] Určuje předponu a vlastnosti, které se mají zahrnout pro vazbu modelu.
[HttpGet] Identifikuje akci, která podporuje operaci akce HTTP GET.
[Consumes] Určuje datové typy, které akce přijímá.
[Produces] Určuje datové typy, které akce vrací.

Seznam, který obsahuje dostupné atributy, najdete v oboru názvů Microsoft.AspNetCore.Mvc.

Atribut ApiController

Atribut [ApiController] lze použít u třídy kontroleru k povolení následujícího názorného chování specifického pro rozhraní API:

Atribut u konkrétních kontrolerů

Atribut [ApiController] lze použít pro konkrétní kontrolery, jako v následujícím příkladu ze šablony projektu:

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

Atribut u několika kontrolerů

Jedním z přístupů k použití atributu ve více než jednom kontroleru je vytvoření vlastní základní třídy kontroleru, která je označená atributem [ApiController]. Následující příklad ukazuje vlastní základní třídu a kontroler, který se z ní odvozuje:

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

Atribut u sestavení

Pokud je verze kompatibility nastavená na 2.2 nebo novější, je možné pro sestavení použít atribut [ApiController]. Anotace tímto způsobem aplikuje chování webového rozhraní API na všechny kontrolery v sestavení. Pro jednotlivé ovladače neexistuje možnost výslovně nesouhlasit. Použijte atribut na úrovni sestavení ke deklaraci oboru názvů, která obklopuje třídu Startup:

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

Požadavek na směrování atributů

Příznak [ApiController] činí směrování na základě atributů povinným. Například:

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

Akce jsou nepřístupné prostřednictvím konvenčních tras definovaných pomocí UseMvc nebo UseMvcWithDefaultRoute v Startup.Configure.

Automatické odpovědi HTTP 400

Atribut [ApiController] zajistí, že chyby ověření modelu automaticky aktivují odpověď HTTP 400. V důsledku toho je následující kód v metodě akce nepotřebný:

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

ASP.NET Core MVC k provedení předchozí kontroly používá filtr akcí ModelStateInvalidFilter.

Výchozí odpověď BadRequest

Při použití verze kompatibility 2.1 je pro odpověď HTTP 400 výchozím typem odpovědi SerializableError. Následující text požadavku je příkladem serializovaného typu:

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

Při použití verze kompatibility 2.2 nebo novější je pro odpověď HTTP 400 výchozím typem odpovědi ValidationProblemDetails. Následující text požadavku je příkladem serializovaného typu:

{
  "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:

  • Poskytuje strojově čitelný formát pro určení chyb v odpovědích webového rozhraní API.
  • Splňuje specifikaci RFC 7807.

Pokud chcete, aby automatické a vlastní odpovědi byly konzistentní, volejte metodu ValidationProblem místo BadRequest. ValidationProblem vrátí objekt ValidationProblemDetails i automatickou odpověď.

Zaznamenávání automatických odpovědí 400

Viz Jak protokolovat automatické odpovědi 400 při chybách ověření modelu (dotnet/AspNetCore.Docs#12157).

Vypnutí automatické odpovědi 400

Chcete-li zakázat automatické chování 400, nastavte vlastnost SuppressModelStateInvalidFilter na true. Přidejte následující zvýrazněný kód v Startup.ConfigureServices:

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

Odvozování parametrů zdroje vazby

Atribut zdroje vazby definuje umístění, ve kterém se nachází hodnota parametru akce. Existují následující zdrojové atributy vazby:

Attribute Zdroj vazby
[FromBody] Obsah požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr dotazu v řetězci požadavku
[FromRoute] Přesměrovat data z aktuálního požadavku
[FromServices] Požadovaná služba vložená jako parametr akce

Warning

Nepoužívejte [FromRoute], pokud hodnoty mohou obsahovat %2f (to znamená /). %2f se nebude převést na /. Pokud hodnota může obsahovat [FromQuery], použijte %2f. Bez atributu [ApiController] nebo atributů zdroje vazby, jako je [FromQuery], se modul runtime ASP.NET Core pokusí použít komplexní objektový vazač modelů. Komplexní objektový vazač modelů načítá data z poskytovatelů hodnot v definovaném pořadí.

V následujícím příkladu atribut [FromQuery] označuje, že hodnota parametru discontinuedOnly je poskytnuta v řetězci dotazu adresy URL požadavku:

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

Atribut [ApiController] používá odvozená pravidla pro výchozí zdroje dat parametrů akce. Tato pravidla vám ušetří nutnost ručně identifikovat zdroje vazeb použitím atributů na parametry akce. Pravidla funkce zdroje vazby se řídí následovně:

  • [FromBody] se odvozuje pro parametry komplexního typu. Výjimkou pro odvozené pravidlo [FromBody] je libovolný komplexní předdefinovaný typ se speciálním významem, jako je IFormCollection a CancellationToken. Kód pro odvození zdroje vazby ignoruje tyto speciální typy.
  • [FromForm] se odvozuje pro parametry typu IFormFile a IFormFileCollection. Neodvozuje se pro žádné jednoduché nebo uživatelsky definované typy.
  • [FromRoute] se odvozuje pro libovolný název parametru akce odpovídající parametru v šabloně trasy. Pokud parametru akce odpovídá více než jedna trasa, za [FromRoute] se považuje libovolná hodnota trasy.
  • [FromQuery] je odvozený pro všechny ostatní parametry akcí.

Poznámky k odvozování FromBody

[FromBody] se neodvozuje pro jednoduché typy, jako je string nebo int. Proto by se atribut [FromBody] měl pro jednoduché typy používat, pokud je tato funkce potřebná.

Pokud má akce více parametrů vázaných z textu požadavku, vyvolá se výjimka. Například všechny následující podpisy akčních metod způsobují výjimku:

  • [FromBody] se odvozuje v obou případech, protože jde o komplexní typy.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Atribut [FromBody] v jednom případě, odvozený v druhém, protože jde o komplexní typ.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atribut [FromBody] v obou případech.

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

Note

V ASP.NET Core 2.1 se parametry typu kolekce, jako jsou seznamy a pole, nesprávně odvozují jako [FromQuery]. Pro tyto parametry by měl být použit atribut [FromBody], pokud mají být vázány z textu požadavku. Toto chování je opraveno v ASP.NET Core verze 2.2 nebo novější, kde se parametry typu kolekce ve výchozím nastavení odvozují z textu.

Zákaz odvozených pravidel

Pokud chcete zakázat odvozování zdroje vazby, nastavte SuppressInferBindingSourcesForParameters na true. V souboru Startup.ConfigureServices přidejte následující kód:

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

Inferenční zpracování požadavků multipart/form-data

Atribut [ApiController] použije odvozené pravidlo pro parametry akce typu IFormFile a IFormFileCollection. Typ obsahu požadavku multipart/form-data je odvozený pro tyto typy. Pokud chcete zakázat výchozí chování, nastavte vlastnost SuppressConsumesConstraintForFormFileParameters na true v Startup.ConfigureServices:

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

Podrobnosti o problému se stavovými kódy chyb

Pokud je verze kompatibility 2.2 nebo novější, MVC transformuje výsledek chyby (výsledek se stavovým kódem 400 nebo vyšším) na výsledek s ProblemDetails. Typ ProblemDetails je založený na specifikaci RFC 7807 pro poskytování strojově čitelných podrobností o chybě v odpovědi HTTP. Zvažte použití následujícího kódu v akci kontroleru:

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

Metoda NotFound vytvoří stavový kód HTTP 404 s textem ProblemDetails. Například:

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

Vypnout odpověď ProblemDetails

Automatické generování ProblemDetails pro chybové stavové kódy je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavena na true. V souboru Startup.ConfigureServices přidejte následující kód:

Definování podporovaných typů obsahu požadavku s atributem [Consumes]

Akce ve výchozím nastavení podporuje všechny dostupné typy obsahu požadavku. Pokud je například aplikace nakonfigurována tak, aby podporovala vstupní formátovací moduly pro JSON i XML, akce podporuje více typů obsahu, včetně application/json a application/xml.

Atribut [Consumes] umožňuje akci omezit podporované typy obsahu požadavku. Atribut [Consumes] použijte u akce nebo kontroleru s určením jednoho nebo několika typů obsahu:

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

Akce CreateProduct v předchozím kódu určuje typ obsahu application/xml. Požadavky směrované na tuto akci musí uvést hlavičku Content-Type typu application/xml. Požadavky, které neurčují hlavičku Content-Type typu application/xml, vedou k odpovědi 415 Nepodporovaný typ média. Atribut [Consumes] také akci umožňuje ovlivnit její výběr na základě typu obsahu příchozího požadavku, a to použitím omezení typu. Představte si následující příklad:

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

V předchozím kódu je třída ConsumesController nakonfigurovaná tak, aby zpracovávala požadavky odeslané na adresu URL https://localhost:5001/api/Consumes. Obě akce kontroleru, PostJson i PostForm, zpracovávají požadavky POST se stejnou adresou URL. Bez atributu [Consumes] aplikujícího omezení typu se vyvolá výjimka nejednoznačné shody. Atribut [Consumes] se použije u obou akcí. Akce PostJson zpracovává požadavky odeslané s hlavičkou Content-Type typu application/json. Akce PostForm zpracovává požadavky odeslané s hlavičkou Content-Type typu application/x-www-form-urlencoded.

Dodatečné zdroje