Erstellen von Web-APIs mit ASP.NET Core

ASP.NET Core unterstützt das Erstellen von Web-APIs mithilfe von Controllern oder minimalen APIs. Controller in einer Web-API sind von ControllerBase abgeleitete Klassen. Controller werden auf Anforderungsbasis aktiviert und verworfen.

In diesem Artikel wird beschrieben, wie Sie Controller für die Verarbeitung von Web-API-Anforderungen verwenden. Informationen zum Erstellen von Web-APIs ohne Controller finden Sie im Tutorial: Erstellen einer minimalen API mit ASP.NET Core.

ControllerBase-Klasse

Eine controllerbasierte 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

Web-API-Controller sollten in der Regel eher von ControllerBase als von Controller ableiten. 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. Wenn derselbe Controller Ansichten und Web-APIs unterstützen muss, leiten Sie von Controller ab.

Die ControllerBase-Klasse bietet viele Eigenschaften und Methoden, die für die Verarbeitung von HTTP-Anforderungen hilfreich sind. 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);
}

Die folgende Tabelle enthält Beispiele für gängige Methoden in ControllerBase.

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:

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

Auf Assemblys kann das [ApiController]-Attribut angewendet werden. Wenn das [ApiController]-Attribut auf eine Assembly angewendet wird, wird auf alle Controller in der Assembly das [ApiController]-Attribut angewendet. Es gibt keine Möglichkeit, einzelne Controller auszuschließen. Wenden Sie das Attribut auf Assemblyebene auf die Program.cs-Datei an:

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

Anforderung für das Attributrouting

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

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

Sie können über konventionelle Routen, die durch UseEndpoints, UseMvc oder UseMvcWithDefaultRoute definiert sind, nicht auf Aktionen zugreifen.

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

Für eine HTTP 400-Antwort wird standardmäßig der Antworttyp ValidationProblemDetails verwendet. Der folgende Antworttext 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-Delegateneigenschaft fest, um benutzerdefinierte Verarbeitung auszuführen. Zum Erstellen einer Instanz von ValidationProblemDetails verwendet InvalidModelStateResponseFactory standardmäßig ProblemDetailsFactory.

Im folgenden Beispiel wird gezeigt, wie Sie eine Instanz von ILogger<TCategoryName> abrufen, um Informationen zu einer automatischen 400-Antwort zu protokollieren:

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

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

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

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.
[AsParameters] Methodenparameter

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:

  • [FromServices] wird für komplexe Typparameter abgeleitet, die im DI-Container registriert sind.
  • [FromBody] wird für komplexe Typparameter abgeleitet, die nicht im DI-Container registriert sind. 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)
    

FromServices-Rückschlusshinweise

Parameterbindung bindet Parameter durch Abhängigkeitsinjektion (Dependency Injection, DI), wenn der Typ als Dienst konfiguriert wird. Dies bedeutet, dass es nicht erforderlich ist, das [FromServices]-Attribut explizit auf einen Parameter anzuwenden. Im folgenden Code geben beide Aktionen die Uhrzeit zurück:

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

In seltenen Fällen kann die automatische DI Apps zum Scheitern bringen, die einen Typ in DI haben, der auch in den Aktionsmethoden eines API-Controllers akzeptiert wird. Es ist nicht üblich, einen Typ in DI und als Argument in einer API-Controlleraktion zu verwenden.

Um den [FromServices]-Rückschluss für einen einzelnen Aktionsparameter zu deaktivieren, wenden Sie das gewünschte Bindungsquellenattribut auf den Parameter an. Wenden Sie beispielsweise das [FromBody]-Attribut auf einen Aktionsparameter an, der vom Textkörper der Anforderung gebunden werden soll.

Um den [FromServices]-Rückschluss global zu deaktivieren, setzen Sie DisableImplicitFromServicesParameters auf 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();

Typen werden beim App-Start mit IServiceProviderIsService überprüft, um festzustellen, ob ein Argument in einer API-Controlleraktion aus DI oder den anderen Quellen stammt.

Der Mechanismus zur Ableitung der Bindungsquelle von Aktionsparametern des API-Controllers verwendet die folgenden Regeln:

