Návratové typy akcí kontroleru ve webovém rozhraní API ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Zobrazení nebo stažení ukázkového kódu (postup stažení)

ASP.NET Core nabízí následující možnosti návratových typů akcí kontroleru webového rozhraní API:

Tento článek vysvětluje, kdy je nejvhodnější použít každý návratový typ.

Konkrétní typ

Nejzákladnější akce vrátí primitivní nebo složitý datový typ, například string nebo vlastní objekt. Představte si následující akci, která vrací kolekci vlastních Product objektů:

[HttpGet]
public Task<List<Product>> Get() =>
    _productContext.Products.OrderBy(p => p.Name).ToListAsync();

Bez známých podmínek pro ochranu před tím, aby vrácení určitého typu mohlo stačit. Předchozí akce nepřijímá žádné parametry, takže ověření omezení parametrů není potřeba.

Pokud je možné použít více návratových typů, je běžné kombinovat návratový ActionResult typ s primitivním nebo komplexním návratovým typem. K přizpůsobení tohoto typu akce je potřeba buď IActionResult , nebo ActionResult<T> . V tomto článku je k dispozici několik ukázek více návratových typů.

Vrátit IEnumerable<T> nebo IAsyncEnumerable<T>

Podívejte se na informace o vrácení IEnumerable<T> nebo IAsyncEnumerable<T> výkonu.

ASP.NET Core uloží do vyrovnávací paměti výsledek akcí, které se vrátí IEnumerable<T> před jejich zápisem do odpovědi. Zvažte deklaraci návratového typu podpisu akce, který IAsyncEnumerable<T> zaručuje asynchronní iteraci. V konečném důsledku je režim iterace založený na vrácených podkladových betonových typech a vybraný formátovací modul ovlivňuje způsob zpracování výsledku:

  • Když používáte System.Text.Json formátovací modul, MVC spoléhá na podporu přidanou System.Text.Json do streamu výsledku.
  • Při použití Newtonsoft.Json nebo s formátováním XML-based je výsledek uložen do vyrovnávací paměti.

Vezměte v úvahu následující akci, která vrací záznamy o produktech s cenami prodeje jako IEnumerable<Product>:

[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
    var products = _productContext.Products.OrderBy(p => p.Name).ToList();

    foreach (var product in products)
    {
        if (product.IsOnSale)
        {
            yield return product;
        }
    }
}

Ekvivalentem IAsyncEnumerable<Product> předchozí akce je:

[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
    var products = _productContext.Products.OrderBy(p => p.Name).AsAsyncEnumerable();

    await foreach (var product in products)
    {
        if (product.IsOnSale)
        {
            yield return product;
        }
    }
}

Typ IActionResult

Návratový IActionResult typ je vhodný, pokud je možné v akci provést více ActionResult návratových typů. Typy ActionResult představují různé stavové kódy HTTP. Každá ne abstraktní třída odvozená z ActionResult kvalifikuje jako platný návratový typ. Mezi běžné návratové typy v této kategorii patří BadRequestResult (400), NotFoundResult (404) a OkObjectResult (200). Alternativně lze metody pohodlí ve ControllerBase třídě použít k vrácení ActionResult typů z akce. Například return BadRequest(); je zkrácená forma return new BadRequestResult();.

Vzhledem k tomu, že v tomto typu akce existuje více návratových typů a cest, je nutné použít atribut liberalně [ProducesResponseType] . Tento atribut vytvoří popisnější podrobnosti odpovědi pro stránky nápovědy webového rozhraní API generované nástroji, jako je Swagger. [ProducesResponseType] označuje známé typy a stavové kódy HTTP, které mají být vráceny akcí.

Synchronní akce

Zvažte následující synchronní akci, ve které existují dva možné návratové typy:

