Erstellen von Web-APIs mit ASP.NET Core

Von Scott Addie und Tom Dykstra

ASP.NET Core unterstützt das Erstellen von RESTful-Diensten, die auch als Web-APIs bezeichnet werden, unter Verwendung von C#. Eine Web-API verwendet Controller, um Anforderungen zu verarbeiten. Controller in einer Web-API sind Klassen, die von ableiten. In diesem Artikel wird beschrieben, wie Sie Controller für die Verarbeitung von Web-API-Anforderungen verwenden.

Anzeigen oder Herunterladen von Beispielcode (Informationen zum Herunterladen)

ControllerBase-Klasse

Eine Web-API besteht aus mindestens einer Controllerklasse, die von ControllerBase abgeleitet ist. Die Web-API-Projektvorlage stellt einen Startercontroller bereit:

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

Erstellen Sie einen Web-API-Controller nicht durch Ableitung aus der Controller-Klasse. Controller wird von ControllerBase abgeleitet und fügt Unterstützung für Ansichten hinzu, wird also für die Verarbeitung von Webseiten verwendet und nicht für Web-API-Anforderungen. Es gibt eine Ausnahme von dieser Regel: Wenn Sie denselben Controller sowohl für Ansichten als auch für Web-APIs verwenden möchten, leiten Sie ihn von Controller ab.

Die ControllerBase-Klasse bietet viele Eigenschaften und Methoden, die für die Verarbeitung von HTTP-Anforderungen hilfreich sind. ControllerBase.CreatedAtAction gibt beispielsweise Statuscode 201 zurück:

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

Hier einige weitere Beispiele für die von ControllerBase bereitgestellten Methoden.

Methode Hinweise
BadRequest Gibt Statuscode 400 zurück.
NotFound Gibt Statuscode 404 zurück.
PhysicalFile Gibt eine Datei zurück.
TryUpdateModelAsync Ruft die Modellbindung auf.
TryValidateModel Ruft die Modellvalidierung auf.

Eine Liste aller verfügbaren Methoden und Eigenschaften finden Sie unter ControllerBase.

Attribute

Der Microsoft.AspNetCore.Mvc-Namespace enthält Attribute, mit denen das Verhalten von Web-API-Controllern und Aktionsmethoden konfiguriert werden kann. Im folgenden Beispiel werden Attribute verwendet, um das unterstützte HTTP-Aktionsverb und alle bekannten HTTP-Statuscodes, die zurückgegeben werden können, anzugeben:

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

Hier einige weitere Beispiele für die verfügbaren Attribute.

Attribut Hinweise
[Route] Gibt ein URL-Muster für einen Controller oder eine Aktion an.
[Bind] Gibt Präfixe und Eigenschaften an, die in die Modellbindung einbezogen werden sollen.
[HttpGet] Identifiziert eine Aktion, die das HTTP GET-Aktionsverb unterstützt.
[Consumes] Gibt die von einer Aktion akzeptierten Datentypen an.
[Produces] Gibt die von einer Aktion zurückgegebenen Datentypen an.

Eine Liste mit den verfügbaren Attributen finden Sie im Microsoft.AspNetCore.Mvc-Namespace.

ApiController-Attribut

Das [ApiController]-Attribut kann auf eine Controllerklasse angewendet werden, um folgende API-spezifische Verhalten mit einigen vordefinierten Konfigurationen zu aktivieren:

Das Feature Problemdetails für Fehlerstatuscodes erfordert mindestens die Kompatibilitätsversion 2.2. Die anderen Features erfordern mindestens Kompatibilitätsversion 2.1.

Diese Features erfordern mindestens Kompatibilitätsversion 2.1.

Attribut für bestimmte Controller

Das [ApiController]-Attribut kann, wie im folgenden Beispiel der Projektvorlage ersichtlich, auf bestimmte Controller angewendet werden:

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

Attribut für mehrere Controller

Eine Möglichkeit, das Attribut für mehr als einen Controller zu verwenden, besteht darin, eine benutzerdefinierte Basiscontrollerklasse zu erstellen, die mit dem [ApiController]-Attribut kommentiert ist. Im folgenden Beispiel wird eine benutzerdefinierte Basisklasse und ein Controller, der von ihr abgeleitet wird, gezeigt:

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

