使用 WCF REST 编程模型创建接受任意数据的服务

有时,开发人员必须完全控制从服务操作返回数据的方式。 当服务操作必须以 WCF 不支持的格式返回数据时,就需要这样做。 本主题讨论如何使用 WCF REST 编程模型创建接收任意数据的服务。

实现服务协定

  1. 定义服务协定。 接收任意数据的操作必须具有一个类型为 Stream 的参数。 此外,此参数必须为传入请求正文的唯一参数。 本示例中介绍的操作还采用一个文件名参数。 此参数在请求的 URL 中传递。 通过在 WebInvokeAttribute 中指定 UriTemplate 可以指定在 URL 中传递参数。 在这种情况下,用于调用此方法的 URI 以“UploadFile/Some-Filename”结尾。 该 URI 模板的“{filename}”部分指定操作的文件名参数在用于调用该操作的 URI 中进行传递。

     [ServiceContract]
    public interface IReceiveData
    {
        [WebInvoke(UriTemplate = "UploadFile/{fileName}")]
        void UploadFile(string fileName, Stream fileContents);
    }
    
  2. 实现服务协定。 该协定只有一个方法 UploadFile,该方法以流的形式接收包含任意数据的文件。 操作读取该数据流,同时对所读字节数进行计数,然后显示文件名和所读字节数。

    public class RawDataService : IReceiveData
    {
        public void UploadFile(string fileName, Stream fileContents)
        {
            byte[] buffer = new byte[10000];
            int bytesRead, totalBytesRead = 0;
            do
            {
                bytesRead = fileContents.Read(buffer, 0, buffer.Length);
                totalBytesRead += bytesRead;
            } while (bytesRead > 0);
            Console.WriteLine("Service: Received file {0} with {1} bytes", fileName, totalBytesRead);
        }
    }
    

承载服务

  1. 创建用于承载服务的控制台应用程序。

    class Program
    {
       static void Main(string[] args)
       {
       }
    }
    
    
  2. Main 方法中创建一个变量以保存服务的基址。

    string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
    
  3. 创建服务的一个 ServiceHost 实例,该实例指定服务类和基址。

    ServiceHost host = new ServiceHost(typeof(RawDataService), new Uri(baseAddress));
    
  4. 添加一个指定协定、WebHttpBindingWebHttpBehavior 的终结点。

    host.AddServiceEndpoint(typeof(IReceiveData), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
    
  5. 打开服务主机。 现在服务已准备好接收请求。

    host.Open();
    Console.WriteLine("Host opened");
    

以编程方式调用服务

  1. 使用用于调用服务的 URI 创建一个 HttpWebRequest 在此代码中,基址与 “/UploadFile/Text” 组合在一起。 URI 的 “UploadFile” 部分指定要调用的操作。 URI 的 “Test.txt” 部分指定要传递给 UploadFile 操作的文件名参数。 这两项都映射到应用于操作协定的 UriTemplate

    HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/UploadFile/Test.txt");
    
    
  2. HttpWebRequestMethod 属性设置为 POST,并将 ContentType 属性设置为 “text/plain” 这会告知服务代码正在发送数据,且数据的格式为纯文本。

    req.Method = "POST";
    req.ContentType = "text/plain";
    
  3. 调用 GetRequestStream() 以获取请求流,创建要发送的数据,将该数据写入请求流,然后关闭请求流。

    Stream reqStream = req.GetRequestStream();
    byte[] fileToSend = new byte[12345];
    for (int i = 0; i < fileToSend.Length; i++)
       {
           fileToSend[i] = (byte)('a' + (i % 26));
       }
    reqStream.Write(fileToSend, 0, fileToSend.Length);
    reqStream.Close();
    
  4. 通过调用 GetResponse() 从服务获取响应,然后向控制台显示响应数据。

    HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
    Console.WriteLine("Client: Receive Response HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
    
    
  5. 关闭服务主机。

    host.Close();
    

下面列出了此示例的完整代码。

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.Net;


namespace ReceiveRawData
{
    [ServiceContract]
    public interface IReceiveData
    {
        [WebInvoke(UriTemplate = "UploadFile/{fileName}")]
        void UploadFile(string fileName, Stream fileContents);
    }
    public class RawDataService : IReceiveData
    {
        public void UploadFile(string fileName, Stream fileContents)
        {
            byte[] buffer = new byte[10000];
            int bytesRead, totalBytesRead = 0;
            do
            {
                bytesRead = fileContents.Read(buffer, 0, buffer.Length);
                totalBytesRead += bytesRead;
            } while (bytesRead > 0);
            Console.WriteLine("Service: Received file {0} with {1} bytes", fileName, totalBytesRead);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(RawDataService), new Uri(baseAddress));
            host.AddServiceEndpoint(typeof(IReceiveData), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
            host.Open();
            Console.WriteLine("Host opened");

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/UploadFile/Test.txt");
            req.Method = "POST";
            req.ContentType = "text/plain";
            Stream reqStream = req.GetRequestStream();
            byte[] fileToSend = new byte[12345];
            for (int i = 0; i < fileToSend.Length; i++)
            {
                fileToSend[i] = (byte)('a' + (i % 26));
            }
            reqStream.Write(fileToSend, 0, fileToSend.Length);
            reqStream.Close();
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Console.WriteLine("Client: Receive Response HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
            host.Close();

        }
    }
}

  • 编译该代码时,请引用 System.ServiceModel.dll 和 System.ServiceModel.Web.dll

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值