Formatieren von Antwortdaten in Web-APIs in ASP.NET Core

Von Rick Anderson und Steve Smith

ASP.NET Core MVC unterstützt das Formatieren von Antwortdaten. Antwortdaten können mithilfe bestimmter Formate oder durch Übernahme des vom Client angeforderten Formats formatiert werden.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Formatspezifische Aktionsergebnisse

Einige Aktionsergebnistypen sind für ein bestimmtes Format spezifisch, wie z.B. JsonResult und ContentResult. Aktionen können Ergebnisse zurückgeben, die in einem bestimmten Format formatiert sind, unabhängig von den Clienteinstellungen. Mit JsonResult beispielsweise werden JSON-formatierte Daten zurückgegeben. Mit ContentResult oder einer Zeichenfolge werden Zeichenfolgendaten in Nur-Text-Format zurückgegeben.

Zum Zurückgeben eines bestimmten Typs ist keine Aktion erforderlich. ASP.NET Core unterstützt jeden Objektrückgabewert. Ergebnisse von Aktionen, die Objekte zurückgeben, deren Typ nicht IActionResult ist, werden mit der entsprechenden IOutputFormatter-Implementierung serialisiert. Weitere Informationen finden Sie unter Rückgabetypen für Controlleraktionen in der ASP.NET Core-Web-API.

Die integrierte Hilfsmethode Ok gibt JSON-formatierte Daten zurück: [!code-csharp]

Der Beispieldownload gibt die Liste der Autoren zurück. Bei Verwendung der F12-Entwicklertools im Browser oder von Postman mit dem obigen Code gilt Folgendes:

  • Der Antwortheader mit content-type: application/json; charset=utf-8 wird angezeigt.
  • Die Anforderungsheader werden angezeigt. Beispiel: Der Header Accept. Der Accept-Header wird vom vorangehenden Code ignoriert.

Wenn Sie Daten im Textformat zurückgeben möchten, verwenden Sie ContentResult und das Content-Hilfsprogramm:

// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
    return Content("An API listing authors of docs.asp.net.");
}

Im obigen Code wird text/plain als Content-Type zurückgegeben. Das Zurückgeben einer Zeichenfolge liefert text/plain als Content-Type:

// GET api/authors/version
[HttpGet("version")]
public string Version()
{
    return "Version 1.0.0";
}

Bei Aktionen mit mehreren Rückgabetypen wird IActionResult zurückgegeben. Beispiel: Die Rückgabe von verschiedenen HTTP-Statuscodes basierend auf dem Ergebnis der ausgeführten Vorgänge.

Inhaltsaushandlung

Eine Inhaltsaushandlung tritt auf, wenn der Client einen Accept-Header angibt. Das von ASP.NET Core verwendete Standardformat ist JSON. Für die Inhaltsaushandlung gilt:

  • Sie wird durch ObjectResult implementiert.
  • Sie ist in die Statuscode-spezifischen Aktionsergebnisse integriert, die von den Hilfsmethoden zurückgegeben werden. Die Hilfsmethoden für Aktionsergebnisse basieren auf ObjectResult.

Wenn ein Modelltyp zurückgegeben wird, lautet der Rückgabetyp ObjectResult.

Die folgende Aktionsmethode verwendet die Hilfsmethoden Ok und NotFound:

// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authors.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

Standardmäßig unterstützt ASP.NET Core application/json-, text/json- und text/plain-Medientypen. Tools wie Fiddler oder Postman können den Accept-Anforderungsheader festlegen, um das Rückgabeformat anzugeben. Wenn der Accept-Header einen vom Server unterstützten Typ enthält, wird dieser Typ zurückgegeben. Der nächste Abschnitt zeigt, wie zusätzliche Formatierer hinzugefügt werden.