Attribut für eine Assembly

Wenn die Kompatibilitätsversion auf 2.2 oder höher festgelegt ist, kann das Attribut auf eine Assembly angewendet werden. Auf diese Weise wendet die Anmerkung das Web-API-Verhalten auf alle Controller in der Assembly an. Es gibt keine Möglichkeit, einzelne Controller auszuschließen. Wenden Sie das Attribut auf Assemblyebene auf die Namespacedeklaration an, die die Startup-Klasse umgibt:

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

Anforderung für das Attributrouting

Durch das [ApiController]-Attribut wird das Attributrouting zu einer Anforderung. Zum Beispiel:

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

Auf Aktionen kann nicht über herkömmliche Routen zugegriffen werden, die durch , oder in definiert UseMvcUseMvcWithDefaultRouteStartup.Configure werden.

Automatische HTTP 400-Antwort

Durch das [ApiController]-Attribut wird bei Modellvalidierungsfehlern automatisch eine HTTP 400-Antwort ausgelöst. Deshalb ist der folgende Code in einer Aktionsmethode überflüssig:

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

ASP.NET Core MVC verwendet den ModelStateInvalidFilter-Aktionsfilter, um die vorherige Überprüfung durchzuführen.

Standardmäßige BadRequest-Antwort

Bei Kompatibilitätsversion 2.1 wird für eine HTTP 400-Antwort standardmäßig der Antworttyp SerializableError verwendet. Der folgende Anforderungstext ist ein Beispiel für den serialisierten Typ:

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

Bei Kompatibilitätsversion 2.2 oder höher wird für eine HTTP 400-Antwort standardmäßig der Antworttyp ValidationProblemDetails verwendet. Der folgende Anforderungstext ist ein Beispiel für den serialisierten Typ:

{
  "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."
    ]
  }
}

Der ValidationProblemDetails-Typ:

  • Bietet ein vom Computer lesbares Format zum Angeben von Fehlern in Web-API-Antworten.
  • Entspricht der RFC 7807-Spezifikation.

Rufen Sie die ValidationProblem-Methode anstelle von BadRequest auf, um automatische und benutzerdefinierte Antworten konsistent zu machen. ValidationProblem gibt sowohl ein ValidationProblemDetails-Objekt als auch die automatische Antwort zurück.

Protokollieren automatischer 400-Antworten

Um automatische 400-Antworten zu protokollieren, legen Sie die InvalidModelStateResponseFactory Delegateigenschaft so fest, dass eine benutzerdefinierte Verarbeitung in Startup.ConfigureServices erfolgt. Standardmäßig verwendet , InvalidModelStateResponseFactory um eine Instanz von zu ProblemDetailsFactoryValidationProblemDetails erstellen.

Das folgende Beispiel zeigt, wie eine Instanz von abgerufen wird, um Informationen zu einer automatischen ILogger<TCategoryName> 400-Antwort zu protokollieren:

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

Deaktivieren automatischer 400-Antwort

Um das automatische Verhalten bei Statuscode 400 zu deaktivieren, legen Sie die SuppressModelStateInvalidFilter-Eigenschaft auf true fest. Fügen Sie folgenden hervorgehobenen Code in Startup.ConfigureServices hinzu:

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

Rückschluss auf Bindungsquellparameter

Ein Bindungsquellenattribut definiert den Speicherort, an dem der Wert eines Aktionsparameters vorhanden ist. Es gibt die folgenden Bindungsquellattribute:

Attribut Bindungsquelle
[FromBody] Anforderungstext
[FromForm] Formulardaten im Anforderungstext
[FromHeader] Anforderungsheader
[FromQuery] Abfragezeichenfolge-Parameter der Anforderung
[FromRoute] Routendaten aus aktuellen Anforderungen
[FromServices] Der als Aktionsparameter eingefügte Anforderungsdienst.

Warnung

Verwenden Sie [FromRoute] nicht, wenn Werte möglicherweise %2f enthalten (d.h. /). %2f wird nicht durch Entfernen von Escapezeichen zu /. Verwenden Sie [FromQuery], wenn der Wert %2f enthalten könnte.

