Como: criar um serviço que retorna dados arbitrários usando o modelo de programação HTTP Web do WCF

Às vezes, os desenvolvedores precisam ter controle total de como os dados são retornados de uma operação de serviço. Este é o caso quando uma operação de serviço deve retornar dados em um formato não suportado pelo WCF. Este tópico discute o uso do WCF WEB HTTP Programming Model para criar tal serviço. Este serviço tem uma operação que retorna um fluxo.

Para implementar o contrato de serviço

  1. Defina o contrato de serviço. O contrato é chamado IImageServer e tem um método chamado GetImage que retorna um Stream.

    [ServiceContract]  
        public interface IImageServer  
        {  
            [WebGet]  
            Stream GetImage(int width, int height);  
        }  
    

    Como o método retorna um Stream, o WCF pressupõe que a operação tem controle total sobre os bytes retornados da operação de serviço e não aplica formatação aos dados retornados.

  2. Implemente o contrato de serviço. O contrato tem apenas uma operação (GetImage). Esse método gera um bitmap e o salva em um MemoryStream no formato .jpg. A operação então retorna esse fluxo para o chamador.

    public class Service : IImageServer
    {
        public Stream GetImage(int width, int height)
        {
            Bitmap bitmap = new Bitmap(width, height);
            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    bitmap.SetPixel(i, j, (Math.Abs(i - j) < 2) ? Color.Blue : Color.Yellow);
                }
            }
            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            ms.Position = 0;
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
            return ms;
        }
    }
    

    Observe a penúltima linha de código: WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";

    Isso define o cabeçalho do tipo de conteúdo como "image/jpeg". Embora este exemplo mostre como retornar um arquivo .jpg, ele pode ser modificado para retornar qualquer tipo de dado necessário, em qualquer formato. A operação deve recuperar ou gerar os dados e, em seguida, gravá-los em um fluxo.

Para hospedar o serviço

  1. Crie um projeto de aplicativo de console para hospedar o serviço.

    class Program  
    {  
        static void Main(string[] args)  
        {  
        }
    }  
    
  2. Crie uma variável para manter o endereço básico do serviço dentro do método Main.

    string baseAddress = "http://" + Environment.MachineName + ":8000/Service";  
    
  3. Crie uma instância ServiceHost para o serviço especificando a classe de serviço e o endereço base.

    ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));  
    
  4. Adicione um endpoint usando o WebHttpBinding e o WebHttpBehavior.

    host.AddServiceEndpoint(typeof(IImageServer), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());  
    
  5. Abra o host do serviço.

    host.Open();  
    
  6. Aguarde até que o usuário pressione Enter para encerrar o serviço.

    Console.WriteLine("Service is running");  
    Console.Write("Press ENTER to close the host");  
    Console.ReadLine();  
    host.Close();  
    

Para chamar o serviço bruto usando um navegador

  1. Execute o serviço, você deverá ver a seguinte saída do serviço: Service is running Press ENTER to close the host

  2. Abra um navegador da Web e insira http://localhost:8000/Service/GetImage?width=50&height=40. Você verá um retângulo amarelo com uma linha diagonal azul no centro.

Exemplo

A seguir está uma lista completa do código para este tópico.

using System;  
using System.Collections.Generic;  
using System.Text;  
using System.ServiceModel;  
using System.ServiceModel.Web;  
using System.ServiceModel.Description;  
using System.IO;  
using System.Drawing;  
  
namespace RawImageService  
{  
    // Define the service contract  
    [ServiceContract]  
    public interface IImageServer  
    {  
        [WebGet]  
        Stream GetImage(int width, int height);  
    }  
  
    // implement the service contract  
    public class Service : IImageServer  
    {  
        public Stream GetImage(int width, int height)  
        {  
            // Although this method returns a jpeg, it can be  
            // modified to return any data you want within the stream  
            Bitmap bitmap = new Bitmap(width, height);  
            for (int i = 0; i < bitmap.Width; i++)  
            {  
                for (int j = 0; j < bitmap.Height; j++)  
                {  
                    bitmap.SetPixel(i, j, (Math.Abs(i - j) < 2) ? Color.Blue : Color.Yellow);  
                }  
            }  
            MemoryStream ms = new MemoryStream();  
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);  
            ms.Position = 0;  
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";  
            return ms;  
        }  
    }  
  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";  
            ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));  
            host.AddServiceEndpoint(typeof(IImageServer), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());  
            host.Open();  
            Console.WriteLine("Service is running");  
            Console.Write("Press ENTER to close the host");  
            Console.ReadLine();  
            host.Close();  
  
        }  
    }  
}  

Compilando o código

Ao compilar a referência de código de exemplo System.ServiceModel.dll e System.ServiceModel.Web.dll.

Confira também