### 用 ASP.NET 开发 Web 服务的五则技巧

一、禁用HTTP POST/GET协议
除非另外指定，否则，.NET将试图把Web服务绑定到三种协议：HTTP/POST、HTTP/GET和SOAP。之所以说“试图”，是因为依赖于服务的参数和返回类型，HTTP/GET协议可能不可用。.NET生成的WSDL文件将自动包含绑定这三种协议的指令，客户程序可以自由选择使用哪种协议与服务通信。
只要在Web.config文件中加入下列内容，就可以方便地删除对HTTP/POST和HTTP/GET协议的绑定：

<webservices> <protocols> <remove name="HttpPost" /> <remove name="HttpGet" /> </protocols>

</webservices>

为什么要避免通过HTTP/POST和HTTP/GET协议引出Web服务呢？主要的两个原因是安全和互操作性。HTTP/GET的安全性不如SOAP，而且由于HTTP/GET常见于Web链接，怀有恶意的人可能利用它实施欺骗，使别人在不知不觉中用自己的安全标识调用Web服务，却还以为自己在点击Web链接。
就互操作性而言，SOAP是广泛应用的Web服务通信标准，而HTTP/GET和HTTP/POST不是。因此，对于.NET生成的WSDL文档中默认包含的HTTP/GET和HTTP/POST绑定，许多自动生成代理服务器的工具不会理解。因此，如果你的Web服务不是非绑定到HTTP/GET和HTTP/POST协议不可，最好取消这两种绑定。
二、用tcpTrace查看SOAP请求/应答消息
对于开发Web服务应用的人来说，调试可能是件异乎寻常的难事，因为无论是.NET SDK还是VS.NET，都没有提供工具来查看客户端和服务器之间的SOAP消息。
如果.NET和非.NET的客户端、服务器端的交互过程出现了问题，要想找出问题的根源，拥有查看SOAP消息的能力就尤为重要，因为这类问题往往与SOAP消息的格式有关（例如，“消息中包含了SOAPAction 吗？”）。
tcpTrace（www.pocketsoap.com/tcptrace）是一个查看这类消息交换过程的优秀工具，它通过设置一个客户端和服务器端之间的隧道工作。启动tcpTrace时，它会要求输入目标URL和端口号，以及tcpTrace监听的本地端口号。这样，你就可以通过设置代理stub的Url属性，把stub指向这个本地端口（例如，localhost:8080）。tcpTrace能够记录所有的请求和应答HTTP消息。
tcpTrace的一个局限是，它在消息流程中所处的位置决定了它不能用来查看通过SSL发送的消息。如果你要查看通过SSL发送的SOAP消息，只能编写一个定制的ISAPI过滤器。
三、简化接口设计
在众多有关n-层应用设计的论述中，简化接口设计这一设计要诀可以说是随处可见。但是，对于Web服务这样的分布式计算环境，简化接口设计的重要性更加突出。
在设计分布式应用时，出于性能和可伸缩性的考虑，应当保证客户端和服务器端之间的调用尽可能地少。减少网络调用不仅有利于减少通信开销（如果只用一个SOAP消息可以达到目标，就绝对不要发三个消息），降低网络流量，而且提高了应用的性能。显然，这一切都是开发者梦寐以求的目标。那么简化的接口到底有何特征呢？
首先来看一个复杂接口的例子：

namespace ChattyService { public class ChattyService : WebService { private string username; private string password; public string Username {

[WebMethod]

set {

username = Username;

} }

public string Password {

[WebMethod]

set {

password = Password;

} }

[WebMethod]

public bool Logon() {

// 验证身份

return true;

}

}

}

在这个例子中，username和password是两个属性，调用logon()方法之前首先必须设置这两个属性。有一个问题光看这段代码不太容易注意到，这就是username和password都作为Web方法引出。这就是说，每次对属性的get/set操作都会导致一个对服务的调用。
按照简化接口设计的要求，改进后的代码如下：

namespace ChattyService { public class ChattyService : WebService { [WebMethod] public bool Logon(string Username, string Password) { // 验证身份

return true;

}

}

}

现在，username和password成了logon()方法的参数。修改之后的代码的优点在于，它把登录操作对服务器的三次调用降低到了一次。另一方面，如果参数的个数太多，这个方法可能看起来很不像样。这时，可能要把方法的参数整理成几个复杂类型，例如，把username和password两个参数封装到一个credential（证书）对象里面。
四、在Web.Config中保存应用私有的数据
用ASP.NET开发的Web服务能够发挥出.aspx应用的所有特长，包括用web.config文件保存应用私有数据的能力（例如，数据库连接字符串、文件路径等）。用Web.config而不是global.asax文件的好处在于修改配置之后不必重新构造应用。
五、避免使用ASP.NET会话状态
.NET实现的会话状态管理功能解决了它的前辈ASP 3.0存在的许多问题，例如请求串行化等，但仍存在一些局限。应当认识到，.NET的会话状态管理功能不是专门为Web服务环境中的会话状态而设计，而是为了在范围更广泛的ASP.NET应用中管理会话状态而设计，它依赖于HTTP Cookie（有一种通过改写URL实现的不需要Cookie的模式，但不适用于Web服务）。
Cookie是HTTP独有的。在Web上，所有的浏览器都支持HTTP，所以Cookie非常适合在Web应用中使用。但是，在Web服务中应用Cookie却把服务限定到了HTTP协议上。另一方面，SOAP协议的运行是独立于传输协议的，因此如果把Web服务应用限制到HTTP协议上，应用的灵活性也受到了限制，一旦要通过非HTTP的传输协议（例如SMTP）提供服务，事情会变得很麻烦。