Ohne das [ApiController]-Attribut oder Bindungsquellenattribute wie [FromQuery] versucht die ASP.NET Core-Runtime, die Modellbindung für komplexe Objekte zu verwenden. Bei der Modellbindung für komplexe Objekte werden Daten aus Wertanbietern in einer festgelegten Reihenfolge abgerufen.

Im folgenden Beispiel gibt das [FromQuery]-Attribut an, dass der Parameterwert discontinuedOnly in der Abfragezeichenfolge der Anforderungs-URL bereitgestellt wird:

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

Das [ApiController]-Attribut wendet Rückschlussregeln auf die Standarddatenquellen von Aktionsparametern an. Da durch diese Regeln Attribute auf die Aktionsparameter angewendet werden, müssen Sie Bindungsquellen nicht manuell identifizieren. Die Rückschlussregeln für Bindungsquellen verhalten sich wie folgt:

  • [FromBody] wird für komplexe Typparameter abgeleitet. Jeder komplexe integrierte Typ mit spezieller Bedeutung, z. B. IFormCollection und CancellationToken, stellt eine Ausnahme von der [FromBody]-Rückschlussregel dar. Der Rückschlusscode der Bindungsquelle ignoriert diese Typen.
  • [FromForm] wird für Aktionsparameter des Typs IFormFile und IFormFileCollection abgeleitet. Es wird für keine einfachen oder benutzerdefinierte Typen abgeleitet.
  • [FromRoute] wird für jeden Namen von Aktionsparametern abgeleitet, der mit einem Parameter in der Routenvorlage übereinstimmt. Wenn mehr als eine Route mit einem Aktionsparameter übereinstimmt, gilt jeder Routenwert als [FromRoute].
  • [FromQuery] wird für alle anderen Aktionsparameter abgeleitet.

Hinweise zum FromBody-Rückschluss

[FromBody] wird für einfache Typen wie string oder int nicht abgeleitet. Deshalb sollte das [FromBody]-Attribut für einfache Typen verwendet werden, wenn diese Funktionsweise benötigt wird.

Wenn an eine Aktion mehr als ein Parameter aus dem Anforderungstext gebunden ist, wird eine Ausnahme ausgelöst. Beispielsweise lösen alle Signaturen der folgenden Aktionsmethoden eine Ausnahme aus:

  • [FromBody] wird für beide abgeleitet, da sie komplexe Typen darstellen.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Das [FromBody]-Attribut für einen Typ wird für den anderen abgeleitet, da es sich um einen komplexen Typ handelt.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Das [FromBody]-Attribut für beide.

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

Deaktivieren von Rückschlussregeln

Legen Sie SuppressInferBindingSourcesForParameters auf true fest, um den Rückschluss auf Bindungsquellen zu deaktivieren. Fügen Sie den folgenden Code zu Startup.ConfigureServices hinzu:

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

Ableiten der Multipart/form-data-Anforderung

Das [ApiController]-Attribut wendet eine Rückschlussregel an, wenn ein Aktionsparameter mit dem [FromForm]-Attribut kommentiert ist. Der multipart/form-data-Anforderungsinhaltstyp wird abgeleitet.

Legen Sie die SuppressConsumesConstraintForFormFileParameters-Eigenschaft auf true in Startup.ConfigureServices fest, um das Standardverhalten zu deaktivieren.

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

Problemdetails für Fehlerstatuscodes

Bei Kompatibilitätsversion 2.2 oder höher wandelt MVC ein Fehlerergebnis (ein Ergebnis mit dem Statuscode 400 oder höher) in ein Ergebnis mit ProblemDetails um. Der ProblemDetails Typ basiert auf der RFC ProblemDetails zum Bereitstellen von maschinenlesbaren Fehlerdetails in einer HTTP-Antwort.

Betrachten Sie den folgenden Code in einer Controlleraktion:

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

Die NotFound-Methode erzeugt einen HTTP-404-Statuscode mit einem ProblemDetails-Text. Zum Beispiel:

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

Deaktivieren der ProblemDetails-Antwort

