Rückgabetypen für Controlleraktionen in der ASP.NET Core-Web-APIController action return types in ASP.NET Core web API

Von Scott AddieBy Scott Addie

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

In ASP.NET Core haben Sie die folgenden Optionen für Rückgabetypen für Web-API-Controlleraktionen:ASP.NET Core offers the following options for web API controller action return types:

In diesem Artikel wird die Verwendung der einzelnen Rückgabetypen erklärt.This document explains when it's most appropriate to use each return type.

Spezifischer TypSpecific type

Die einfachste Aktion gibt einen primitiven oder komplexen Datentyp zurück (z.B. string oder einen benutzerdefinierten Objekttyp).The simplest action returns a primitive or complex data type (for example, string or a custom object type). Die folgende Aktion gibt eine Auflistung benutzerdefinierter Product-Objekte zurück:Consider the following action, which returns a collection of custom Product objects:

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

Ohne bekannte Bedingungen, gegen die während der Ausführung einer Aktion Schutzmaßnahmen ergriffen werden müssen, reicht die Rückgabe eines spezifischen Typs möglicherweise aus.Without known conditions to safeguard against during action execution, returning a specific type could suffice. Die vorherige Aktion akzeptiert keine Parameter, weshalb eine Validierung von Parametereinschränkungen nicht erforderlich ist.The preceding action accepts no parameters, so parameter constraints validation isn't needed.

Wenn mehrere Rückgabe Typen möglich sind, wird häufig ein ActionResult Rückgabetyp mit dem primitiven oder komplexen Rückgabetyp gemischt.When multiple return types are possible, it's common to mix an ActionResult return type with the primitive or complex return type. Für diese Art von Aktion sind entweder ' IAction result ' oder ' <T> Action result ' erforderlich.Either IActionResult or ActionResult<T> are necessary to accommodate this type of action. In diesem Dokument werden mehrere Beispiele mehrerer Rückgabe Typen bereitgestellt.Several samples of multiple return types are provided in this document.

IEnumerable <T> oder iasyncenumerable zurückgeben<T>Return IEnumerable<T> or IAsyncEnumerable<T>

Wenn eine Aktion in ASP.NET Core 2.2 und früher IEnumerable<T> zurückgibt, führt dies zu einer synchronen Sammlungsiteration durch das Serialisierungsprogramm.In ASP.NET Core 2.2 and earlier, returning IEnumerable<T> from an action results in synchronous collection iteration by the serializer. Das Ergebnis sind die Blockierung von Aufrufen und die potenzielle Außerkraftsetzung des Threadpools.The result is the blocking of calls and a potential for thread pool starvation. Stellen Sie sich zur Veranschaulichung vor, dass der Entity Framework-Core (EF) für die Datenzugriffsanforderungen der Web-API verwendet wird.To illustrate, imagine that Entity Framework (EF) Core is being used for the web API's data access needs. Der Rückgabetyp der folgenden Aktion wird während der Serialisierung synchron aufgezählt:The following action's return type is synchronously enumerated during serialization:

public IEnumerable<Product> GetOnSaleProducts() =>
    _context.Products.Where(p => p.IsOnSale);

Um synchrone Enumeration und blockierendes Warten auf die Datenbank in ASP.NET Core 2.2 und früher zu vermeiden, rufen Sie ToListAsync auf:To avoid synchronous enumeration and blocking waits on the database in ASP.NET Core 2.2 and earlier, invoke ToListAsync:

public async Task<IEnumerable<Product>> GetOnSaleProducts() =>
    await _context.Products.Where(p => p.IsOnSale).ToListAsync();

In ASP.NET Core 3.0 und höher gilt Folgendes, wenn eine Aktion IAsyncEnumerable<T> zurückgibt:In ASP.NET Core 3.0 and later, returning IAsyncEnumerable<T> from an action:

  • Es kommt nicht mehr zu synchroner Iteration.No longer results in synchronous iteration.
  • Gleiche Effizienz wie bei Rückgabe von IEnumerable<T>.Becomes as efficient as returning IEnumerable<T>.

