[原]RESTful Web Service之以HTTP PUT方式调用WCF服务

昨天突然想到一个问题,在RESTful Web Service中,如何修改一个对象呢,怎么看都不像是通过把一个复杂对象分解为Uri的参数的形式来上传到服务器上的。又看了微软提供的WCF的示例代码《高级 Web 编程》,其中倒有一段代码貌似和我的需求一致:
代码
    [OperationContract]
    [WebInvoke(Method 
= "PUT", UriTemplate = "{id}")]
    Customer UpdateCustomer(
string id, Customer newCustomer);

这里从客户端传上来一个Customer类型的对象newCustomer,而不是完全把Customer分解成简单类型传上来。但是还是感觉这不是我想要的代码,因为这个Customer类型还是太“具体”,为每一个PUT动作都设计一个方法并不是我想要的。而且,如果离开了.NET平台,离开了DataContract,DataMember调用是不是会变的复杂呢(这个我现在也没有去研究,希望知道的兄弟指教一二),我心中希望的这种调用,最好就像Google Data API中的AtomEntry一样,使用一个AtomEntry.Update(),就可以把自已更新到服务器上去,而不是为每一个类型都去做自已的更新方法。既然Google能做到,那一定是实现的办法。

通过反复的查询MSDN,终于找到了一个可以被WCF当然数据契约接收的“通用”类型:

代码
[DataContractAttribute]
public abstract class SyndicationItemFormatter

很显然,这是一个抽象类,它的继承层次如下:

System.Object
    System.ServiceModel.Syndication.SyndicationItemFormatter
    System.ServiceModel.Syndication.Atom10ItemFormatter
    System.ServiceModel.Syndication.Rss20ItemFormatter

再进一步,又发现了下面的这个类型:

代码
public class Atom10ItemFormatter<TSyndicationItem> : Atom10ItemFormatter
where TSyndicationItem : new(), SyndicationItem

MSDN解释如下:

一个用于在 SyndicationItem派生类与 Atom 1.0 格式之间来回序列化的类。

备注:

使用此类可以序列化SyndicationItem 派生类的实例,以及从包含 Atom 1.0 项的 XML 文档创建SyndicationFeed 派生类的实例。如果必须序列化SyndicationItem实例,请改用Atom10ItemFormatter格式化程序。

如果把Atom10ItemFormatter<TSyndicationItem>做为WCF服务方法的参数类型,再使用HTTP 的PUT方式把数据推到WCF服务的方法上,这个Atom10ItemFormatter<TSyndicationItem>应该会将推进来的XML数据自动转换成SyndicationItem对象吧,试试看:

随例建一个Syndication Service项目,然后将IFeed1.cs修改为如下代码所示:

代码
    [ServiceContract]
    [ServiceKnownType(
typeof(Atom10FeedFormatter))]
    [ServiceKnownType(
typeof(Rss20FeedFormatter))]
    
public interface IFeed1
    {

        [OperationContract]
        [WebGet(UriTemplate 
= "get", BodyStyle = WebMessageBodyStyle.Bare)]
        SyndicationFeedFormatter CreateFeed();

        [OperationContract]
        [WebInvoke(Method 
= "PUT", RequestFormat = WebMessageFormat.Xml, UriTemplate = "up")]
        
void Update(Atom10ItemFormatter<SyndicationItem> item);
    }

接下来再修改Feed1.cs,为其添加Update方法:

代码
        public void Update(Atom10ItemFormatter<SyndicationItem> item)
        {
            
using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\a.txt"true))
            {
                file.WriteLine(item.Item.Title.Text);
            } 
        }

为了观察是否得到了客户端PUT来的数据,我做了一个简单的Log,把PUT来的SyndicationItem的Title写入到一个文本文件。

有了服务端,还得有个客户端,新建一个控制台应用程序,将main.cs修改为如下所示:

代码
        static void Main(string[] args)
        {
            HttpWebRequest req 
= (HttpWebRequest)WebRequest.Create("http://localhost:8731/Design_Time_Addresses/RESTfulTest/Feed1/up");
            req.Method 
= "PUT";
            SyndicationItem item 
= new SyndicationItem("think8848""Item Content"new Uri("http://Item/Alternate/Link"), "itemID", DateTimeOffset.Now);
            MemoryStream ms 
= new MemoryStream();
            XmlWriter writer 
= XmlWriter.Create(ms);
            item.SaveAsAtom10(writer);
            writer.Close();
            req.ContentLength 
= ms.Length;
            req.ContentType 
= "text/html";
            Stream sw 
= req.GetRequestStream();
            sw.Write(ms.ToArray(), 
0, (int)ms.Length);
            WebResponse resp 
= req.GetResponse();
            Stream s 
= resp.GetResponseStream();
            StreamReader sr 
= new StreamReader(s);
            Console.WriteLine(sr.ReadToEnd());
            resp.Close();
            Console.ReadLine();
        

Go!Go!Go! Start new instance

观察下c:\a.txt中有没有东西:

示例代码下载

参考文章:http://social.msdn.microsoft.com/Forums/en/wcf/thread/c2f7a08e-3af8-4ea6-8eab-03eb07951de4

推荐博客:http://www.robbagby.com/blog

原文地址:https://www.cnblogs.com/think8848/p/1614520.html