ASP.NET Web API 2'deki Medya Biçimlendiricileri

Bu öğreticide, ASP.NET Web API'sinde ek medya biçimlerini destekleme gösterilmektedir.

İnternet Medya Türleri

MIME türü olarak da adlandırılan medya türü, bir veri parçasının biçimini tanımlar. HTTP'de, medya türleri ileti gövdesinin biçimini açıklar. Medya türü iki dizeden oluşur: bir tür ve bir alt tür. Örnek:

  • text/html
  • image/png
  • uygulama/json

HTTP iletisi bir varlık gövdesi içerdiğinde, content-Type üst bilgisi ileti gövdesinin biçimini belirtir. Bu, alıcıya ileti gövdesinin içeriğini nasıl ayrıştıracaklarını bildirir.

Örneğin, BIR HTTP yanıtı png görüntüsü içeriyorsa, yanıt aşağıdaki üst bilgileri içerebilir.

HTTP/1.1 200 OK
Content-Length: 95267
Content-Type: image/png

İstemci bir istek iletisi gönderdiğinde Accept üst bilgisi içerebilir. Accept üst bilgisi, sunucuya istemcinin sunucudan hangi medya türlerini istediğini bildirir. Örnek:

Accept: text/html,application/xhtml+xml,application/xml

Bu üst bilgi sunucuya istemcinin HTML, XHTML veya XML istediğini bildirir.

Medya türü, Web API'sinin HTTP ileti gövdesini nasıl seri hale getireceğini ve seri durumdan çıkardığını belirler. Web API'si XML, JSON, BSON ve form urlencoded verileri için yerleşik desteğe sahiptir ve bir medya biçimlendirici yazarak ek medya türlerini destekleyebilirsiniz.

Medya biçimlendirici oluşturmak için şu sınıflardan birinden türetin:

Zaman uyumsuz kod olmadığından BufferedMediaTypeFormatter'dan türetilmesi daha basittir, ancak çağıran iş parçacığının G/Ç sırasında engelleyebileceği anlamına da gelir.

Örnek: CSV Medya Biçimlendiricisi Oluşturma

Aşağıdaki örnekte, product nesnesini virgülle ayrılmış değerler (CSV) biçiminde seri hale getirebilen bir medya türü biçimlendirici gösterilmektedir. Bu örnekte CRUD İşlemlerini Destekleyen Bir Web API'sini Oluşturma öğreticisinde tanımlanan Ürün türü kullanılır. Product nesnesinin tanımı aşağıdadır:

namespace ProductStore.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

CSV biçimlendirici uygulamak için BufferedMediaTypeFormatter'dan türetilen bir sınıf tanımlayın:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using ProductStore.Models;

namespace ProductStore.Formatters
{
    public class ProductCsvFormatter : BufferedMediaTypeFormatter
    {
    }
}

Oluşturucuda, biçimlendiricinin desteklediği medya türlerini ekleyin. Bu örnekte, biçimlendirici "text/csv" adlı tek bir medya türünü destekler:

public ProductCsvFormatter()
{
    // Add the supported media type.
    SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
}

Biçimlendiricinin hangi türleri seri hale getirebileceğini belirtmek için CanWriteType yöntemini geçersiz kılın:

public override bool CanWriteType(System.Type type)
{
    if (type == typeof(Product))
    {
        return true;
    }
    else
    {
        Type enumerableType = typeof(IEnumerable<Product>);
        return enumerableType.IsAssignableFrom(type);
    }
}

Bu örnekte, biçimlendirici hem tek nesneleri Product hem de nesne koleksiyonlarını Product seri hale getirebilir.

Benzer şekilde, biçimlendiricinin seri durumdan çıkarabileceği türleri belirtmek için CanReadType yöntemini geçersiz kılın. Bu örnekte, biçimlendirici seri durumdan çıkarma işlemini desteklemez, bu nedenle yöntem yalnızca false döndürür.

public override bool CanReadType(Type type)
{
    return false;
}

Son olarak WriteToStream yöntemini geçersiz kılın. Bu yöntem bir akışa yazarak bir türü serileştirir. Biçimlendiriciniz seri durumdan çıkarmayı destekliyorsa ReadFromStream yöntemini de geçersiz kılın.

public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
    using (var writer = new StreamWriter(writeStream))
    {
        var products = value as IEnumerable<Product>;
        if (products != null)
        {
            foreach (var product in products)
            {
                WriteItem(product, writer);
            }
        }
        else
        {
            var singleProduct = value as Product;
            if (singleProduct == null)
            {
                throw new InvalidOperationException("Cannot serialize type");
            }
            WriteItem(singleProduct, writer);
        }
    }
}

// Helper methods for serializing Products to CSV format. 
private void WriteItem(Product product, StreamWriter writer)
{
    writer.WriteLine("{0},{1},{2},{3}", Escape(product.Id),
        Escape(product.Name), Escape(product.Category), Escape(product.Price));
}

static char[] _specialChars = new char[] { ',', '\n', '\r', '"' };

private string Escape(object o)
{
    if (o == null)
    {
        return "";
    }
    string field = o.ToString();
    if (field.IndexOfAny(_specialChars) != -1)
    {
        // Delimit the entire field with quotes and replace embedded quotes with "".
        return String.Format("\"{0}\"", field.Replace("\"", "\"\""));
    }
    else return field;
}

Web API İşlem Hattına Medya Biçimlendirici Ekleme

Web API işlem hattına medya türü biçimlendirici eklemek için HttpConfiguration nesnesinde Formatters özelliğini kullanın.

public static void ConfigureApis(HttpConfiguration config)
{
    config.Formatters.Add(new ProductCsvFormatter()); 
}

Karakter Kodlamaları

İsteğe bağlı olarak, bir medya biçimlendirici UTF-8 veya ISO 8859-1 gibi birden çok karakter kodlamayı destekleyebilir.

Oluşturucuda SupportedEncodings koleksiyonuna bir veya daha fazla System.Text.Encoding türü ekleyin. İlk olarak varsayılan kodlamayı koyun.

public ProductCsvFormatter()
{
    SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));

    // New code:
    SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
    SupportedEncodings.Add(Encoding.GetEncoding("iso-8859-1"));
}

WriteToStream ve ReadFromStream yöntemlerinde, tercih edilen karakter kodlamasını seçmek için MediaTypeFormatter.SelectCharacterEncoding öğesini çağırın. Bu yöntem, istek üst bilgilerini desteklenen kodlamalar listesiyle eşleştirir. Akıştan okurken veya yazarken döndürülen Kodlamayı kullanın:

public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
    Encoding effectiveEncoding = SelectCharacterEncoding(content.Headers);

    using (var writer = new StreamWriter(writeStream, effectiveEncoding))
    {
        // Write the object (code not shown)
    }
}