ASP.NET Core 3.0 und höher puffert das Ergebnis der folgenden Aktion, bevor es dem Serialisierungsprogramm bereitgestellt wird:ASP.NET Core 3.0 and later buffers the result of the following action before providing it to the serializer:

public IEnumerable<Product> GetOnSaleProducts() =>
    _context.Products.Where(p => p.IsOnSale);

Sie sollten den Rückgabetyp der Signatur der Aktion als IAsyncEnumerable<T> deklarieren, um die asynchrone Iteration sicherzustellen.Consider declaring the action signature's return type as IAsyncEnumerable<T> to guarantee the asynchronous iteration. Letztendlich basiert der Iterationsmodus auf dem zugrunde liegenden konkreten Typ, der zurückgegeben wird.Ultimately, the iteration mode is based on the underlying concrete type being returned. MVC puffert automatisch jeden konkreten Typ, der IAsyncEnumerable<T> implementiert.MVC automatically buffers any concrete type that implements IAsyncEnumerable<T>.

Sehen Sie sich die folgende Aktion an, die den Verkaufspreis enthaltende Produktdatensätze als IEnumerable<Product> zurückgibt:Consider the following action, which returns sale-priced product records as IEnumerable<Product>:

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

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

Die IAsyncEnumerable<Product>-Entsprechung der vorherigen Aktion lautet wie folgt:The IAsyncEnumerable<Product> equivalent of the preceding action is:

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

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

Beide vorangehenden Aktionen führen ab ASP.NET Core 3.0 nicht mehr zu Blockierungen.Both of the preceding actions are non-blocking as of ASP.NET Core 3.0.

IActionResult-TypIActionResult type

Der Rückgabetyp IActionResult eignet sich in Fällen, in denen mehrere ActionResult-Rückgabetypen in einer Aktion möglich sind.The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. Die ActionResult-Typen stellen verschiedene HTTP-Statuscodes dar.The ActionResult types represent various HTTP status codes. Alle nicht abstrakten Klassen, die von ActionResult abgeleitet werden, qualifizieren sich als gültiger Rückgabetyp.Any non-abstract class deriving from ActionResult qualifies as a valid return type. Einige allgemeine Rückgabetypen in dieser Kategorie sind BadRequestResult (400), NotFoundResult (404) und OkObjectResult (200).Some common return types in this category are BadRequestResult (400), NotFoundResult (404), and OkObjectResult (200). Alternativ können Hilfsmethoden in der ControllerBase-Klasse verwendet werden, um ActionResult-Typen aus einer Aktion zurückzugeben.Alternatively, convenience methods in the ControllerBase class can be used to return ActionResult types from an action. return BadRequest(); ist beispielsweise eine Kurzform von return new BadRequestResult();.For example, return BadRequest(); is a shorthand form of return new BadRequestResult();.

Da in dieser Art von Aktion mehrere Rückgabe Typen und Pfade vorhanden sind, ist die liberale Verwendung des- [ProducesResponseType] Attributs erforderlich.Because there are multiple return types and paths in this type of action, liberal use of the [ProducesResponseType] attribute is necessary. Dieses Attribut erzeugt aussagekräftigere Antwortdetails für Web-API-Hilfeseiten, die mit Tools wie Swagger erstellt wurden.This attribute produces more descriptive response details for web API help pages generated by tools like Swagger. [ProducesResponseType] gibt die bekannten Typen und HTTP-Statuscodes an, die von der Aktion zurückgegeben werden sollen.[ProducesResponseType] indicates the known types and HTTP status codes to be returned by the action.

Synchrone AktionSynchronous action

Bei der folgenden synchronen Aktion gibt es zwei mögliche Rückgabetypen:Consider the following synchronous action in which there are two possible return types:

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

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

    return Ok(product);
}

