.NET 8中调用Workday Inventory WSDL生成的WCF客户端遇序列化错误
解决方案:Workday Inventory v43.1 WCF客户端序列化错误与.NET 8替代方案
一、解决CodeGenError(IsNotAssignableFrom)序列化错误
1. 调整dotnet-svcutil生成参数,指定XmlSerializer
Workday的SOAP服务大多基于XmlSerializer,默认的DataContractSerializer容易出现类型不匹配问题。重新生成客户端时添加以下参数:
dotnet-svcutil https://community.workday.com/sites/default/files/file-hosting/productionapi/Inventory/v43.1/Inventory.wsdl --serializer:XmlSerializer --collectionType:System.Collections.Generic.List`1
--serializer:XmlSerializer强制使用XmlSerializer适配Workday的schema,--collectionType指定集合类型为List,避免数组与单个对象的序列化冲突。
2. 手动修正生成代码的属性定义
如果工具生成的代码中存在数组与单个对象的类型混淆,找到对应错误的属性(比如Inventory_Par_RemovalObject),修改其类型并补充Xml序列化特性:
// 原错误代码(单个对象类型) // public Inventory_Par_RemovalObjectType Inventory_Par_RemovalObject { get; set; } // 修改为集合类型并添加序列化特性 [System.Xml.Serialization.XmlArrayAttribute(Order = 4)] [System.Xml.Serialization.XmlArrayItemAttribute("Inventory_Par_RemovalObject", IsNullable = false)] public System.Collections.Generic.List<Inventory_Par_RemovalObjectType> Inventory_Par_RemovalObject { get; set; } // 同时在构造函数中初始化集合 public Get_Inventory_BalanceInput() { this.Inventory_Par_RemovalObject = new System.Collections.Generic.List<Inventory_Par_RemovalObjectType>(); // 其他属性初始化... }
注意匹配WSDL中对应的元素名称和顺序,避免连锁错误。
3. 更新dotnet-svcutil到最新版本
你当前使用的2.1.0版本存在对复杂WSDL的兼容性问题,安装最新版本:
dotnet tool uninstall --global dotnet-svcutil dotnet tool install --global dotnet-svcutil --version 3.2.0
新版本对Workday的schema解析更准确,能自动处理数组与单个对象的映射。
二、.NET 8中消费Workday WSDL的替代方案
1. 使用Visual Studio WCF Connected Service扩展
这是官方集成的工具,比手动调用dotnet-svcutil更便捷:
- 在Visual Studio 2022中,右键项目 → 「添加」→ 「Connected Service」
- 选择「Microsoft WCF Web Service Reference Provider」
- 输入Workday Inventory的WSDL地址,配置序列化方式为XmlSerializer,集合类型为List,生成客户端代码。
2. 手动使用HttpClient+XmlSerializer调用
放弃自动生成的代理,直接构造SOAP请求,可控性更强:
// 构造SOAP信封(根据WSDL定义的格式) var soapEnvelope = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:inv=""urn:com.workday/bsvc/Inventory""> <soapenv:Header> <!-- 这里添加Workday的认证头,比如UsernameToken --> </soapenv:Header> <soapenv:Body> <inv:Get_Inventory_Balance_Request> <!-- 填充请求参数 --> </inv:Get_Inventory_Balance_Request> </soapenv:Body> </soapenv:Envelope>"; // 使用HttpClient发送请求 using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("SOAPAction", "urn:com.workday/bsvc/Get_Inventory_Balance"); var content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml"); var response = await httpClient.PostAsync("https://services.workday.com/ccx/service/your_tenant_name/Inventory/v43.1", content); // 反序列化响应 var responseContent = await response.Content.ReadAsStringAsync(); var serializer = new XmlSerializer(typeof(Get_Inventory_Balance_Response)); using var reader = new StringReader(responseContent); var result = (Get_Inventory_Balance_Response)serializer.Deserialize(reader);
这种方式需要自己定义请求/响应的实体类(可通过xsd.exe从WSDL导出的XSD生成),但完全避免工具生成的代理问题。
3. 使用第三方SOAP客户端生成工具
- SoapUI:导入Workday WSDL,生成C#客户端代码,再适配到.NET 8项目中,它对复杂WSDL的解析能力优于dotnet-svcutil。
- wsdl.exe:虽然是.NET Framework时代的工具,但可以生成兼容.NET 8的代码,命令行调用:
wsdl.exe /language:C# /out:WorkdayInventory.cs https://community.workday.com/sites/default/files/file-hosting/productionapi/Inventory/v43.1/Inventory.wsdl,生成后手动调整部分代码适配.NET 8。
内容的提问来源于stack exchange,提问作者HobbyLobbyVS
相关产品推荐
相关产品推荐