Die automatische Erstellung einer ProblemDetails-Antwort für Fehlerstatuscodes ist deaktiviert, wenn die SuppressMapClientErrors-Eigenschaft auf true festgelegt ist. Fügen Sie den folgenden Code zu Startup.ConfigureServices hinzu:

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

Definieren unterstützter Anforderungsinhaltstypen mit dem [Consumes]-Attribut

Standardmäßig unterstützt eine Aktion alle verfügbaren Anforderungsinhaltstypen. Wenn eine App beispielsweise für die Unterstützung von JSON- und XML-Eingabeformatierern konfiguriert ist, unterstützt eine Aktion mehrere Inhaltstypen, einschließlich und application/xml .

Das [Consumes]-Attribut ermöglicht es einer Aktion, die unterstützten Anforderungsinhaltstypen einzuschränken. Wenden Sie das [Consumes]-Attribut auf eine Aktion oder einen Controller an, und geben Sie mindestens einen Inhaltstyp an:

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

Im obigen Code gibt die CreateProduct-Aktion den Inhaltstyp application/xml an. Anforderungen, die an diese Aktion weitergeleitet werden, müssen den Content-Type-Header application/xml angeben. Anforderungen, die keinen Header von angeben, führen zu einer Antwort vom Typ Content-Typeapplication/xmlContent-Type unterstützt".

Das [Consumes]-Attribut ermöglicht es einer Aktion auch, eine Typeinschränkung anzuwenden, um die Auswahl basierend auf dem Inhaltstyp einer eingehenden Anforderung zu beeinflussen. Betrachten Sie das folgende Beispiel:

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

Im obigen Code ist ConsumesController zur Verarbeitung von Anforderungen konfiguriert, die an die URL https://localhost:5001/api/Consumes gesendet werden. Beide Controlleraktionen – PostJson und PostForm – verarbeiten POST-Anforderungen mit derselben URL. Wenn das [Consumes]-Attribut keine Typeinschränkung anwendet, wird eine Ausnahme in Bezug auf eine mehrdeutige Übereinstimmung ausgelöst.

Das [Consumes]-Attribut wird auf beide Aktionen angewendet. Die PostJson-Aktion verarbeitet Anforderungen, die mit dem Content-Type-Header application/json gesendet werden. Die PostForm-Aktion verarbeitet Anforderungen, die mit dem Content-Type-Header application/x-www-form-urlencoded gesendet werden.

Zusätzliche Ressourcen

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

Erstellen Sie einen Web-API-Controller nicht durch Ableitung aus der Controller-Klasse. Controller wird von ControllerBase abgeleitet und fügt Unterstützung für Ansichten hinzu, wird also für die Verarbeitung von Webseiten verwendet und nicht für Web-API-Anforderungen. Es gibt eine Ausnahme von dieser Regel: Wenn Sie denselben Controller sowohl für Ansichten als auch für Web-APIs verwenden möchten, leiten Sie ihn von Controller ab.

Die ControllerBase-Klasse bietet viele Eigenschaften und Methoden, die für die Verarbeitung von HTTP-Anforderungen hilfreich sind. ControllerBase.CreatedAtAction gibt beispielsweise Statuscode 201 zurück:

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

Hier einige weitere Beispiele für die von ControllerBase bereitgestellten Methoden.

Methode Hinweise
BadRequest Gibt Statuscode 400 zurück.
NotFound Gibt Statuscode 404 zurück.
PhysicalFile Gibt eine Datei zurück.
TryUpdateModelAsync Ruft die Modellbindung auf.
TryValidateModel Ruft die Modellvalidierung auf.

Eine Liste aller verfügbaren Methoden und Eigenschaften finden Sie unter ControllerBase.

Attribute

Der Microsoft.AspNetCore.Mvc-Namespace enthält Attribute, mit denen das Verhalten von Web-API-Controllern und Aktionsmethoden konfiguriert werden kann. Im folgenden Beispiel werden Attribute verwendet, um das unterstützte HTTP-Aktionsverb und alle bekannten HTTP-Statuscodes, die zurückgegeben werden können, anzugeben:

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

