在Web Service中傳送Dictionary
有個需求,想在Web Service中傳遞Dictionary<string, string>參數,例如:
[WebMethod]
public Dictionary<string, string> Process(Dictionary<string, string> dct)
{
//Do something on the Dictionary
//... blah blah blah ....
return dct;
}
天不從人願,以上的寫法會產生Web Service不支援IDictionary的錯誤:
The type System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] is not supported because it implements IDictionary.
既是IDictionary的原罪,就算是換用Hashtable、ListDictionary應該也是同樣結果,測試之下果然無一倖免。
Google發現討論區有篇來自MS RD的留言,算是證實這是先天限制:
ASMX web services do not support types that implement IDictionary since V1. This is by design and was initially done since key-value constraints could not be appropriately expressed in schema.
來源: http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/thread/d7cb8844-6774-4a98-8aa3-85e445af4867/
既然是By Design,就只有繞道而行。Survey了一下,找到一些建議做法:
- 改用XML
- 使用DataSet
- 另外自訂Class作為參數
- 以DictionaryEntry[]瓜代之
評估了一下,我原本想要借重的就是Dictionary Key/Value的單純資料結構,XML為開放格式不易限制成Key/Value的形式;小小需求動用到DataSet略嫌笨重;自訂Class在編譯時期就要確定Key的種類,不符本案例的前題。看來DictionaryEntry[]較合需求,因此我試寫如下: (剛好Dictionary與DirectionaryEntry的雙向轉換都有示範到)
[WebMethod]
public DictionaryEntry[] Test(System.Collections.DictionaryEntry[] entries)
{
//用ListDictionary主要是為了稍後可以直接CopyTo轉DictionaryEntry[]
//若有效率或其他考量,可改用其他Collection Class
ListDictionary dct = new ListDictionary();
foreach (DictionaryEntry de in entries)
dct.Add(de.Key, de.Value);
//Do something on the Dictionary
//... blah blah blah ....
if (dct.Contains("Kuso"))
dct["Kuso"] = "殺很大";
DictionaryEntry[] result = new DictionaryEntry[dct.Count];
dct.CopyTo(result, 0);
return result;
}
呼叫端範例如下:
protected void Page_Load(object sender, EventArgs e)
{
localhost.AFAWebService aws = new localhost.AFAWebService();
aws.Credentials = CredentialCache.DefaultCredentials;
Dictionary<string, string> dct = new Dictionary<string, string>();
dct.Add("Kuso", "你不要走");
//DictionaryEntry在Web Service傳遞時會被當成自訂類別
//因此要用namespace.DictionaryEntry而非System.Collections.DictionaryEntry
List<localhost.DictionaryEntry> lst = new List<localhost.DictionaryEntry>();
foreach (string key in dct.Keys)
{
localhost.DictionaryEntry de = new localhost.DictionaryEntry();
de.Key = key;
de.Value = dct[key];
lst.Add(de);
}
localhost.DictionaryEntry[] result = aws.Test(lst.ToArray());
Dictionary<string, string> dctRes = new Dictionary<string, string>();
foreach (localhost.DictionaryEntry de in result)
dctRes.Add(de.Key.ToString(), de.Value.ToString());
Response.Write(dct["Kuso"] + "->" + dctRes["Kuso"]);
Response.End();
}
經過這番來回折騰,這方法看來也不怎麼簡潔。
於是,我又嘗試了Paul Welter的SerializableDictionary物件,做法上要在Web Service與Client端都Reference這個自訂物件,而且使用Visual Studio的Add Web Reference時,自動產生的Proxy Class宣告中SerializableDictionary會被當成DataSet而失敗,因此得改成手動產生Proxy Class後再將DataSet改回SerializableDictionary:
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'AfaWebServiceProxy.cs'.
用了SerializableDictionary後,程式碼簡化許多:
[WebMethod]
public SerializableDictionary<string, string> Test(
SerializableDictionary<string, string> dct)
{
if (dct.ContainsKey("Kuso"))
dct["Kuso"] = "殺很大";
return dct;
}
呼叫端也很單純:
protected void Page_Load(object sender, EventArgs e)
{
localhost.AFAWebService aws = new localhost.AFAWebService();
aws.Credentials = CredentialCache.DefaultCredentials;
SerializableDictionary<string, string> dct =
new SerializableDictionary<string, string>();
dct.Add("Kuso", "你不要走");
SerializableDictionary<string, string> dctRes = aws.Test(dct);
Response.Write(dct["Kuso"] + "->" + dctRes["Kuso"]);
Response.End();
}
但是,這個做法需要在Web Service與Client端加入自訂元件參照、Proxy Class需要手動增加或修改,還是有些許不便。這樣看來,DataSet或XML法雖有其他缺點,但內建支援的特點,在力求簡單的場合裡,倒也值得納入考量吧!
在Web Service中傳送Dictionary的更多相关文章
- 问题:不支持Dictionary;结果:在Web Service中傳送Dictionary
在Web Service中傳送Dictionary 有個需求,想在Web Service中傳遞Dictionary<string, string>參數,例如: 排版顯示純文字 [WebMe ...
- Web Service 中返回DataSet结果大小改进
http://www.cnblogs.com/scottckt/archive/2012/11/10/2764496.html Web Service 中返回DataSet结果方法: 1)直接返回Da ...
- Web Service 中返回DataSet结果的几种方法
Web Service 中返回DataSet结果的几种方法: 1)直接返回DataSet对象 特点:通常组件化的处理机制,不加任何修饰及处理: 优点:代码精减.易于处理,小数据量处理较快: ...
- ASP.NET Web Service中使用Session 及 Session丢失解决方法 续
原文:ASP.NET Web Service中使用Session 及 Session丢失解决方法 续 1.关于Session丢失问题的说明汇总,参考这里 2.在Web Servcie中使用Sessio ...
- 转-Web Service中三种发送接受协议SOAP、http get、http post
原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...
- 企业级SOA之路——在Web Service中使用HTTP和JMS
原文:http://www.tibco.com/resources/solutions/soa/enterprise_class_soa_wp.pdf 概述 IT业界在早期有一种误解,认为 ...
- Web Service中的几个重要术语
WSDL:web service definition language 直译:WebService定义语言 1.对应一种该类型的文件.WSDL 2.定义了Web Service的服务器与客户端应用交 ...
- Web Service中的XFire 传输List 自定义对象.
我把这个创建的步骤和代码的贴出来,. 首先新建一个工程,取名就随便点啦..MyWebService,然后复制jar包到lib目录下, 创建包,建立接口..写一个javaBean的类, 以下是一个简单的 ...
- WCF Service 转换为Web Service 中字段属性
1.新建WCF服务,服务中包含对象 2.部署WCF服务,并将其转换为应用程序 3.通过添加服务引用,使用WCF服务 4.调用对应的对象时需要对应的值设置为True. 参考:https://cloud. ...
随机推荐
- C++基础笔记(四)C++内存管理
析构函数 * 析构函数在对象所占用内存释放时调用,通常用来释放相关的资源 * 析构函数就是一个特殊的类成员函数,它是构造函数相反 构造函数:对象在分配内存之后,立即调用 析构函数:对象在内存被释放之前 ...
- flex4的s:states和mx:states的区别
http://help.adobe.com/en_US/Flex/4.0/UsingSDK/WS2db454920e96a9e51e63e3d11c0bf63611-7ffa.html#WS43468 ...
- java 13-2 Arrays工具类
1.Arrays:针对数组进行操作的工具类.比如说排序和查找. 1:public static String toString(int[] a) 把数组转成字符串 2:public static v ...
- java11-6 String类的其它功能
String类的其他功能: 替换功能: String replace(char old,char new) String replace(String old,String new) 去除字符串两空格 ...
- 【转】【Asp.Net】ASP.NET中自定义控件无法响应事件
在自定义服务器控件中增加事件处理程序,但代码运行时没有错误,按钮点击下去却没有反应.应该如何处理呢?(本例中,该自定义控件包括一个Button,和一个Label,我希望用户点击了这个Button后,改 ...
- VSFTPD配置TLS/SSL
今天在OSX上配置Coda2 + Xampp的时候,发现FTP老是不连接到服务器上面,导致每次更改了文件都需要使用scp命令上传到服务器.如果一个文件还好,文件和文件夹一多就得使用rp参数全部提交,再 ...
- Java 8新特性——default方法(defender方法)介绍
我们都知道在Java语言的接口中只能定义方法名,而不能包含方法的具体实现代码.接口中定义的方法必须在接口的非抽象子类中实现.下面就是关于接口的一个例子: 1 2 3 4 5 6 7 8 9 10 11 ...
- python爬虫中文网页cmd打印出错问题解决
问题描述 用python写爬虫,很多时候我们会先在cmd下先进行尝试. 运行爬虫之后,肯定的,我们想看看爬取的结果. 于是,我们print... 运气好的话,一切顺利.但这样的次数不多,更多地,我们会 ...
- Objective-c内存管理
cocoa中的内存管理机制 引用计数 每一个对象都拥有一个引用计数 当对象创建的时候,引用计数的值是1 当发生retain消息时,该对象的引用计数+1,该对象的引用计数为2 当向这个对象发送relea ...
- python数字图像处理(11):图像自动阈值分割
图像阈值分割是一种广泛应用的分割技术,利用图像中要提取的目标区域与其背景在灰度特性上的差异,把图像看作具有不同灰度级的两类区域(目标区域和背景区域)的组合,选取一个比较合理的阈值,以确定图像中每个像素 ...