[HttpGet("{id}")]
[ProducesResponseType<Product>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById_IActionResult(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? NotFound() : Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt reprezentovaný id v podkladovém úložišti dat neexistuje. Metoda NotFound pohodlí je vyvolána jako zkratka pro return new NotFoundResult();.
  • Stavový kód 200 se vrátí s objektem Product , pokud produkt existuje. Metoda Ok pohodlí je vyvolána jako zkratka pro return new OkObjectResult(product);.

Asynchronní akce

Vezměte v úvahu následující asynchronní akci, ve které existují dva možné návratové typy:

[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync_IActionResult(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    return CreatedAtAction(nameof(CreateAsync_IActionResult), new { id = product.Id }, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když popis produktu obsahuje "XYZ Widget". Metoda BadRequest pohodlí je vyvolána jako zkratka pro return new BadRequestResult();.

  • Stavový kód 201 je generován metodou CreatedAtAction pohodlí při vytvoření produktu. Následující kód je alternativou k volání CreatedAtAction:

    return new CreatedAtActionResult(nameof(CreateAsync), 
                                    "Products", 
                                    new { id = product.Id }, 
                                    product);
    

    V předchozí cestě Product kódu je objekt zadaný v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Následující model například označuje, že požadavky musí obsahovat vlastnosti Name a Description vlastnosti. Neúspěšné zadání Name a Description v požadavku způsobí selhání ověření modelu.

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; } = string.Empty;

    [Required]
    public string Description { get; set; } = string.Empty;

    public bool IsOnSale { get; set; }
}

[ApiController] Pokud se atribut použije, výsledkem chyb ověření modelu je stavový kód 400. Další informace naleznete v tématu Automatické odpovědi HTTP 400.

ActionResult vs IActionResult

Následující část porovnává s ActionResultIActionResult

Typ ActionResult<T>

ASP.NET Core obsahuje návratový typ ActionResult<T> pro akce kontroleru webového rozhraní API. Umožňuje vrácení typu odvozeného z ActionResult konkrétního typu nebo vrácení určitého typu. ActionResult<T> nabízí následující výhody oproti typu IActionResult:

  • [ProducesResponseType] Vlastnost atributu Type lze vyloučit. Například [ProducesResponseType(200, Type = typeof(Product))] je zjednodušena na [ProducesResponseType(200)]. Očekávaný návratový typ akce je odvozen z hodnoty T in ActionResult<T>.
  • Implicitní operátory přetypování podporují převod obou T a ActionResult na ActionResult<T>. T převede na ObjectResult, což znamená return new ObjectResult(T); , že je zjednodušen na return T;.

Jazyk C# nepodporuje implicitní operátory přetypování v rozhraních. V důsledku toho je převod rozhraní na konkrétní typ nezbytný k použití ActionResult<T>. Například použití IEnumerable v následujícím příkladu nefunguje:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
    _repository.GetProducts();

Jednou z možností, jak opravit předchozí kód, je vrátit _repository.GetProducts().ToList();.

Většina akcí má konkrétní návratový typ. Během provádění akce může dojít k neočekávaným podmínkám, v takovém případě se konkrétní typ nevrátí. Vstupní parametr akce může například selhat ověření modelu. V takovém případě je běžné místo konkrétního typu vrátit odpovídající ActionResult typ.

Synchronní akce

Zvažte synchronní akci, ve které existují dva možné návratové typy:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById_ActionResultOfT(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? NotFound() : product;
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje.

Asynchronní akce

Zvažte asynchronní akci, ve které existují dva možné návratové typy:

[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync_ActionResultOfT(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    return CreatedAtAction(nameof(CreateAsync_ActionResultOfT), new { id = product.Id }, product);
}

V předchozí akci:

  • Stavový kód 400 (BadRequest) vrací modul runtime ASP.NET Core, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou CreatedAtAction při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Typ HttpResults

Kromě předdefinovaných typů výsledků MVC (IActionResult a ActionResult<T>) ASP.NET Core obsahuje typy HttpResults , které je možné použít v minimálních rozhraních API i webovém rozhraní API.

Jiné než typy výsledků specifické pro MVC:HttpResults

  • Jsou implementace výsledků, která je zpracována voláním IResult.ExecuteAsync.

  • Nevyužít nakonfigurované formátovací moduly. Využití nakonfigurovaných formátovacích nástrojů znamená:

    • Některé funkce, jako Content negotiation jsou, nejsou dostupné.
    • Content-Type Produkce je určena implementacíHttpResults.

To HttpResults může být užitečné při sdílení kódu mezi minimálními rozhraními API a webovým rozhraním API.

Typ IResult

Obor Microsoft.AspNetCore.Http.HttpResults názvů obsahuje třídy, které implementují IResult rozhraní. Rozhraní IResult definuje kontrakt, který představuje výsledek koncového bodu HTTP. Static Results třída slouží k vytvoření různých IResult objektů, které představují různé typy odpovědí.

Tabulka předdefinovaných výsledků zobrazuje běžné pomocné rutiny výsledků.

Uvažujte následující kód:

[HttpGet("{id}")]
[ProducesResponseType<Product>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IResult GetById(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? Results.NotFound() : Results.Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje, vygenerovaný results.ok <T>().

Uvažujte následující kód:

[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType<Product>(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IResult> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return Results.BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    var location = Url.Action(nameof(CreateAsync), new { id = product.Id }) ?? $"/{product.Id}";
    return Results.Created(location, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou Results.Create při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Výsledky<TResult1, typ TResultN>

Static TypedResults třída vrací konkrétní IResult implementaci, která umožňuje použít IResult jako návratový typ. Použití konkrétní IResult implementace nabízí následující výhody oproti typu IResult:

  • [ProducesResponseType] Všechny atributy lze vyloučit, protože HttpResult implementace přispívá automaticky k metadatům koncového bodu.

Pokud je potřeba více IResult návratových typů, je vrácení Results<TResult1, TResultN> upřednostňované před vrácením IResult. Results<TResult1, TResultN> Vrácení se upřednostňuje, protože obecné typy sjednocení automaticky uchovávají metadata koncového bodu.

Typy Results<TResult1, TResultN> sjednocení implementují implicitní operátory přetypování, aby kompilátor mohl automaticky převést typy zadané v obecných argumentech na instanci sjednocovacího typu. To má přidanou výhodu poskytování kontroly času kompilace, že obslužná rutina trasy skutečně vrací pouze výsledky, které deklaruje. Pokus o vrácení typu, který není deklarován jako jeden z obecných argumentů, aby výsledkem Results<> byla chyba kompilace.

Uvažujte následující kód:

[HttpGet("{id}")]
public Results<NotFound, Ok<Product>> GetById(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? TypedResults.NotFound() : TypedResults.Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje, vygenerovaný TypedResults.Ok <T>.
[HttpPost]
public async Task<Results<BadRequest, Created<Product>>> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return TypedResults.BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    var location = Url.Action(nameof(CreateAsync), new { id = product.Id }) ?? $"/{product.Id}";
    return TypedResults.Created(location, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou TypedResults.Created při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Další materiály

Zobrazení nebo stažení ukázkového kódu (postup stažení)

ASP.NET Core nabízí následující možnosti návratových typů akcí kontroleru webového rozhraní API:

Tento článek vysvětluje, kdy je nejvhodnější použít každý návratový typ.

Konkrétní typ

Nejzákladnější akce vrátí primitivní nebo složitý datový typ, například string nebo vlastní objekt. Představte si následující akci, která vrací kolekci vlastních Product objektů:

[HttpGet]
public Task<List<Product>> Get() =>
    _productContext.Products.OrderBy(p => p.Name).ToListAsync();

Bez známých podmínek pro ochranu před tím, aby vrácení určitého typu mohlo stačit. Předchozí akce nepřijímá žádné parametry, takže ověření omezení parametrů není potřeba.

Pokud je možné použít více návratových typů, je běžné kombinovat návratový ActionResult typ s primitivním nebo komplexním návratovým typem. K přizpůsobení tohoto typu akce je potřeba buď IActionResult , nebo ActionResult<T> . V tomto článku je k dispozici několik ukázek více návratových typů.

Vrátit IEnumerable<T> nebo IAsyncEnumerable<T>

Podívejte se na informace o vrácení IEnumerable<T> nebo IAsyncEnumerable<T> výkonu.

ASP.NET Core uloží do vyrovnávací paměti výsledek akcí, které se vrátí IEnumerable<T> před jejich zápisem do odpovědi. Zvažte deklaraci návratového typu podpisu akce, který IAsyncEnumerable<T> zaručuje asynchronní iteraci. V konečném důsledku je režim iterace založený na vrácených podkladových betonových typech a vybraný formátovací modul ovlivňuje způsob zpracování výsledku:

  • Když používáte System.Text.Json formátovací modul, MVC spoléhá na podporu přidanou System.Text.Json do streamu výsledku.
  • Při použití Newtonsoft.Json nebo s formátováním XML-based je výsledek uložen do vyrovnávací paměti.

Vezměte v úvahu následující akci, která vrací záznamy o produktech s cenami prodeje jako IEnumerable<Product>:

[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
    var products = _productContext.Products.OrderBy(p => p.Name).ToList();

    foreach (var product in products)
    {
        if (product.IsOnSale)
        {
            yield return product;
        }
    }
}

Ekvivalentem IAsyncEnumerable<Product> předchozí akce je:

[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
    var products = _productContext.Products.OrderBy(p => p.Name).AsAsyncEnumerable();

    await foreach (var product in products)
    {
        if (product.IsOnSale)
        {
            yield return product;
        }
    }
}

Typ IActionResult

Návratový IActionResult typ je vhodný, pokud je možné v akci provést více ActionResult návratových typů. Typy ActionResult představují různé stavové kódy HTTP. Každá ne abstraktní třída odvozená z ActionResult kvalifikuje jako platný návratový typ. Mezi běžné návratové typy v této kategorii patří BadRequestResult (400), NotFoundResult (404) a OkObjectResult (200). Alternativně lze metody pohodlí ve ControllerBase třídě použít k vrácení ActionResult typů z akce. Například return BadRequest(); je zkrácená forma return new BadRequestResult();.

Vzhledem k tomu, že v tomto typu akce existuje více návratových typů a cest, je nutné použít atribut liberalně [ProducesResponseType] . Tento atribut vytvoří popisnější podrobnosti odpovědi pro stránky nápovědy webového rozhraní API generované nástroji, jako je Swagger. [ProducesResponseType] označuje známé typy a stavové kódy HTTP, které mají být vráceny akcí.

Synchronní akce

Zvažte následující synchronní akci, ve které existují dva možné návratové typy:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById_IActionResult(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? NotFound() : Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt reprezentovaný id v podkladovém úložišti dat neexistuje. Metoda NotFound pohodlí je vyvolána jako zkratka pro return new NotFoundResult();.
  • Stavový kód 200 se vrátí s objektem Product , pokud produkt existuje. Metoda Ok pohodlí je vyvolána jako zkratka pro return new OkObjectResult(product);.

Asynchronní akce

Vezměte v úvahu následující asynchronní akci, ve které existují dva možné návratové typy:

[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync_IActionResult(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    return CreatedAtAction(nameof(GetById_IActionResult), new { id = product.Id }, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když popis produktu obsahuje "XYZ Widget". Metoda BadRequest pohodlí je vyvolána jako zkratka pro return new BadRequestResult();.

  • Stavový kód 201 je generován metodou CreatedAtAction pohodlí při vytvoření produktu. Následující kód je alternativou k volání CreatedAtAction:

    return new CreatedAtActionResult(nameof(GetById), 
                                    "Products", 
                                    new { id = product.Id }, 
                                    product);
    

    V předchozí cestě Product kódu je objekt zadaný v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Následující model například označuje, že požadavky musí obsahovat vlastnosti Name a Description vlastnosti. Neúspěšné zadání Name a Description v požadavku způsobí selhání ověření modelu.

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; } = string.Empty;

    [Required]
    public string Description { get; set; } = string.Empty;

    public bool IsOnSale { get; set; }
}

[ApiController] Pokud se atribut použije, výsledkem chyb ověření modelu je stavový kód 400. Další informace naleznete v tématu Automatické odpovědi HTTP 400.

ActionResult vs IActionResult

Následující část porovnává s ActionResultIActionResult

Typ ActionResult<T>

ASP.NET Core obsahuje návratový typ ActionResult<T> pro akce kontroleru webového rozhraní API. Umožňuje vrácení typu odvozeného z ActionResult konkrétního typu nebo vrácení určitého typu. ActionResult<T> nabízí následující výhody oproti typu IActionResult:

  • [ProducesResponseType] Vlastnost atributu Type lze vyloučit. Například [ProducesResponseType(200, Type = typeof(Product))] je zjednodušena na [ProducesResponseType(200)]. Očekávaný návratový typ akce je odvozen z hodnoty T in ActionResult<T>.
  • Implicitní operátory přetypování podporují převod obou T a ActionResult na ActionResult<T>. T převede na ObjectResult, což znamená return new ObjectResult(T); , že je zjednodušen na return T;.

Jazyk C# nepodporuje implicitní operátory přetypování v rozhraních. V důsledku toho je převod rozhraní na konkrétní typ nezbytný k použití ActionResult<T>. Například použití IEnumerable v následujícím příkladu nefunguje:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
    _repository.GetProducts();

Jednou z možností, jak opravit předchozí kód, je vrátit _repository.GetProducts().ToList();.

Většina akcí má konkrétní návratový typ. Během provádění akce může dojít k neočekávaným podmínkám, v takovém případě se konkrétní typ nevrátí. Vstupní parametr akce může například selhat ověření modelu. V takovém případě je běžné místo konkrétního typu vrátit odpovídající ActionResult typ.

Synchronní akce

Zvažte synchronní akci, ve které existují dva možné návratové typy:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById_ActionResultOfT(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? NotFound() : product;
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje.

Asynchronní akce

Zvažte asynchronní akci, ve které existují dva možné návratové typy:

[HttpPost()]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync_ActionResultOfT(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    return CreatedAtAction(nameof(GetById_ActionResultOfT), new { id = product.Id }, product);
}

V předchozí akci:

  • Stavový kód 400 (BadRequest) vrací modul runtime ASP.NET Core, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou CreatedAtAction při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Typ HttpResults

Kromě předdefinovaných typů výsledků MVC (IActionResult a ActionResult<T>) ASP.NET Core obsahuje typy HttpResults , které je možné použít v minimálních rozhraních API i webovém rozhraní API.

Jiné než typy výsledků specifické pro MVC:HttpResults

  • Jsou implementace výsledků, která je zpracována voláním IResult.ExecuteAsync.

  • Nevyužít nakonfigurované formátovací moduly. Využití nakonfigurovaných formátovacích nástrojů znamená:

    • Některé funkce, jako Content negotiation jsou, nejsou dostupné.
    • Content-Type Produkce je určena implementacíHttpResults.

To HttpResults může být užitečné při sdílení kódu mezi minimálními rozhraními API a webovým rozhraním API.

Typ IResult

Obor Microsoft.AspNetCore.Http.HttpResults názvů obsahuje třídy, které implementují IResult rozhraní. Rozhraní IResult definuje kontrakt, který představuje výsledek koncového bodu HTTP. Static Results třída slouží k vytvoření různých IResult objektů, které představují různé typy odpovědí.

Tabulka předdefinovaných výsledků zobrazuje běžné pomocné rutiny výsledků.

Uvažujte následující kód:

[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IResult GetById(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? Results.NotFound() : Results.Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje, vygenerovaný results.ok <T>().

Uvažujte následující kód:

[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(typeof(Product), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IResult> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return Results.BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}";
    return Results.Created(location, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou Results.Create při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Výsledky<TResult1, typ TResultN>

Static TypedResults třída vrací konkrétní IResult implementaci, která umožňuje použít IResult jako návratový typ. Použití konkrétní IResult implementace nabízí následující výhody oproti typu IResult:

  • [ProducesResponseType] Všechny atributy lze vyloučit, protože HttpResult implementace přispívá automaticky k metadatům koncového bodu.

Pokud je potřeba více IResult návratových typů, je vrácení Results<TResult1, TResultN> upřednostňované před vrácením IResult. Results<TResult1, TResultN> Vrácení se upřednostňuje, protože obecné typy sjednocení automaticky uchovávají metadata koncového bodu.

Typy Results<TResult1, TResultN> sjednocení implementují implicitní operátory přetypování, aby kompilátor mohl automaticky převést typy zadané v obecných argumentech na instanci sjednocovacího typu. To má přidanou výhodu poskytování kontroly času kompilace, že obslužná rutina trasy skutečně vrací pouze výsledky, které deklaruje. Pokus o vrácení typu, který není deklarován jako jeden z obecných argumentů, aby výsledkem Results<> byla chyba kompilace.

Uvažujte následující kód:

[HttpGet("{id}")]
public Results<NotFound, Ok<Product>> GetById(int id)
{
    var product = _productContext.Products.Find(id);
    return product == null ? TypedResults.NotFound() : TypedResults.Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje, vygenerovaný TypedResults.Ok <T>.
[HttpPost]
public async Task<Results<BadRequest, Created<Product>>> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return TypedResults.BadRequest();
    }

    _productContext.Products.Add(product);
    await _productContext.SaveChangesAsync();

    var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}";
    return TypedResults.Created(location, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou TypedResults.Create při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Další materiály

Zobrazení nebo stažení ukázkového kódu (postup stažení)

ASP.NET Core nabízí následující možnosti návratových typů akcí kontroleru webového rozhraní API:

Tento dokument vysvětluje, kdy je nejvhodnější použít každý návratový typ.

Konkrétní typ

Nejjednodušší akce vrátí primitivní nebo komplexní datový typ (například string vlastní typ objektu). Představte si následující akci, která vrací kolekci vlastních Product objektů:

[HttpGet]
public List<Product> Get() =>
    _repository.GetProducts();

Bez známých podmínek pro ochranu před provedením akce může být vrácení konkrétního typu dostačující. Předchozí akce nepřijímá žádné parametry, takže ověření omezení parametrů není potřeba.

Pokud je možné použít více návratových typů, je běžné kombinovat návratový ActionResult typ s primitivním nebo komplexním návratovým typem. K přizpůsobení tohoto typu akce je potřeba buď IActionResult , nebo ActionResult<T> . V tomto dokumentu je k dispozici několik ukázek více návratových typů.

Vrátit IEnumerable<T> nebo IAsyncEnumerable<T>

ASP.NET Core uloží do vyrovnávací paměti výsledek akcí, které se vrátí IEnumerable<T> před jejich zápisem do odpovědi. Zvažte deklaraci návratového typu podpisu akce, který IAsyncEnumerable<T> zaručuje asynchronní iteraci. V konečném důsledku je režim iterace založen na vráceného podkladového konkrétního typu. MVC automaticky do vyrovnávací paměti jakéhokoli konkrétního typu, který implementuje IAsyncEnumerable<T>.

Vezměte v úvahu následující akci, která vrací záznamy o produktech s cenami prodeje jako IEnumerable<Product>:

[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
    var products = _repository.GetProducts();

    foreach (var product in products)
    {
        if (product.IsOnSale)
        {
            yield return product;
        }
    }
}

Ekvivalentem IAsyncEnumerable<Product> předchozí akce je:

[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
    var products = _repository.GetProductsAsync();

    await foreach (var product in products)
    {
        if (product.IsOnSale)
        {
            yield return product;
        }
    }
}

Typ IActionResult

Návratový IActionResult typ je vhodný, pokud je možné v akci provést více ActionResult návratových typů. Typy ActionResult představují různé stavové kódy HTTP. Každá ne abstraktní třída odvozená z ActionResult kvalifikuje jako platný návratový typ. Mezi běžné návratové typy v této kategorii patří BadRequestResult (400), NotFoundResult (404) a OkObjectResult (200). Alternativně lze metody pohodlí ve ControllerBase třídě použít k vrácení ActionResult typů z akce. Například return BadRequest(); je zkrácená forma return new BadRequestResult();.

Vzhledem k tomu, že v tomto typu akce existuje více návratových typů a cest, je nutné použít atribut liberalně [ProducesResponseType] . Tento atribut vytvoří popisnější podrobnosti odpovědi pro stránky nápovědy webového rozhraní API generované nástroji, jako je Swagger. [ProducesResponseType] označuje známé typy a stavové kódy HTTP, které mají být vráceny akcí.

Synchronní akce

Zvažte následující synchronní akci, ve které existují dva možné návratové typy:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return Ok(product);
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt reprezentovaný id v podkladovém úložišti dat neexistuje. Metoda NotFound pohodlí je vyvolána jako zkratka pro return new NotFoundResult();.
  • Stavový kód 200 se vrátí s objektem Product , pokud produkt existuje. Metoda Ok pohodlí je vyvolána jako zkratka pro return new OkObjectResult(product);.

Asynchronní akce

Vezměte v úvahu následující asynchronní akci, ve které existují dva možné návratové typy:

[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

V předchozí akci:

  • Stavový kód 400 se vrátí, když popis produktu obsahuje "XYZ Widget". Metoda BadRequest pohodlí je vyvolána jako zkratka pro return new BadRequestResult();.
  • Stavový kód 201 je generován metodou CreatedAtAction pohodlí při vytvoření produktu. Alternativou k volání CreatedAtAction je return new CreatedAtActionResult(nameof(GetById), "Products", new { id = product.Id }, product);. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Následující model například označuje, že požadavky musí obsahovat vlastnosti Name a Description vlastnosti. Neúspěšné zadání Name a Description v požadavku způsobí selhání ověření modelu.

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }

    public bool IsOnSale { get; set; }
}

[ApiController] Pokud se atribut použije, výsledkem chyb ověření modelu je stavový kód 400. Další informace naleznete v tématu Automatické odpovědi HTTP 400.

ActionResult vs IActionResult

Následující část porovnává s ActionResultIActionResult

Typ ActionResult<T>

ASP.NET Core obsahuje návratový typ ActionResult<T> pro akce kontroleru webového rozhraní API. Umožňuje vrátit typ odvozený nebo ActionResult vrátit určitý typ. ActionResult<T> nabízí následující výhody oproti typu IActionResult:

  • [ProducesResponseType] Vlastnost atributu Type lze vyloučit. Například [ProducesResponseType(200, Type = typeof(Product))] je zjednodušena na [ProducesResponseType(200)]. Očekávaný návratový typ akce se místo toho odvodí z in TActionResult<T>.
  • Implicitní operátory přetypování podporují převod obou T a ActionResult na ActionResult<T>. T převede na ObjectResult, což znamená return new ObjectResult(T); , že je zjednodušen na return T;.

Jazyk C# nepodporuje implicitní operátory přetypování v rozhraních. V důsledku toho je převod rozhraní na konkrétní typ nezbytný k použití ActionResult<T>. Například použití IEnumerable v následujícím příkladu nefunguje:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
    _repository.GetProducts();

Jednou z možností, jak opravit předchozí kód, je vrátit _repository.GetProducts().ToList();.

Většina akcí má konkrétní návratový typ. Během provádění akce může dojít k neočekávaným podmínkám, v takovém případě se konkrétní typ nevrátí. Vstupní parametr akce může například selhat ověření modelu. V takovém případě je běžné místo konkrétního typu vrátit odpovídající ActionResult typ.

Synchronní akce

Zvažte synchronní akci, ve které existují dva možné návratové typy:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return product;
}

V předchozí akci:

  • Stavový kód 404 se vrátí, když produkt v databázi neexistuje.
  • Stavový kód 200 se vrátí s odpovídajícím Product objektem, pokud produkt existuje.

Asynchronní akce

Zvažte asynchronní akci, ve které existují dva možné návratové typy:

[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

V předchozí akci:

  • Stavový kód 400 (BadRequest) vrací modul runtime ASP.NET Core, když:
    • Atribut [ApiController] byl použit a ověření modelu selže.
    • Popis produktu obsahuje "XYZ Widget".
  • Stavový kód 201 je generován metodou CreatedAtAction při vytvoření produktu. V této cestě Product kódu je objekt poskytován v textu odpovědi. Location Je k dispozici hlavička odpovědi obsahující nově vytvořenou adresu URL produktu.

Další materiály