In der vorhergehenden Aktion geschieht Folgendes:In the preceding action:

  • Ein 404-Statuscode wird zurückgegeben, wenn das durch id dargestellte Produkt im zugrunde liegenden Datenspeicher nicht vorhanden ist.A 404 status code is returned when the product represented by id doesn't exist in the underlying data store. Die NotFound-Hilfsmethode wird als Kurzform für return new NotFoundResult(); aufgerufen.The NotFound convenience method is invoked as shorthand for return new NotFoundResult();.
  • Ein 200-Statuscode wird mit dem Product-Objekt zurückgegeben, wenn das Produkt vorhanden ist.A 200 status code is returned with the Product object when the product does exist. Die Ok-Hilfsmethode wird als Kurzform für return new OkObjectResult(product); aufgerufen.The Ok convenience method is invoked as shorthand for return new OkObjectResult(product);.

Asynchrone AktionAsynchronous action

Bei der folgenden asynchronen Aktion gibt es zwei mögliche Rückgabetypen:Consider the following asynchronous action in which there are two possible return types:

[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);
}
[HttpPost]
[Consumes("application/json")]
[ProducesResponseType(typeof(Product), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync([FromBody] Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

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

In der vorhergehenden Aktion geschieht Folgendes:In the preceding action:

  • Ein 400-Statuscode wird zurückgegeben, wenn die Produktbeschreibung „XYZ-Widget“ enthält.A 400 status code is returned when the product description contains "XYZ Widget". Die BadRequest-Hilfsmethode wird als Kurzform für return new BadRequestResult(); aufgerufen.The BadRequest convenience method is invoked as shorthand for return new BadRequestResult();.
  • Ein 201-Statuscode wird von der Hilfsmethode CreatedAtAction generiert, wenn ein Produkt erstellt wird.A 201 status code is generated by the CreatedAtAction convenience method when a product is created. Eine Alternative zum Aufrufen von CreatedAtAction ist return new CreatedAtActionResult(nameof(GetById), "Products", new { id = product.Id }, product);.An alternative to calling CreatedAtAction is return new CreatedAtActionResult(nameof(GetById), "Products", new { id = product.Id }, product);. In diesem Codepfad wird das Product-Objekt im Antworttext bereitgestellt.In this code path, the Product object is provided in the response body. Ein Location-Antwortheader, der die neu erstellte Produkt-URL enthält, wird bereitgestellt.A Location response header containing the newly created product's URL is provided.

Das folgende Modell gibt beispielsweise an, dass Anforderungen die Name- und Description-Eigenschaften einbinden müssen.For example, the following model indicates that requests must include the Name and Description properties. Wenn Name und Description in der Anforderung nicht bereitgestellt werden, tritt bei der Modellvalidierung ein Fehler auf.Failure to provide Name and Description in the request causes model validation to fail.

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

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

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

Wenn das- [ApiController] Attribut in ASP.net Core 2,1 oder höher angewendet wird, führen Modell Validierungs Fehler zu einem 400-Statuscode.If the [ApiController] attribute in ASP.NET Core 2.1 or later is applied, model validation errors result in a 400 status code. Weitere Informationen finden Sie unter Automatische HTTP 400-Antworten.For more information, see Automatic HTTP 400 responses.

Aktions <T> ErgebnistypActionResult<T> type

In ASP.net Core 2,1 wurde der Rückgabetyp " aktionresult <T> " für Web-API-Controller AktionenASP.NET Core 2.1 introduced the ActionResult<T> return type for web API controller actions. Damit wird die Rückgabe eines von ActionResult abgeleiteten Typs oder eines spezifischen Typs ermöglicht.It enables you to return a type deriving from ActionResult or return a specific type. ActionResult<T> besitzt gegenüber dem IActionResult-Typ die folgenden Vorteile:ActionResult<T> offers the following benefits over the IActionResult type:

  • Die [ProducesResponseType] -Eigenschaft des Attributs Type kann ausgeschlossen werden.The [ProducesResponseType] attribute's Type property can be excluded. [ProducesResponseType(200, Type = typeof(Product))] wird beispielsweise zu [ProducesResponseType(200)] vereinfacht.For example, [ProducesResponseType(200, Type = typeof(Product))] is simplified to [ProducesResponseType(200)]. Der erwartete Rückgabetyp der Aktion wird stattdessen von T in ActionResult<T> abgeleitet.The action's expected return type is instead inferred from the T in ActionResult<T>.
  • Implizite Umwandlungsoperatoren unterstützen die Konvertierung von T und ActionResult in ActionResult<T>.Implicit cast operators support the conversion of both T and ActionResult to ActionResult<T>. T wird in ObjectResult konvertiert, wodurch return new ObjectResult(T); zu return T; vereinfacht wird.T converts to ObjectResult, which means return new ObjectResult(T); is simplified to return T;.

C# unterstützt keine impliziten Umwandlungsoperatoren in Schnittstellen.C# doesn't support implicit cast operators on interfaces. Daher ist die Konvertierung der Schnittstelle in einen konkreten Typ erforderlich, um ActionResult<T> verwenden zu können.Consequently, conversion of the interface to a concrete type is necessary to use ActionResult<T>. Die Verwendung von IEnumerable im folgenden Beispiel funktioniert also nicht:For example, use of IEnumerable in the following example doesn't work:

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

Eine Möglichkeit zur Korrektur des oben stehenden Codes besteht darin, _repository.GetProducts().ToList(); zurückzugeben.One option to fix the preceding code is to return _repository.GetProducts().ToList();.

Die meisten Aktionen haben einen bestimmten Rückgabetyp.Most actions have a specific return type. Während der Ausführung der Aktion können unerwartete Bedingungen auftreten, wodurch der spezifische Typ nicht zurückgegeben wird.Unexpected conditions can occur during action execution, in which case the specific type isn't returned. So kann beispielsweise die Modellvalidierung des Eingabeparameters einer Aktion fehlschlagen.For example, an action's input parameter may fail model validation. In diesem Fall wird üblicherweise der entsprechende ActionResult-Typ anstatt des spezifischen Typs zurückgegeben.In such a case, it's common to return the appropriate ActionResult type instead of the specific type.

Synchrone AktionSynchronous action

Bei der folgenden synchronen Aktion gibt es zwei mögliche Rückgabetypen:Consider a synchronous action in which there are two possible return types:

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

In der vorhergehenden Aktion geschieht Folgendes:In the preceding action:

  • Ein 404-Statuscode wird zurückgegeben, wenn das Produkt in der Datenbank nicht vorhanden ist.A 404 status code is returned when the product doesn't exist in the database.
  • Ein 200-Statuscode wird mit dem entsprechenden Product-Objekt zurückgegeben, wenn das Produkt vorhanden ist.A 200 status code is returned with the corresponding Product object when the product does exist. Vor ASP.NET Core 2.1 hätte die Zeile return product; stattdessen return Ok(product); lauten müssen.Before ASP.NET Core 2.1, the return product; line had to be return Ok(product);.

Asynchrone AktionAsynchronous action

Bei der folgenden asynchronen Aktion gibt es zwei mögliche Rückgabetypen:Consider an asynchronous action in which there are two possible return types:

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

In der vorhergehenden Aktion geschieht Folgendes:In the preceding action:

  • Ein 400-Statuscode (BadRequest) wird durch die ASP.NET Core-Runtime zurückgegeben, wenn:A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when:
    • Das [ApiController] -Attribut wurde angewendet, und die Modell Validierung schlägt fehl.The [ApiController] attribute has been applied and model validation fails.
    • Die Produktbeschreibung „XYZ-Widget“ enthält.The product description contains "XYZ Widget".
  • Ein 201-Statuscode wird von der Methode CreatedAtAction generiert, wenn ein Produkt erstellt wird.A 201 status code is generated by the CreatedAtAction method when a product is created. In diesem Codepfad wird das Product-Objekt im Antworttext bereitgestellt.In this code path, the Product object is provided in the response body. Ein Location-Antwortheader, der die neu erstellte Produkt-URL enthält, wird bereitgestellt.A Location response header containing the newly created product's URL is provided.

Zusätzliche RessourcenAdditional resources