Controlleraktionen können POCOs (Plain Old CLR Objects) zurückgeben. Wenn ein POCO zurückgegeben wird, erstellt die Runtime automatisch ein ObjectResult, das das Objekt umschließt. Der Client empfängt das formatierte serialisierte Objekt. Wenn das zurückgegebene Objekt null ist, wird eine 204 No Content-Antwort zurückgegeben.

Zurückgeben eines Objekttyps:

// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
    return _authors.GetByAlias(alias);
}

Im oben stehenden Code gibt die Anforderung eines gültigen Autoralias eine 200 OK-Antwort mit den Daten des Autors zurück. Die Anforderung eines ungültigen Alias gibt eine 204 No Content-Antwort zurück.

Der Accept-Header

Eine Aushandlung des Inhalts findet statt, wenn in der Anforderung ein Accept-Header angezeigt wird. Wenn eine Anforderung einen Accept-Header enthält, führt ASP.NET Core Folgendes aus:

  • Die Medientypen im Accept-Header werden in der bevorzugten Reihenfolge aufgelistet.
  • Es wird versucht, einen Formatierer zu finden, der eine Antwort in einem der angegebenen Formate erzeugen kann.

Wenn kein Formatierer gefunden wird, der die Clientanforderung erfüllen kann, führt ASP.NET Core Folgendes aus:

  • Gibt 406 Not Acceptable zurück, wenn MvcOptions.ReturnHttpNotAcceptable auf festgelegt true ist, oder :
  • Es wird versucht, den ersten Formatierer zu finden, der eine Antwort erzeugen kann.

Wenn kein Formatierer für das angeforderte Format konfiguriert wurde, wird der erste Formatierer verwendet, der das Objekt formatieren kann. Wenn in der Anforderung kein Accept-Header vorhanden ist, gilt Folgendes:

  • Der erste Formatierer, der das Objekt verarbeiten kann, wird zum Serialisieren der Antwort verwendet.
  • Es findet keine Aushandlung statt. Der Server bestimmt, welches Format zurückgegeben werden soll.