Hier einige weitere Beispiele für die verfügbaren Attribute.

Attribut Hinweise
[Route] Gibt ein URL-Muster für einen Controller oder eine Aktion an.
[Bind] Gibt Präfixe und Eigenschaften an, die in die Modellbindung einbezogen werden sollen.
[HttpGet] Identifiziert eine Aktion, die das HTTP GET-Aktionsverb unterstützt.
[Consumes] Gibt die von einer Aktion akzeptierten Datentypen an.
[Produces] Gibt die von einer Aktion zurückgegebenen Datentypen an.

Eine Liste mit den verfügbaren Attributen finden Sie im Microsoft.AspNetCore.Mvc-Namespace.

ApiController-Attribut

Das [ApiController]-Attribut kann auf eine Controllerklasse angewendet werden, um folgende API-spezifische Verhalten mit einigen vordefinierten Konfigurationen zu aktivieren:

Das Feature Problemdetails für Fehlerstatuscodes erfordert mindestens die Kompatibilitätsversion 2.2. Die anderen Features erfordern mindestens Kompatibilitätsversion 2.1.

Diese Features erfordern mindestens Kompatibilitätsversion 2.1.

Attribut für bestimmte Controller

Das [ApiController]-Attribut kann, wie im folgenden Beispiel der Projektvorlage ersichtlich, auf bestimmte Controller angewendet werden:

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

Attribut für mehrere Controller

Eine Möglichkeit, das Attribut für mehr als einen Controller zu verwenden, besteht darin, eine benutzerdefinierte Basiscontrollerklasse zu erstellen, die mit dem [ApiController]-Attribut kommentiert ist. Im folgenden Beispiel wird eine benutzerdefinierte Basisklasse und ein Controller, der von ihr abgeleitet wird, gezeigt:

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

Attribut für eine Assembly

Wenn die Kompatibilitätsversion auf 2.2 oder höher festgelegt ist, kann das -Attribut auf eine Assembly angewendet werden. Auf diese Weise wendet die Anmerkung das Web-API-Verhalten auf alle Controller in der Assembly an. Es gibt keine Möglichkeit, einzelne Controller auszuschließen. Wenden Sie das Attribut auf Assemblyebene auf die Namespacedeklaration an, die die Startup-Klasse umgibt:

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

Anforderung für das Attributrouting

Durch das [ApiController]-Attribut wird das Attributrouting zu einer Anforderung. Zum Beispiel:

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

Auf Aktionen kann nicht über herkömmliche Routen zugegriffen werden, die durch oder in definiert UseMvcWithDefaultRouteStartup.Configure werden.

Automatische HTTP 400-Antwort

Durch das [ApiController]-Attribut wird bei Modellvalidierungsfehlern automatisch eine HTTP 400-Antwort ausgelöst. Deshalb ist der folgende Code in einer Aktionsmethode überflüssig:

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

ASP.NET Core MVC verwendet den ModelStateInvalidFilter-Aktionsfilter, um die vorherige Überprüfung durchzuführen.

Standardmäßige BadRequest-Antwort

Bei Kompatibilitätsversion 2.1 wird für eine HTTP 400-Antwort standardmäßig der Antworttyp SerializableError verwendet. Der folgende Anforderungstext ist ein Beispiel für den serialisierten Typ:

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

Bei Kompatibilitätsversion 2.2 oder höher wird für eine HTTP 400-Antwort standardmäßig der Antworttyp ValidationProblemDetails verwendet. Der folgende Anforderungstext ist ein Beispiel für den serialisierten Typ:

{
  "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."
    ]
  }
}

Der ValidationProblemDetails-Typ:

  • Bietet ein vom Computer lesbares Format zum Angeben von Fehlern in Web-API-Antworten.
  • Entspricht der RFC 7807-Spezifikation.

Rufen Sie die ValidationProblem-Methode anstelle von BadRequest auf, um automatische und benutzerdefinierte Antworten konsistent zu machen. ValidationProblem gibt sowohl ein ValidationProblemDetails-Objekt als auch die automatische Antwort zurück.

Protokollieren automatischer 400-Antworten