Deaktivieren von Rückschlussregeln

Legen Sie SuppressInferBindingSourcesForParameters auf true fest, um den Rückschluss auf Bindungsquellen zu deaktivieren:

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

Ableiten der Multipart/form-data-Anforderung

Das [ApiController]-Attribut wendet eine Rückschlussregel für Aktionsparameter des Typs IFormFile und IFormFileCollection an. Der multipart/form-data-Anforderungsinhaltstyp wird für diese Typen abgeleitet.

Legen Sie die SuppressConsumesConstraintForFormFileParameters-Eigenschaft auf true fest, um das Standardverhalten zu deaktivieren:

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

Problemdetails für Fehlerstatuscodes

MVC wandelt ein Fehlerergebnis (ein Ergebnis mit dem Statuscode 400 oder höher) in ein Ergebnis mit ProblemDetails um. Die ProblemDetails-Typ basiert auf der RFC 7807-Spezifikation 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 hinzu:

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

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

Standardmäßig unterstützt eine Aktion alle verfügbaren Anforderungsinhaltstypen. Wenn eine App beispielsweise zur Unterstützung von JSON- und XML-Eingabeformatierern konfiguriert ist, unterstützt eine Aktion mehrere Inhaltstypen, wie etwa application/json 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. Für Anforderungen, die den Content-Type-Header application/xml nicht angeben, wird die Antwort 415 – Nicht unterstützter Medientyp zurückgegeben.

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

ASP.NET Core unterstützt das Erstellen von Web-APIs mithilfe von Controllern oder minimalen APIs. Controller in einer Web-API sind von ControllerBase abgeleitete Klassen. In diesem Artikel wird beschrieben, wie Sie Controller für die Verarbeitung von Web-API-Anforderungen verwenden. Informationen zum Erstellen von Web-APIs ohne Controller finden Sie im Tutorial: Erstellen einer minimalen API mit ASP.NET Core.

ControllerBase-Klasse

Eine controllerbasierte 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

Web-API-Controller sollten in der Regel eher von ControllerBase als von Controller ableiten. 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. Wenn derselbe Controller Ansichten und Web-APIs unterstützen muss, leiten Sie von Controller ab.

Die ControllerBase-Klasse bietet viele Eigenschaften und Methoden, die für die Verarbeitung von HTTP-Anforderungen hilfreich sind. 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);
}

Die folgende Tabelle enthält Beispiele für gängige Methoden in ControllerBase.

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:

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

Auf Assemblys kann das [ApiController]-Attribut angewendet werden. Wenn das [ApiController]-Attribut auf eine Assembly angewendet wird, wird auf alle Controller in der Assembly das [ApiController]-Attribut angewendet. Es gibt keine Möglichkeit, einzelne Controller auszuschließen. Wenden Sie das Attribut auf Assemblyebene auf die Program.cs-Datei an:

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

Anforderung für das Attributrouting

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

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

Sie können über konventionelle Routen, die durch UseEndpoints, UseMvc oder UseMvcWithDefaultRoute definiert sind, nicht auf Aktionen zugreifen.

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

Der folgende Antworttext ist ein Beispiel für den serialisierten Typ:

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

Für eine HTTP 400-Antwort wird standardmäßig der Antworttyp ValidationProblemDetails verwendet. Der folgende Antworttext 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-Delegateneigenschaft fest, um benutzerdefinierte Verarbeitung auszuführen. Zum Erstellen einer Instanz von ValidationProblemDetails verwendet InvalidModelStateResponseFactory standardmäßig ProblemDetailsFactory.

Im folgenden Beispiel wird gezeigt, wie Sie eine Instanz von ILogger<TCategoryName> abrufen, um Informationen zu einer automatischen 400-Antwort zu protokollieren:

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

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

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

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, die nicht im DI-Container registriert sind. 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:

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

Ableiten der Multipart/form-data-Anforderung

Das [ApiController]-Attribut wendet eine Rückschlussregel für Aktionsparameter des Typs IFormFile und IFormFileCollection an. Der multipart/form-data-Anforderungsinhaltstyp wird für diese Typen abgeleitet.

