首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

WebService 帶結構體參數調用報錯?客戶端直接引用服務端類型定義避免序列化不匹配

     編輯:程式設計綜合問答

錯誤現象

C# 客戶端調用 WebService 方法,參數為自定義結構體 MyStruct。雖然客戶端與服務端定義了「同名、同字段」的結構體,但調用時拋出異常:
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> Object reference not set to an instance of an object.

根本原因

WebService (ASMX/WCF) 基於 **XML Schema (XSD)** 定義數據契約。客戶端與服務端雖代碼長得一樣,但屬於**兩個獨立的類型**(不同命名空間、不同程序集)。序列化時生成的 XML 命名空間不一致,服務端反序列化失敗,字段全為 null/default。

正確做法:共享契約 / 服務引用生成類型

方案一:添加服務引用(最通用)

  1. VS 右鍵項目 → Add Service Reference。
  2. 輸入 WSDL 地址(如 https://server:port/Service.asmx?wsdl)。
  3. VS 根據 WSDL 生成代理類與**數據契約類**(位於 Reference.cs)。
  4. 客戶端代碼直接使用生成的類型:
var client = new MyServiceSoapClient();
var req = new MyService.RequestStruct { Field1 = "A", Field2 = 123 }; // 使用生成的類型
var resp = client.MyMethod(req);

方案二:共享程序集(僅限 .NET 雙端、內網、版本強一致)

  1. 將數據契約類(POCO/Struct + [DataContract]/[DataMember])抽離到獨立 Class Library (SharedContracts.dll)。
  2. 服務端、客戶端**同時引用同一 DLL**。
  3. WCF 配置 dataContractSerializer 已知類型,或 ASMX 無需額外配置。

⚠️ 風險:版本不一致導致反序列化異常,升級需協同部署。

方案三:手動構造 SOAP(不推薦,維護成本極高)

用 HttpWebRequest 發送手寫 XML,完全掌控命名空間、前綴。僅用於無法引用服務的異構系統(Java/Python/Go 調用 .NET ASMX)。

調試技巧

  • 開啟 WCF 追蹤:<system.diagnostics><sources><source name="System.ServiceModel" switchValue="Information, ActivityTracing">...</source></sources></system.diagnostics>,用 SvcTraceViewer.exe 分析異常詳情。
  • 抓包:Fiddler/Wireshark 對比請求/響應 XML,重點看 xmlns、xsi:type、字段順序。
  • 在服務端臨時添加 try-catch 記錄完整異常堆棧,而非讓 SOAP Fault 吞沒細節。

總結

切勿手工複製結構體定義。Add Service Reference → 使用生成的類型 是 .NET WebService 開發的鐵律。若跨語言,請嚴格遵循 WSDL/XSD 契約,或改用 REST/JSON (Web API) 避免 SOAP 複雜性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved