1. 方式一:通过 Visual Studio/Add Service Reference 自动生成代理类
这是最简单、最常用的方式。适合传统 .NET Framework 项目。
步骤
- 在项目中右键“添加服务引用”或“Add Service Reference”
- 输入 WebService 的 WSDL 地址(如 http://example.com/service?wsdl)
- 生成代理类,自动添加到项目中
调用示例
假设服务有方法 Add(int a, int b):
// 假设命名空间为 ServiceReference1
var client = new ServiceReference1.MyWebServiceSoapClient();
int result = client.Add(3, 5);
Console.WriteLine("结果:" + result);
注意:
- 代理类会自动处理 SOAP 协议、序列化、参数类型。
- 支持复杂对象、数组等。
2. 方式二:手动发送 SOAP XML(适合 .NET Core 或无WSDL场景)
适合没有 WSDL 或跨语言调用。
示例:调用一个简单的加法 WebService
2.1 构造 SOAP XML
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<a>3</a>
<b>5</b>
</Add>
</soap:Body>
</soap:Envelope>
2.2 C#代码实现
using System.Net;
using System.IO;
public string CallWebService(string url, string soapAction, string soapXml)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "text/xml; charset=utf-8";
request.Method = "POST";
request.Headers.Add("SOAPAction", soapAction);
using (Stream stream = request.GetRequestStream())
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(soapXml);
}
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
{
return reader.ReadToEnd();
}
}
使用方法
string url = "http://example.com/service.asmx";
string soapAction = "http://tempuri.org/Add";
string soapXml = @"<?xml version='1.0' encoding='utf-8'?><soap:Envelope ... >...</soap:Envelope>";
string resultXml = CallWebService(url, soapAction, soapXml);
// 解析 resultXml 得到结果
注意:
- 需自己解析返回的 XML,可用
System.Xml或XDocument。 - 复杂类型建议用序列化工具辅助生成 XML。
3. 方式三:.NET Core/现代项目推荐
3.1 使用 WSDL 工具(svcutil/dotnet-svcutil)
在 .NET Core/5/6/7 下,可用命令行工具生成代理类:
dotnet tool install --global dotnet-svcutil
dotnet-svcutil http://example.com/service?wsdl
生成的代理类直接引用并调用。
3.2 使用第三方库(如 SoapClient)
NuGet 安装:
Install-Package SoapClient
示例:
using SimpleSOAPClient;
using SimpleSOAPClient.Models;
var client = new SoapClient();
client.Endpoint = new Uri("http://example.com/service.asmx");
var response = await client.SendAsync(
SoapEnvelope.Prepare().WithBody(new Add { a = 3, b = 5 })
);
4. 复杂参数/对象传递
- 自动生成代理类时,复杂对象会自动生成对应的 C# 类型。
- 手动发送 SOAP XML 时,复杂对象需自己构造嵌套的 XML 节点。
5. 异常与调试建议
- 捕获
WebException,检查 HTTP 响应码、错误信息。 - SOAP Fault 错误需解析 XML
<Fault>节点。 - Fiddler/Wireshark 可抓包分析请求/响应。
- 调试建议先用 Postman 或 SoapUI 测试接口,再用 C# 实现。
6. 复杂类型和数组参数的处理
自动代理方式(Add Service Reference)
如果 WebService 方法参数或返回值是复杂对象或数组,代理类会自动生成对应的 C# 类型。例如:
假设 WSDL 定义:
<complexType name="Person">
<sequence>
<element name="Name" type="string"/>
<element name="Age" type="int"/>
</sequence>
</complexType>
C# 调用:
var client = new ServiceReference1.MyWebServiceSoapClient();
var person = new ServiceReference1.Person { Name = "张三", Age = 28 };
var result = client.AddPerson(person);
数组/列表参数直接用 C# 的数组或 List。
手动 SOAP XML方式
你需要自己构造嵌套 XML。例如:
<soap:Envelope ...>
<soap:Body>
<AddPerson xmlns="http://tempuri.org/">
<person>
<Name>张三</Name>
<Age>28</Age>
</person>
</AddPerson>
</soap:Body>
</soap:Envelope>
7. 异步调用 WebService
自动代理方式
代理类通常支持异步方法(以 Async 结尾):
var client = new ServiceReference1.MyWebServiceSoapClient();
var result = await client.AddAsync(3, 5);
Console.WriteLine(result.Body.AddResult);
手动 SOAP XML方式
用 HttpClient 实现异步请求:
using System.Net.Http;
using System.Text;
public async Task<string> CallWebServiceAsync(string url, string soapAction, string soapXml)
{
using (var client = new HttpClient())
{
var content = new StringContent(soapXml, Encoding.UTF8, "text/xml");
content.Headers.Add("SOAPAction", soapAction);
var response = await client.PostAsync(url, content);
return await response.Content.ReadAsStringAsync();
}
}
8. SOAP响应解析
SOAP 响应通常是 XML,需要解析节点获取结果:
using System.Xml.Linq;
string soapResponse = "..."; // 上面获得的XML字符串
var doc = XDocument.Parse(soapResponse);
XNamespace ns = "http://tempuri.org/";
var result = doc.Descendants(ns + "AddResult").FirstOrDefault()?.Value;
Console.WriteLine("结果:" + result);
复杂类型需按实际 XML 层级解析。
9. WCF 与 WebService 的区别
| 特点 | WebService(ASMX) | WCF |
|---|---|---|
| 协议 | 仅支持 SOAP | 支持 SOAP/REST/TCP/HTTP等 |
| 配置 | 简单,直接在 IIS 托管 | 灵活,支持多协议多绑定 |
| 特性 | 适合简单场景 | 企业级,安全/事务/多协议 |
| 代码生成 | Add Service Reference | Add Service Reference/SvcUtil |
| 推荐场景 | 老项目/兼容性需求 | 新项目/复杂分布式服务 |
10. 企业级实战技巧
- 异常处理:捕获
FaultException、WebException,记录详细日志,便于排查。 - 日志监控:集成 NLog/Serilog,记录每次调用的请求、响应、耗时、异常。
- 安全加固:敏感业务建议用 HTTPS,或 WCF 的消息加密/签名。
- 批量/多线程调用:用 Task/Parallel 实现高并发批量请求。
- 跨平台兼容:.NET Core 推荐用
dotnet-svcutil或SoapCore,支持 Linux/Mac。
11. 面试深度问题与答题思路
-
如何在 C# 中调用没有 WSDL 的 WebService?
- 构造 SOAP XML,手动 POST 请求,解析 XML 响应。
-
ASMX 与 WCF 的主要区别?
- 协议支持、配置灵活性、安全和事务、扩展能力。
-
如何处理 WebService 返回的复杂对象或数组?
- 自动代理方式直接用类型,手动 XML 需按节点解析。
-
如何保证 WebService 调用的健壮性和高可用?
- 异常重试、超时设置、日志监控、批量并发、连接池等。
-
SOAP 与 RESTful API 的区别?
- SOAP基于XML和协议标准,REST基于HTTP和资源,SOAP适合复杂/安全场景,REST适合轻量/开放场景。
- 能区别 RESTful API 和 SOAP WebService 的实现与调用方式。
- 熟悉自动代理与手动 XML 的优缺点。
- 能处理复杂对象、数组、命名空间冲突等 SOAP 通用问题。
- 了解 .NET Core 下新工具(dotnet-svcutil)、跨平台兼容性。
- 能结合异常处理、日志、监控给出企业级解决方案。
3866






