Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie ASP.NET Web-API Inhaltsverhandlung für ASP.NET 4.x implementiert.
Die HTTP-Spezifikation (RFC 2616) definiert die Inhaltsverhandlung als "der Prozess der Auswahl der besten Darstellung für eine bestimmte Antwort, wenn mehrere Darstellungen verfügbar sind". Der primäre Mechanismus für die Inhaltsverhandlung in HTTP sind die folgenden Anforderungsheader:
- Akzeptieren: Welche Medientypen für die Antwort akzeptabel sind, z. B. "application/json", "application/xml" oder einen benutzerdefinierten Medientyp wie "application/vnd.example+xml"
- Accept-Charset: Welche Zeichensätze zulässig sind, z. B. UTF-8 oder ISO 8859-1.
- Accept-Encoding: Welche Inhaltscodierungen akzeptabel sind, z. B. gzip.
- Accept-Language: Die bevorzugte natürliche Sprache, z. B. "en-us".
Der Server kann auch andere Teile der HTTP-Anforderung betrachten. Wenn die Anforderung beispielsweise einen X-Requested-With-Header enthält, der eine AJAX-Anforderung angibt, kann der Server standardmäßig JSON verwenden, wenn kein Accept-Header vorhanden ist.
In diesem Artikel wird erläutert, wie die Web-API die Header "Accept" und "Accept-Charset" verwendet. (Derzeit gibt es keine integrierte Unterstützung für Accept-Encoding oder Accept-Language.)
Serialisierung
Wenn ein Web-API-Controller eine Ressource als CLR-Typ zurückgibt, serialisiert die Pipeline den Rückgabewert und schreibt sie in den HTTP-Antworttext.
Betrachten Sie beispielsweise die folgende Controlleraktion:
public Product GetProduct(int id)
{
var item = _products.FirstOrDefault(p => p.ID == id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
Ein Client sendet möglicherweise diese HTTP-Anforderung:
GET http://localhost.:21069/api/products/1 HTTP/1.1
Host: localhost.:21069
Accept: application/json, text/javascript, */*; q=0.01
Als Antwort sendet der Server möglicherweise Folgendes:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 57
Connection: Close
{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}
In diesem Beispiel hat der Client ENTWEDER JSON, Javascript oder "anything" (*/*) angefordert. Der Server hat mit einer JSON-Darstellung des Product Objekts geantwortet. Beachten Sie, dass der Content-Type-Header in der Antwort auf "application/json" festgelegt ist.
Ein Controller kann auch ein HttpResponseMessage-Objekt zurückgeben. Rufen Sie die CreateResponse-Erweiterungsmethode auf, um ein CLR-Objekt für den Antworttext anzugeben:
public HttpResponseMessage GetProduct(int id)
{
var item = _products.FirstOrDefault(p => p.ID == id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return Request.CreateResponse(HttpStatusCode.OK, item);
}
Diese Option bietet Ihnen mehr Kontrolle über die Details der Antwort. Sie können den Statuscode festlegen, HTTP-Header hinzufügen usw.
Das Objekt, das die Ressource serialisiert, wird als Medienformatierer bezeichnet. Medienformatierer werden von der MediaTypeFormatter-Klasse abgeleitet. Die Web-API stellt Medienformatierer für XML und JSON bereit, und Sie können benutzerdefinierte Formatierer erstellen, um andere Medientypen zu unterstützen. Informationen zum Schreiben eines benutzerdefinierten Formatierers finden Sie unter Media Formatters.
Funktionsweise der Inhaltsverhandlung
Zunächst ruft die Pipeline den IContentNegotiator-Dienst aus dem HttpConfiguration-Objekt ab . Außerdem wird die Liste der Medienformatierer aus der HttpConfiguration.Formatters -Auflistung abgerufen.
Als Nächstes ruft die Pipeline IContentNegotiator.Negotiate auf und übergibt Folgendes:
- Der Typ des zu serialisierenden Objekts
- Die Sammlung von Medienformatierern
- Die HTTP-Anforderung
Die Negotiate-Methode gibt zwei Informationen zurück:
- Welcher Formatierer verwendet werden soll
- Der Medientyp für die Antwort
Wenn kein Formatierer gefunden wird, gibt die Negotiate-MethodeNULL zurück, und der Client empfängt HTTP-Fehler 406 (Nicht akzeptabel).
Der folgende Code zeigt, wie ein Controller die Inhaltsverhandlung direkt aufrufen kann:
public HttpResponseMessage GetProduct(int id)
{
var product = new Product()
{ Id = id, Name = "Gizmo", Category = "Widgets", Price = 1.99M };
IContentNegotiator negotiator = this.Configuration.Services.GetContentNegotiator();
ContentNegotiationResult result = negotiator.Negotiate(
typeof(Product), this.Request, this.Configuration.Formatters);
if (result == null)
{
var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
throw new HttpResponseException(response));
}
return new HttpResponseMessage()
{
Content = new ObjectContent<Product>(
product, // What we are serializing
result.Formatter, // The media formatter
result.MediaType.MediaType // The MIME type
)
};
}
Dieser Code entspricht dem, was die Pipeline automatisch ausführt.
Standard-Inhaltsverhandler
Die DefaultContentNegotiator-Klasse stellt die Standardimplementierung von IContentNegotiator bereit. Es verwendet mehrere Kriterien, um einen Formatierer auszuwählen.
Zunächst muss der Formatierer in der Lage sein, den Typ zu serialisieren. Dies wird durch Aufrufen von MediaTypeFormatter.CanWriteType überprüft.
Als Nächstes betrachtet der Inhaltsverhandler jeden Formatierer und wertet aus, wie gut er der HTTP-Anforderung entspricht. Um die Übereinstimmung auszuwerten, betrachtet der Inhaltsverhandler zwei Dinge im Formatierer:
- Die SupportedMediaTypes-Auflistung , die eine Liste der unterstützten Medientypen enthält. Der Inhaltsverhandler versucht, diese Liste mit dem Anforderungs-Accept-Header abzugleichen. Beachten Sie, dass die Accept-Kopfzeile Wertebereiche enthalten kann. Beispielsweise ist "text/plain" eine Übereinstimmung für text/* oder */*.
- Die MediaTypeMappings-Auflistung , die eine Liste von MediaTypeMapping-Objekten enthält. Die MediaTypeMapping-Klasse bietet eine generische Möglichkeit, HTTP-Anforderungen mit Medientypen abzugleichen. Beispielsweise könnte ein benutzerdefinierter HTTP-Header einem bestimmten Medientyp zugeordnet werden.
Wenn mehrere Übereinstimmungen vorhanden sind, gewinnt die Übereinstimmung mit dem höchsten Qualitätsfaktor. Beispiel:
Accept: application/json, application/xml; q=0.9, */*; q=0.1
In diesem Beispiel weist Application/json einen impliziten Qualitätsfaktor von 1.0 auf, daher wird sie gegenüber "application/xml" bevorzugt.
Wenn keine Übereinstimmungen gefunden werden, versucht der Inhaltsverhandler, falls vorhanden, den Medientyp des Anforderungstexts abzugleichen. Wenn die Anforderung beispielsweise JSON-Daten enthält, sucht der Inhaltsverhandler nach einem JSON-Formatierer.
Wenn immer noch keine Übereinstimmungen vorhanden sind, wählt der Inhaltsverhandler einfach den ersten Formatierer aus, der den Typ serialisieren kann.
Auswählen einer Zeichencodierung
Nachdem ein Formatierer ausgewählt wurde, wählt der Inhaltsaushandler die beste Zeichencodierung aus, indem er die SupportedEncodings-Eigenschaft auf dem Formatierer betrachtet und mit dem Accept-Charset-Header in der Anforderung abgleicht (falls vorhanden).