Informationen finden Sie unter Protokollieren automatischer 400-Antworten auf Modellvalidierungsfehler, (dotnet/AspNetCore.Docs#12157).

Deaktivieren automatischer 400-Antwort

Um das automatische Verhalten bei Statuscode 400 zu deaktivieren, legen Sie die SuppressModelStateInvalidFilter-Eigenschaft auf true fest. Fügen Sie folgenden hervorgehobenen Code in Startup.ConfigureServices hinzu:

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

Rückschluss auf Bindungsquellparameter

Ein Bindungsquellenattribut definiert den Speicherort, an dem der Wert eines Aktionsparameters vorhanden ist. Es gibt die folgenden Bindungsquellattribute:

Attribut Bindungsquelle
[FromBody] Anforderungstext
[FromForm] Formulardaten im Anforderungstext
[FromHeader] Anforderungsheader
[FromQuery] Abfragezeichenfolge-Parameter der Anforderung
[FromRoute] Routendaten aus aktuellen Anforderungen
[FromServices] Der als Aktionsparameter eingefügte Anforderungsdienst.

Warnung

Verwenden Sie [FromRoute] nicht, wenn Werte möglicherweise %2f enthalten (d.h. /). %2f wird nicht durch Entfernen von Escapezeichen zu /. Verwenden Sie [FromQuery], wenn der Wert %2f enthalten könnte.

Ohne das [ApiController]-Attribut oder Bindungsquellenattribute wie [FromQuery] versucht die ASP.NET Core-Runtime, die Modellbindung für komplexe Objekte zu verwenden. Bei der Modellbindung für komplexe Objekte werden Daten aus Wertanbietern in einer festgelegten Reihenfolge abgerufen.

Im folgenden Beispiel gibt das [FromQuery]-Attribut an, dass der Parameterwert discontinuedOnly in der Abfragezeichenfolge der Anforderungs-URL bereitgestellt wird:

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

Das [ApiController]-Attribut wendet Rückschlussregeln auf die Standarddatenquellen von Aktionsparametern an. Da durch diese Regeln Attribute auf die Aktionsparameter angewendet werden, müssen Sie Bindungsquellen nicht manuell identifizieren. Die Rückschlussregeln für Bindungsquellen verhalten sich wie folgt:

  • [FromBody] wird für komplexe Typparameter abgeleitet. Jeder komplexe integrierte Typ mit spezieller Bedeutung, z. B. IFormCollection und CancellationToken, stellt eine Ausnahme von der [FromBody]-Rückschlussregel dar. Der Rückschlusscode der Bindungsquelle ignoriert diese Typen.
  • [FromForm] wird für Aktionsparameter des Typs IFormFile und IFormFileCollection abgeleitet. Es wird für keine einfachen oder benutzerdefinierte Typen abgeleitet.
  • [FromRoute] wird für jeden Namen von Aktionsparametern abgeleitet, der mit einem Parameter in der Routenvorlage übereinstimmt. Wenn mehr als eine Route mit einem Aktionsparameter übereinstimmt, gilt jeder Routenwert als [FromRoute].
  • [FromQuery] wird für alle anderen Aktionsparameter abgeleitet.

Hinweise zum FromBody-Rückschluss

[FromBody] wird für einfache Typen wie string oder int nicht abgeleitet. Deshalb sollte das [FromBody]-Attribut für einfache Typen verwendet werden, wenn diese Funktionsweise benötigt wird.

Wenn an eine Aktion mehr als ein Parameter aus dem Anforderungstext gebunden ist, wird eine Ausnahme ausgelöst. Beispielsweise lösen alle Signaturen der folgenden Aktionsmethoden eine Ausnahme aus:

  • [FromBody] wird für beide abgeleitet, da sie komplexe Typen darstellen.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Das [FromBody]-Attribut für einen Typ wird für den anderen abgeleitet, da es sich um einen komplexen Typ handelt.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Das [FromBody]-Attribut für beide.

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

Hinweis

In ASP.NET Core 2.1 werden Sammlungstypparameter wie Listen und Arrays fälschlicherweise als [FromQuery] abgeleitet. Für diese Parameter sollte das [FromBody]-Attribut verwendet werden, wenn sie aus dem Anforderungstext gebunden werden sollen. Dieses Verhalten wurde bei ASP.NET Core 2.2 oder höher behoben. Hier werden Sammlungstypparameter standardmäßig als „[FromBody]“ abgeleitet.

Deaktivieren von Rückschlussregeln

Legen Sie SuppressInferBindingSourcesForParameters auf true fest, um den Rückschluss auf Bindungsquellen zu deaktivieren. Fügen Sie den folgenden Code zu Startup.ConfigureServices hinzu:

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

Ableiten der Multipart/form-data-Anforderung

Das [ApiController]-Attribut wendet eine Rückschlussregel an, wenn ein Aktionsparameter mit dem [FromForm]-Attribut kommentiert ist. Der multipart/form-data-Anforderungsinhaltstyp wird abgeleitet.

Legen Sie die SuppressConsumesConstraintForFormFileParameters-Eigenschaft auf true in Startup.ConfigureServices fest, um das Standardverhalten zu deaktivieren.

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

Problemdetails für Fehlerstatuscodes

Bei Kompatibilitätsversion 2.2 oder höher wandelt MVC ein Fehlerergebnis (ein Ergebnis mit dem Statuscode 400 oder höher) in ein Ergebnis mit ProblemDetails um. Der ProblemDetails Typ basiert auf der ProblemDetails für die Bereitstellung maschinenlesbarer Fehlerdetails in einer HTTP-Antwort.

Betrachten Sie den folgenden Code in einer Controlleraktion:

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

Die NotFound-Methode erzeugt einen HTTP-404-Statuscode mit einem ProblemDetails-Text. Zum Beispiel:

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

Deaktivieren der ProblemDetails-Antwort

Die automatische Erstellung einer ProblemDetails-Antwort für Fehlerstatuscodes ist deaktiviert, wenn die SuppressMapClientErrors-Eigenschaft auf true festgelegt ist. Fügen Sie den folgenden Code zu Startup.ConfigureServices hinzu:

Definieren unterstützter Anforderungsinhaltstypen mit dem [Consumes]-Attribut

Standardmäßig unterstützt eine Aktion alle verfügbaren Anforderungsinhaltstypen. Wenn eine App beispielsweise so konfiguriert ist, dass sie sowohl JSON- als auch XML-Eingabeformatiererunterstützt, unterstützt eine Aktion mehrere Inhaltstypen, einschließlich und application/xml .

Das [Consumes]-Attribut ermöglicht es einer Aktion, die unterstützten Anforderungsinhaltstypen einzuschränken. Wenden Sie das [Consumes]-Attribut auf eine Aktion oder einen Controller an, und geben Sie mindestens einen Inhaltstyp an:

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

Im obigen Code gibt die CreateProduct-Aktion den Inhaltstyp application/xml an. Anforderungen, die an diese Aktion weitergeleitet werden, müssen den Content-Type-Header application/xml angeben. Anforderungen, die keinen Header von angeben, führen zu einer Antwort vom Content-Typeapplication/xml Typ Content-Type

Das [Consumes]-Attribut ermöglicht es einer Aktion auch, eine Typeinschränkung anzuwenden, um die Auswahl basierend auf dem Inhaltstyp einer eingehenden Anforderung zu beeinflussen. Betrachten Sie das folgende Beispiel:

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

Im obigen Code ist ConsumesController zur Verarbeitung von Anforderungen konfiguriert, die an die URL https://localhost:5001/api/Consumes gesendet werden. Beide Controlleraktionen – PostJson und PostForm – verarbeiten POST-Anforderungen mit derselben URL. Wenn das [Consumes]-Attribut keine Typeinschränkung anwendet, wird eine Ausnahme in Bezug auf eine mehrdeutige Übereinstimmung ausgelöst.

Das [Consumes]-Attribut wird auf beide Aktionen angewendet. Die PostJson-Aktion verarbeitet Anforderungen, die mit dem Content-Type-Header application/json gesendet werden. Die PostForm-Aktion verarbeitet Anforderungen, die mit dem Content-Type-Header application/x-www-form-urlencoded gesendet werden.

Zusätzliche Ressourcen