ASP.NET Web API 'de içerik anlaşmasıContent Negotiation in ASP.NET Web API

, Mike te sonby Mike Wasson

Bu makalede, ASP.NET Web API 'sinin ASP.NET 4. x için içerik anlaşmasını nasıl uyguladığı açıklanır.This article describes how ASP.NET Web API implements content negotiation for ASP.NET 4.x.

HTTP belirtimi (RFC 2616), "birden fazla temsili varsa belirli bir yanıt için en iyi temsili seçme işlemi" olarak içerik anlaşmasını tanımlar.The HTTP specification (RFC 2616) defines content negotiation as "the process of selecting the best representation for a given response when there are multiple representations available." HTTP 'de içerik anlaşmasına yönelik birincil mekanizma şu istek başlıklardır:The primary mechanism for content negotiation in HTTP are these request headers:

  • Kabul et: "Application/JSON," application/xml "gibi yanıt için kabul edilebilir medya türleri veya "application/vnd gibi özel bir medya türü. örnek + XML"Accept: Which media types are acceptable for the response, such as "application/json," "application/xml," or a custom media type such as "application/vnd.example+xml"
  • Accept-Charset: UTF-8 veya ISO 8859-1 gibi hangi karakter kümeleri kabul edilebilir.Accept-Charset: Which character sets are acceptable, such as UTF-8 or ISO 8859-1.
  • Accept-Encoding: Gzip gibi hangi içerik kodlamaları kabul edilebilir.Accept-Encoding: Which content encodings are acceptable, such as gzip.
  • Accept-Language: Tercih edilen doğal dil ("en-US" gibi).Accept-Language: The preferred natural language, such as "en-us".

Sunucu ayrıca HTTP isteğinin diğer bölümlerine da bakabilirler.The server can also look at other portions of the HTTP request. Örneğin, istek bir AJAX isteği gösteren bir X-requested-with üst bilgisi içeriyorsa, Accept üst bilgisi yoksa sunucu JSON olarak varsayılan olabilir.For example, if the request contains an X-Requested-With header, indicating an AJAX request, the server might default to JSON if there is no Accept header.

Bu makalede, Web API 'sinin Accept ve Accept-Charset üst bilgilerini nasıl kullandığını inceleyeceğiz.In this article, we'll look at how Web API uses the Accept and Accept-Charset headers. (Şu anda, Accept-Encoding veya Accept-Language için yerleşik destek yoktur.)(At this time, there is no built-in support for Accept-Encoding or Accept-Language.)

SerileştirmeSerialization

Bir Web API denetleyicisi bir kaynağı CLR türü olarak döndürürse, işlem hattı döndürülen değeri serileştirir ve HTTP yanıt gövdesine yazar.If a Web API controller returns a resource as CLR type, the pipeline serializes the return value and writes it into the HTTP response body.

Örneğin, aşağıdaki denetleyici eylemini göz önünde bulundurun:For example, consider the following controller action:

public Product GetProduct(int id)
{
    var item = _products.FirstOrDefault(p => p.ID == id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item; 
}

İstemci şu HTTP isteğini gönderebilir:A client might send this HTTP request:

GET http://localhost.:21069/api/products/1 HTTP/1.1
Host: localhost.:21069
Accept: application/json, text/javascript, */*; q=0.01

Yanıt olarak, sunucunun şunları gönderebileceğini:In response, the server might send:

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}

Bu örnekte, istemci JSON, JavaScript veya "her şeyi" (*/*) istedi.In this example, the client requested either JSON, Javascript, or "anything" (*/*). Sunucu, Product nesnesinin JSON temsili ile yanıt verdi.The server responded with a JSON representation of the Product object. Yanıttaki Içerik türü üstbilgisinin "Application/JSON"olarak ayarlandığını unutmayın.Notice that the Content-Type header in the response is set to "application/json".

Bir denetleyici, bir HttpResponseMessage nesnesi de döndürebilir.A controller can also return an HttpResponseMessage object. Yanıt gövdesi için bir CLR nesnesi belirtmek üzere Createres, Extension metodunu çağırın:To specify a CLR object for the response body, call the CreateResponse extension method:

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

Bu seçenek, yanıtın ayrıntıları üzerinde daha fazla denetim sağlar.This option gives you more control over the details of the response. Durum kodunu ayarlayabilir, HTTP üst bilgileri ekleyebilir ve benzeri bir durumla devam edebilirsiniz.You can set the status code, add HTTP headers, and so forth.

Kaynağı serileştiren nesneye medya biçimlendiricidenir.The object that serializes the resource is called a media formatter. Medya formatlayıcıları, MediaTypeFormatter sınıfından türetilir.Media formatters derive from the MediaTypeFormatter class. Web API 'si, XML ve JSON için medya biçimleri sağlar ve diğer medya türlerini desteklemek için özel biçimleri de oluşturabilirsiniz.Web API provides media formatters for XML and JSON, and you can create custom formatters to support other media types. Özel bir biçimlendirici yazma hakkında daha fazla bilgi için bkz. medya biçimleri.For information about writing a custom formatter, see Media Formatters.

Içerik anlaşması nasıl kullanılır?How Content Negotiation Works

İlk olarak, işlem hattı HttpConfiguration nesnesinden ıtentnegotiator hizmetini alır.First, the pipeline gets the IContentNegotiator service from the HttpConfiguration object. Ayrıca, HttpConfiguration. biçimlendiricileri koleksiyonundan medya formatlayıcıları listesini alır.It also gets the list of media formatters from the HttpConfiguration.Formatters collection.

Sonra, işlem hattı ıditentnegotiator. Negotiateçağırır, geçirme:Next, the pipeline calls IContentNegotiator.Negotiate, passing in:

  • Seri hale getirilecek nesnenin türüThe type of object to serialize
  • Medya formatlayıcıları koleksiyonuThe collection of media formatters
  • HTTP isteğiThe HTTP request

Negotiate yöntemi iki bilgi parçası döndürür:The Negotiate method returns two pieces of information:

  • Kullanılacak biçimlendiriciWhich formatter to use
  • Yanıt için medya türüThe media type for the response

Bir biçimlendirici bulunmazsa, Negotiate yöntemi nullDEĞERINI döndürür ve istemci http hatası 406 (kabul edilemez) alır.If no formatter is found, the Negotiate method returns null, and the client receives HTTP error 406 (Not Acceptable).

Aşağıdaki kod, bir denetleyicinin içerik anlaşmasını doğrudan nasıl çağırabileceği gösterilmektedir:The following code shows how a controller can directly invoke content negotiation:

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

Bu kod, işlem hattının otomatik olarak ne olduğuna eşdeğerdir.This code is equivalent to the what the pipeline does automatically.

Varsayılan Içerik NegotiatorDefault Content Negotiator

Defaultcontentnegotiator sınıfı, ıtenttrnegotiator'ın varsayılan uygulamasını sağlar.The DefaultContentNegotiator class provides the default implementation of IContentNegotiator. Bir biçimlendirici seçmek için birkaç ölçüt kullanır.It uses several criteria to select a formatter.

İlk olarak, biçimlendirici türü seri hale getirmek için gereklidir.First, the formatter must be able to serialize the type. Bu, MediaTypeFormatter. CanWriteTypeçağırarak doğrulanır.This is verified by calling MediaTypeFormatter.CanWriteType.

Ardından, içerik Negotiator her bir biçimlendirici üzerinde bakar ve HTTP isteğiyle ne kadar iyi eşleşme olduğunu değerlendirir.Next, the content negotiator looks at each formatter and evaluates how well it matches the HTTP request. Eşleşmeyi değerlendirmek için, içerik Negotiator, biçimlendirici üzerinde iki şeyi arar:To evaluate the match, the content negotiator looks at two things on the formatter:

  • Desteklenen medya türlerinin bir listesini içeren Supportedmediatypes koleksiyonu.The SupportedMediaTypes collection, which contains a list of supported media types. İçerik Negotiator, istek kabul üstbilgisiyle bu listeyi eşleştirmeye çalışır.The content negotiator tries to match this list against the request Accept header. Accept üst bilgisinin aralıklar içerebileceğini unutmayın.Note that the Accept header can include ranges. Örneğin, "metin/düz" metin/* veya */*için bir eşleşmedir.For example, "text/plain" is a match for text/* or */*.
  • MediaTypeMapping nesnelerinin bir listesini Içeren mediatypemappings koleksiyonu.The MediaTypeMappings collection, which contains a list of MediaTypeMapping objects. MediaTypeMapping sınıfı, medya türleriyle http isteklerini eşleştirmek için genel bir yol sağlar.The MediaTypeMapping class provides a generic way to match HTTP requests with media types. Örneğin, özel bir HTTP üst bilgisini belirli bir medya türüyle eşleyebilir.For example, it could map a custom HTTP header to a particular media type.

Birden çok eşleşme varsa, en yüksek kalite faktörüyle eşleşme kazanır.If there are multiple matches, the match with the highest quality factor wins. Örneğin:For example:

Accept: application/json, application/xml; q=0.9, */*; q=0.1

Bu örnekte, Application/JSON 'ın kapsanan bir kalite faktörü 1,0, bu nedenle application/xml üzerinden tercih edilir.In this example, application/json has an implied quality factor of 1.0, so it is preferred over application/xml.

Hiçbir eşleşme bulunmazsa, içerik Negotiator, varsa istek gövdesinin medya türüyle eşleştirmeye çalışır.If no matches are found, the content negotiator tries to match on the media type of the request body, if any. Örneğin, istek JSON verisi içeriyorsa, içerik Negotiator bir JSON biçimlendiricisi arar.For example, if the request contains JSON data, the content negotiator looks for a JSON formatter.

Hala eşleşme yoksa, Negotiator, türü seri hale getirmek için yalnızca ilk biçimlendirici seçer.If there are still no matches, the content negotiator simply picks the first formatter that can serialize the type.

Bir karakter kodlaması seçmeSelecting a Character Encoding

Bir biçimlendirici seçildikten sonra, içerik Negotiator, biçimlendirici üzerindeki Supportedencoular özelliğine bakarak en iyi karakter kodlamasını seçer ve istekteki Accept-Charset üstbilgisine (varsa) karşılık gelir.After a formatter is selected, the content negotiator chooses the best character encoding by looking at the SupportedEncodings property on the formatter, and matching it against the Accept-Charset header in the request (if any).