Sdílet prostřednictvím


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

ASP.NET Core podporuje vytváření webových rozhraní API pomocí kontrolerů nebo minimálních rozhraní API. Kontrolery ve webovém rozhraní API jsou třídy, které odvozují z ControllerBase. Kontrolery se aktivují a vyřaďte na každý požadavek.

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.

Třída ControllerBase

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.

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

Atributy

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.

Atribut 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] zajišťuje směrování atributů jako požadavek. Pří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ěď.

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

Zákaz 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:

Atribut Zdroj vazby
[FromBody] Text požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr řetězce dotazu požadavku
[FromRoute] Směrování dat z aktuálního požadavku
[FromServices] Služba požadavku vložená jako parametr akce
[AsParameters] Parametry metody

Upozorňující

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

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. Odvozená pravidla zdroje vazby se chovají takto:

  • [FromServices] se odvozuje pro parametry komplexního typu, které jsou registrované v kontejneru injektáže závislostí.
  • [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 odvození zdroje vazby tyto speciální typy ignoruje.
  • [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] se odvozuje pro všechny ostatní parametry.

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

Poznámky k odvozování FromServices

Vazby parametrů sváže parametry prostřednictvím injektáže závislostí, když je typ nakonfigurován jako služba. 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);
}

Vevýjimečných 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ů 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. Příklad:

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

Zákaz odpovědi ProblemDetails

Automatické vytvoření ProblemDetails pro stavové kódy kódů chyb je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavená 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átovací moduly 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í výjimky 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.

Další materiály

ASP.NET Core podporuje vytváření webových rozhraní API pomocí kontrolerů nebo 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.

Třída ControllerBase

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.

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

Atributy

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.

Atribut 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] zajišťuje směrování atributů jako požadavek. Pří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ěď.

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

Zákaz 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:

Atribut Zdroj vazby
[FromBody] Text požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr řetězce dotazu požadavku
[FromRoute] Směrování dat z aktuálního požadavku
[FromServices] Služba požadavku vložená jako parametr akce

Upozorňující

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

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. Odvozená pravidla zdroje vazby se chovají takto:

  • [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 odvození zdroje vazby tyto speciální typy ignoruje.
  • [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] se odvozuje pro všechny ostatní parametry.

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

Odvozová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. Příklad:

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

Zákaz odpovědi ProblemDetails

Automatické vytvoření ProblemDetails pro stavové kódy kódů chyb je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavená 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 nakonfigurovaná tak, aby podporovala vstupní formátovací moduly 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í výjimky 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.

Další materiály

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í).

Třída ControllerBase

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.

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

Atributy

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.

Atribut 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í na deklaraci oboru názvů u třídy Startup:

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

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

Atribut [ApiController] zajišťuje směrování atributů jako požadavek. Pří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í 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í v Startup.ConfigureServices. 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:

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

Zákaz 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.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:

Atribut Zdroj vazby
[FromBody] Text požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr řetězce dotazu požadavku
[FromRoute] Směrování dat z aktuálního požadavku
[FromServices] Služba požadavku vložená jako parametr akce

Upozorňující

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

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. Odvozená pravidla zdroje vazby se chovají takto:

  • [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 odvození zdroje vazby tyto speciální typy ignoruje.
  • [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] se odvozuje pro všechny ostatní parametry.

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 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. 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ů 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. Příklad:

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

Zákaz odpovědi ProblemDetails

Automatické vytvoření ProblemDetails pro stavové kódy kódů chyb je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavená 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átovací moduly 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í výjimky 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.

Další materiály

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

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

Atributy

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:

Atribut 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í na deklaraci oboru názvů u třídy Startup:

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

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

Atribut [ApiController] zajišťuje směrování atributů jako požadavek. Pří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ěď.

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

Projděte si téma Postup protokolování automatických odpovědí 400 u chyb ověření modelu (dotnet/AspNetCore.Docs#12157).

Zákaz 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:

Atribut Zdroj vazby
[FromBody] Text požadavku
[FromForm] Formulářová data v textu požadavku
[FromHeader] Hlavička požadavku
[FromQuery] Parametr řetězce dotazu požadavku
[FromRoute] Směrování dat z aktuálního požadavku
[FromServices] Služba požadavku vložená jako parametr akce

Upozorňující

Nepoužívejte [FromRoute], pokud hodnoty mohou obsahovat %2f (to znamená /). %2f se nepřevedou na /. Pokud hodnota může obsahovat %2f, použijte [FromQuery]. 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. Odvozená pravidla zdroje vazby se chovají takto:

  • [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 odvození zdroje vazby tyto speciální typy ignoruje.
  • [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] se odvozuje pro všechny ostatní parametry.

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

Poznámka:

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

Odvozová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. Příklad:

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

Zákaz odpovědi ProblemDetails

Automatické vytvoření ProblemDetails pro stavové kódy kódů chyb je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavená 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 nakonfigurovaná tak, aby podporovala vstupní formátovací moduly 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í výjimky 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.

Další materiály