Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este tutorial mostra como suportar formatos de media adicionais na ASP.NET Web API.
Tipos de Media na Internet
Um tipo de media, também chamado de tipo MIME, identifica o formato de um dado. Em HTTP, os tipos de media descrevem o formato do corpo da mensagem. Um tipo de media consiste em duas cadeias, um tipo e um subtipo. Por exemplo:
- texto/html
- tipo de ficheiro imagem/png
- application/json
Quando uma mensagem HTTP contém um corpo-entidade, o cabeçalho Content-Type especifica o formato do corpo da mensagem. Isto indica ao destinatário como analisar o conteúdo do corpo da mensagem.
Por exemplo, se uma resposta HTTP contiver uma imagem PNG, a resposta pode ter os seguintes cabeçalhos.
HTTP/1.1 200 OK
Content-Length: 95267
Content-Type: image/png
Quando o cliente envia uma mensagem de pedido, pode incluir um cabeçalho Aceitar. O cabeçalho Aceitar indica ao servidor que tipo(s) de media o cliente quer do servidor. Por exemplo:
Accept: text/html,application/xhtml+xml,application/xml
Este cabeçalho indica ao servidor que o cliente quer HTML, XHTML ou XML.
O tipo de media determina como a Web API serializa e desserializa o corpo da mensagem HTTP. A Web API tem suporte incorporado para dados XML, JSON, BSON e form-urlencoded, e pode suportar tipos de mídia adicionais escrevendo um formatador de mídia.
Para criar um formatador de media, derive de uma destas classes:
- MediaTypeFormatter. Esta classe utiliza métodos assíncronos de leitura e escrita.
- BufferedMediaTypeFormatter. Esta classe deriva do MediaTypeFormatter mas utiliza métodos síncronos de leitura/escrita.
Derivar de BufferedMediaTypeFormatter é mais simples, porque não existe um código assíncrono, mas também significa que a chamada pode ser bloqueada durante operações de I/O.
Exemplo: Criação de um Formatador de Media CSV
O exemplo seguinte mostra um formatador de tipo media que pode serializar um objeto Product para um formato de valores separados por vírgulas (CSV). Este exemplo utiliza o tipo de produto definido no tutorial Criar uma API Web que Suporta Operações CRUD. Aqui está a definição do objeto Produto:
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; }
}
}
Para implementar um formatador CSV, defina uma classe que derive de BufferedMediaTypeFormatter:
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
{
}
}
No construtor, adicione os tipos de mídia que o formatador suporta. Neste exemplo, o formatador suporta um único tipo de media, "texto/csv":
public ProductCsvFormatter()
{
// Add the supported media type.
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
}
Substitua o método CanWriteType para indicar que tipos o formatador pode serializar:
public override bool CanWriteType(System.Type type)
{
if (type == typeof(Product))
{
return true;
}
else
{
Type enumerableType = typeof(IEnumerable<Product>);
return enumerableType.IsAssignableFrom(type);
}
}
Neste exemplo, o formatador pode serializar objetos individuais Product , bem como coleções de objetos Product .
De forma semelhante, substitua o método CanReadType para indicar que tipos o formatador pode desserializar. Neste exemplo, o formador não suporta desserialização, pelo que o método simplesmente retorna falso.
public override bool CanReadType(Type type)
{
return false;
}
Por fim, substitua o método WriteToStream . Este método serializa um tipo ao escrevê-lo num fluxo. Se o seu formatador suportar desserialização, também substitua o método ReadFromStream.
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;
}
Adicionar um Formateador de Mídia ao Pipeline da Web API
Para adicionar um formateador de tipo de media ao pipeline da API Web, use a propriedade Formatter no objeto HttpConfiguration .
public static void ConfigureApis(HttpConfiguration config)
{
config.Formatters.Add(new ProductCsvFormatter());
}
Codificações de Caracteres
Opcionalmente, um formatador de media pode suportar múltiplas codificações de caracteres, como UTF-8 ou ISO 8859-1.
No construtor, adicione um ou mais tipos System.Text.Encoding à coleção SupportedEncodings . Coloque a codificação padrão em primeiro lugar.
public ProductCsvFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
// New code:
SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
SupportedEncodings.Add(Encoding.GetEncoding("iso-8859-1"));
}
Nos métodos WriteToStream e ReadFromStream , chame MediaTypeFormatter.SelectCharacterEncoding para selecionar a codificação de caracteres preferida. Este método compara os cabeçalhos dos pedidos com a lista de codificações suportadas. Use a codificação devolvida quando ler ou escrever a partir do fluxo:
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)
}
}