Legen Sie die SuppressConsumesConstraintForFormFileParameters-Eigenschaft auf true fest, um das Standardverhalten zu deaktivieren:

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

Problemdetails für Fehlerstatuscodes

MVC wandelt ein Fehlerergebnis (ein Ergebnis mit dem Statuscode 400 oder höher) in ein Ergebnis mit ProblemDetails um. Die ProblemDetails-Typ basiert auf der RFC 7807-Spezifikation 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:

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

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

Standardmäßig unterstützt eine Aktion alle verfügbaren Anforderungsinhaltstypen. Wenn eine App beispielsweise zur Unterstützung von JSON- und XML-Eingabeformatierern konfiguriert ist, unterstützt eine Aktion mehrere Inhaltstypen, wie etwa application/json 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. Für Anforderungen, die den Content-Type-Header application/xml nicht angeben, wird die Antwort 415 – Nicht unterstützter Medientyp zurückgegeben.

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

ASP.NET Core unterstützt das Erstellen von RESTful-Diensten mit C#, die auch als Web-APIs bekannt sind. Eine Web-API verwendet Controller, um Anforderungen zu verarbeiten. Controller in einer Web-API sind von ControllerBase abgeleitete Klassen. 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:

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

Auf Assemblys kann das [ApiController]-Attribut 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

Sie können über konventionelle Routen, die durch UseEndpoints, UseMvc oder UseMvcWithDefaultRoute in Startup.Configure definiert sind, nicht auf Aktionen zugreifen.

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

Der folgende Anforderungstext ist ein Beispiel für den serialisierten Typ:

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

Für eine HTTP 400-Antwort wird 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-Delegateneigenschaft in Startup.ConfigureServices fest, um benutzerdefinierte Verarbeitung auszuführen. Zum Erstellen einer Instanz von ValidationProblemDetails verwendet InvalidModelStateResponseFactory standardmäßig ProblemDetailsFactory.

Im folgenden Beispiel wird gezeigt, wie Sie eine Instanz von ILogger<TCategoryName> abrufen, um Informationen zu einer automatischen 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";
        options.DisableImplicitFromServicesParameters = 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)
    

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";
        options.DisableImplicitFromServicesParameters = true;
    });

Ableiten der Multipart/form-data-Anforderung

Das [ApiController]-Attribut wendet eine Rückschlussregel für Aktionsparameter des Typs IFormFile und IFormFileCollection an. Der multipart/form-data-Anforderungsinhaltstyp wird für diese Typen 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";
        options.DisableImplicitFromServicesParameters = true;
    });

Problemdetails für Fehlerstatuscodes

MVC wandelt ein Fehlerergebnis (ein Ergebnis mit dem Statuscode 400 oder höher) in ein Ergebnis mit ProblemDetails um. Die ProblemDetails-Typ basiert auf der RFC 7807-Spezifikation 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:

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

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

Standardmäßig unterstützt eine Aktion alle verfügbaren Anforderungsinhaltstypen. Wenn eine App beispielsweise zur Unterstützung von JSON- und XML-Eingabeformatierern konfiguriert ist, unterstützt eine Aktion mehrere Inhaltstypen, wie etwa application/json 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. Für Anforderungen, die den Content-Type-Header application/xml nicht angeben, wird die Antwort 415 – Nicht unterstützter Medientyp zurückgegeben.

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

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 [ApiController]-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

Sie können über konventionelle Routen, die durch UseMvc oder UseMvcWithDefaultRoute in Startup.Configure definiert sind, nicht auf Aktionen zugreifen.

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 für Aktionsparameter des Typs IFormFile und IFormFileCollection an. Der multipart/form-data-Anforderungsinhaltstyp wird für diese Typen 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. Die ProblemDetails-Typ basiert auf der RFC 7807-Spezifikation 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 zur Unterstützung von JSON- und XML-Eingabeformatierern konfiguriert ist, unterstützt eine Aktion mehrere Inhaltstypen, wie etwa application/json 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. Für Anforderungen, die den Content-Type-Header application/xml nicht angeben, wird die Antwort 415 – Nicht unterstützter Medientyp zurückgegeben. 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