Enthält der Accept-Header */*, wird der Header ignoriert, es sei denn, RespectBrowserAcceptHeader ist in MvcOptions auf TRUE festgelegt.

Browser und Inhaltsaushandlung

Im Gegensatz zu typischen API-Clients, stellen Webbrowser Accept-Header bereit. Webbrowser geben viele Formate an, einschließlich Platzhaltern. Wenn das Framework erkennt, dass eine Anforderung von einem Browser stammt, wird standardmäßig Folgendes ausgeführt:

  • Der Accept-Header wird ignoriert.
  • Der Inhalt wird im JSON-Format zurückgegeben, sofern nicht anders konfiguriert.

Dies sorgt bei der Verwendung von APIs für ein konsistenteres browserübergreifendes Benutzererlebnis.

Um eine App so zu konfigurieren, dass Accept-Header in Browsern berücksichtigt werden, legen Sie RespectBrowserAcceptHeader auf true fest:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Konfigurieren von Formatierern

Apps, die zusätzliche Formate unterstützen müssen, können die geeigneten NuGet-Pakete hinzufügen und die Unterstützung konfigurieren. Es gibt unterschiedliche Formatierungsprogramme für Ein- und für Ausgaben. Eingabeformatierer werden von der Modellbindung verwendet. Ausgabeformatierer werden zum Formatieren von Antworten verwendet. Informationen zum Erstellen eines benutzerdefinierten Formatierers finden Sie unter Benutzerdefinierte Formatierer.

Hinzufügen von Unterstützung für das XML-Format

XML-Formatierer, die mithilfe von XmlSerializer implementiert wurden, werden durch Aufruf von AddXmlSerializerFormatters konfiguriert:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddXmlSerializerFormatters();
}

Der oben stehende Code serialisiert Ergebnisse mithilfe von XmlSerializer.

Bei Verwendung dieses Codes geben Controllermethoden das geeignete Format basierend auf dem Accept-Header der Anforderung zurück.

Konfigurieren System.Text.Json von basierten Formatierern

Features für die System.Text.Json basierten Formatierer können mit konfiguriert Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions werden. Die Standardformatierung ist camelCase. Der folgende hervorgehobene Code legt die PascalCase-Formatierung fest:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
            .AddJsonOptions(options => 
               options.JsonSerializerOptions.PropertyNamingPolicy = null);
}

Die folgende Aktionsmethode ruft ControllerBase.Problem auf, um eine Antwort zu ProblemDetails erstellen:

[HttpGet("error")]
public IActionResult GetError()
{
    return Problem("Something went wrong!");
}

Mit dem vorangehenden Code:

  • https://localhost:5001/WeatherForecast/temperature gibt PascalCase zurück.
  • https://localhost:5001/WeatherForecast/error gibt camelCase zurück. Die Fehlerantwort lautet immer camelCase, auch wenn die App das Format auf PascalCase festlegt. ProblemDetails folgt RFC 7807, das Kleinbuchstaben angibt.

Der folgende Code legt PascalCase fest und fügt einen benutzerdefinierten Konverter hinzu:

services.AddControllers().AddJsonOptions(options =>
{
    // Use the default property (Pascal) casing.
    options.JsonSerializerOptions.PropertyNamingPolicy = null;

    // Configure a custom converter.
    options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

Optionen zur Ausgabeserialisierung können aktionsweise mithilfe von JsonResult konfiguriert werden. Beispiel:

public IActionResult Get()
{
    return Json(model, new JsonSerializerOptions
    {
        WriteIndented = true,
    });
}

Hinzufügen von Newtonsoft.Json-basierter Unterstützung für das JSON-Format

Vor ASP.NET Core 3.0 wurden standardmäßig die JSON-Formatierer verwendet, die mithilfe des Newtonsoft.Json-Pakets implementiert wurden. In ASP.NET Core 3.0 oder höher basieren die Standardformatierer für JSON auf System.Text.Json. Unterstützung für Newtonsoft.Json basierte Formatierer und Features ist verfügbar, indem das Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet-Paket installiert und in konfiguriert Startup.ConfigureServices wird.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson();
}

Im vorangehenden Code konfiguriert der Aufruf von AddNewtonsoftJson die folgenden Web-API-, MVC- und Razor Pages-Features für die Verwendung Newtonsoft.Json von :

Einige Features funktionieren mit System.Text.Json-basierten Formatierern möglicherweise nicht gut und erfordern einen Verweis auf die Newtonsoft.Json-basierten Formatierer. Verwenden Sie weiterhin Newtonsoft.Json-basierte Formatierer, wenn für die App Folgendes gilt:

  • Sie verwendet Newtonsoft.Json-Attribute. Zum Beispiel: [JsonProperty] oder [JsonIgnore].
  • Sie passt die Serialisierungseinstellungen an.
  • Sie nutzt Features, die von Newtonsoft.Json bereitgestellt werden.
  • Microsoft.AspNetCore.Mvc.JsonResult.SerializerSettings konfiguriert. Vor ASP.NET Core 3.0 akzeptiert JsonResult.SerializerSettings eine Instanz von JsonSerializerSettings, die für Newtonsoft.Json spezifisch ist.

Funktionen für die Newtonsoft.Json-basierten Formatierer können mithilfe von Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings konfiguriert werden:

services.AddControllers().AddNewtonsoftJson(options =>
{
    // Use the default property (Pascal) casing
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();

    // Configure a custom converter
    options.SerializerSettings.Converters.Add(new MyCustomJsonConverter());
});

Optionen zur Ausgabeserialisierung können aktionsweise mithilfe von JsonResult konfiguriert werden. Beispiel:

public IActionResult Get()
{
    return Json(model, new JsonSerializerSettings
    {
        Formatting = Formatting.Indented,
    });
}

Hinzufügen von Unterstützung für das XML-Format

Die XML-Formatierung erfordert das NuGet-Paket Microsoft.AspNetCore.Mvc.Formatters.Xml.

XML-Formatierer, die mithilfe von XmlSerializer implementiert wurden, werden durch Aufruf von AddXmlSerializerFormatters konfiguriert:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddXmlSerializerFormatters();
}

Der oben stehende Code serialisiert Ergebnisse mithilfe von XmlSerializer.

Bei Verwendung dieses Codes sollten Controllermethoden das geeignete Format basierend auf dem Accept-Header der Anforderung zurückgeben.

Angeben eines Formats

Wenden Sie den Filter an, um die Antwortformate [Produces] einzuschränken. Wie die meisten Filterkann auf [Produces] die Aktion, den Controller oder den globalen Bereich angewendet werden:

[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{

Der vorherige [Produces] Filter:

  • Er erzwingt die Rückgabe von JSON-formatierten Antworten von allen Aktionen im Controller.
  • Wenn andere Formatierer konfiguriert sind und der Client ein anderes Format angibt, wird JSON zurückgegeben.

Weitere Informationen finden Sie unter Filter.

Formatierer für besondere Fälle

Einige besondere Fälle werden mithilfe von integrierten Formatierungsprogrammen implementiert. Standardmäßig werden string-Rückgabetypen als text/plain formatiert (bzw. als text/html, wenn sie über den Accept-Header angefordert werden). Dieses Verhalten kann durch Entfernen von StringOutputFormatter gelöscht werden. Formatierer werden in der ConfigureServices-Methode entfernt. Aktionen mit einem Modellobjekt-Rückgabetyp geben null zurück, wenn der Rückgabewert 204 No Content lautet. Dieses Verhalten kann durch Entfernen von HttpNoContentOutputFormatter gelöscht werden. Der folgende Code entfernt StringOutputFormatter und HttpNoContentOutputFormatter.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        // requires using Microsoft.AspNetCore.Mvc.Formatters;
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
        options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        // requires using Microsoft.AspNetCore.Mvc.Formatters;
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
        options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Ohne den StringOutputFormatter formatiert der integrierte JSON-Formatierer string-Rückgabetypen. Wenn der integrierte JSON-Formatierer entfernt wird und ein XML-Formatierer verfügbar ist, formatiert der XML-Formatierer string-Rückgabetypen. Andernfalls geben string-Rückgabetypen 406 Not Acceptable zurück.

Ohne HttpNoContentOutputFormatter werden NULL-Objekte mithilfe des konfigurierten Formatierungsprogramms formatiert. Beispiel:

  • Der JSON-Formatierer gibt eine Antwort mit dem Text null zurück.
  • Der XML-Formatierer gibt ein leeres XML-Element mit festgelegtem Attribut xsi:nil="true" zurück.

Zuordnung des Antwortformats durch URLs

Clients können in der URL ein bestimmtes Format anfordern, beispielsweise folgendermaßen:

  • In der Abfragezeichenfolge oder als Teil des Pfads.
  • Durch Verwendung einer formatspezifischen Dateierweiterung wie „.xml“ oder „.json“.

Die Zuordnung des Anforderungspfads sollte in der Route angegeben werden, die die API verwendet. Beispiel:

[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
    [HttpGet("{id}.{format?}")]
    public Product Get(int id)
    {

Mit der oben genannten Route kann das angeforderte Format als optionale Dateierweiterung angegeben werden. Das -Attribut überprüft das Vorhandensein des Formatwerts in der und ordnet das Antwortformat dem entsprechenden Formatierungsformat zu, wenn [FormatFilter] die Antwort erstellt RouteData wird.

Route Formatierungsprogramm
/api/products/5 Standard-Ausgabeformatierungsprogramm
/api/products/5.json JSON-Formatierungsprogramm (falls konfiguriert)
/api/products/5.xml XML-Formatierungsprogramm (falls konfiguriert)