在 C# 中建立 SOAP 服務

Saad Aslam 2023年10月12日
  1. SOAP 的簡要說明
  2. SOAP 網路服務
  3. 在 C# 中使用 .NET Core 呼叫 SOAP 服務
  4. 在 C# 中使用 SoapClientMessage
  5. 在 C# 中使用 ASP.NET Core 建立 SOAP 服務
在 C# 中建立 SOAP 服務

如果你想將 SOAP 或 WCF 與 ASP.NET Core 一起使用,你並不孤單。它是 .NET Core 中最受歡迎和最受歡迎的功能之一。

在這篇文章中,我們將介紹如何在 .NET Core 應用程式中使用 WCF SOAP 服務。我們還演示了使用 ASP.NET Core 來建立和託管 SOAP 服務。

SOAP 的簡要說明

SOAP(簡單物件訪問協議)是一種用於在分散且可能不同的系統之間傳輸結構化資料的協議。它的通訊格式是 XML,它依賴於 HTTP 等應用層協議。

大多數人都熟悉它作為線上服務的標準協議。

直到最近,SOAP 還是構建 Web 服務的事實標準,而面向服務的體系結構 (SOA) 強烈依賴它。SOAP 建立了一種應該遵循的訊息格式,但我們可以自由地在其中包含我們想要的任何內容——甚至可以使用二進位制附件。

SOAP 標準提供了一個包含的信封(envelope >),它可以包括一個標頭(header >)和一個主體(body >),後者可以包含一個故障部分(fault >)以及其他子部分。只有 body > 是必需的,而 fault > 是為發生錯誤的答案而不是請求保留的。

在訊息期間合併部分二進位制材料的能力稱為訊息傳輸優化機制 (MTOM),它是利用 Base-64 對二進位制流進行編碼的替代方案,使二進位制流大 30%。

SOAP 網路服務

呼叫線上服務時,正文必須包括要執行的操作以及可能提供的任何引數。POST 始終由 SOAP Web 服務使用,並且信封始終作為有效負載傳送到單個眾所周知的 URL。

Web 服務框架會將請求路由到特定的系統類和功能。

Web 服務使 Web 服務定義語言 (WSDL) 檔案可用,其中包含有關服務的資訊,例如每個操作方法的名稱、每個操作方法的引數和返回值以及預期的錯誤。Visual Studio(和其他工具,如 SVCUtil.exe 命令列程式)可以生成程式碼代理,使用此 WSDL 與 Web 服務互動。

在 C# 中使用 .NET Core 呼叫 SOAP 服務

因此,如果你希望通過 .NET Core 在客戶端使用 WCF,則可以。首先,仔細檢查你是否包含了 System.ServiceModel

System 的原語之一 ServiceModel.Http 或 System(用於 BasicHttpBinding/BasicHttpsBindingNetHttpBinding/NetHttpsBinding 繫結,包括 SOAP 和 REST)。ServiceModel.NetTcp 是一種允許你傳送和接收的協議(對於 NetTcpBinding,一種僅限 Windows 的二進位制協議)。

讓我們看一個基本的例子。

一、合同:

public interface IPServ {
  string P(string msg);
}

然後是客戶端程式碼:

var bind = new BasicHttpBinding();
var endp = new EndpointAddress(new Uri("[url]"));
var cF = new ChannelFactory(bind, endp);
var servC = cF.CreateChannel();
var res = servC.Ping("Ping");
cF.Close();

如你所見,一切都與你在完整的 .NET 框架中工作時的情況相同。由於沒有 App.configWeb.config 檔案,你需要手動配置所有內容,例如建立正確的繫結和端點地址。

你還可以使用 svcutil.exe 程式手動生成與 .NET Core 相容的代理類。這將允許你使用 .NET Core。

當你考慮到使用 SOAP 配置 ASP.NET Core 是多麼容易時,很容易忽略它可能是多麼困難。

在 C# 中使用 SoapClientMessage

記錄 XML Web 服務客戶端傳送和接收的 SOAP 訊息的 SOAP 擴充套件包括以下程式碼段。傳送到 SoapExtension 的 SoapClientMessage 由該片段處理。

SOAP 擴充套件的 ProcessMessage 函式將 SoapClientMessage 屬性寫入日誌檔案。

// Process the SOAP message received and write it to a log file.
public override void PM(SoapMessage m) {
  switch (m.Stage) {
    case SoapMessageStage.BeforeSerialize:
      break;
    case SoapMessageStage.AfterSerialize:
      WriteOutput((SoapClientMessage)m);
      break;
    case SoapMessageStage.BeforeDeserialize:
      WriteInput((SoapClientMessage)m);
      break;
    case SoapMessageStage.AfterDeserialize:
      break;
    default:
      throw new Exception("this is and invalid state");
  }
}

為了輸出,輸出到檔案的 SOAP 訊息的日誌稱為日誌檔案。

public void WO(SoapClientMessage m) {
  newStream.Position = 0;
  FileStream mf = new FileStream(filename, FileMode.Append, FileAccess.Write);
  StreamWriter ms = new StreamWriter(mf);
  ms.WriteLine("--> Requested at " + DateTime.Now);

  // Print to the log file the  field of request header for header SoapAction .
  ms.WriteLine("The  Http SoapAction  header request field is: ");
  ms.WriteLine("\t" + m.Action);

  // Write the client type that called the XML Web service method to the log file.
  ms.WriteLine("The client type is: ");
  if ((m.Client.GetType()).Equals(typeof(MathSvc)))
    ms.WriteLine("\tMathSvc");

  // The client's technique will be printed to the log file.
  ms.WriteLine("The approach that the client has requested is:");
  ms.WriteLine("\t" + m.MethodInfo.Name);

  // The client's technique will be printed on the log file.
  if (m.OneWay)
    ms.WriteLine("The client does not wait for the server to complete the task.");
  else
    ms.WriteLine("The client waits for the server to complete the task.");

  // The URL of the site that implements the method is printed to the log file.
  ms.WriteLine("The XML Web service method that has been requested has the following URL: ");
  ms.WriteLine("\t" + m.Url);
  ms.WriteLine("The SOAP envelope's contents are as follows: ");
  ms.Flush();

  // Copy one stream's content to another.
  Copy(newStream, mf);
  mf.Close();
  newStream.Position = 0;

  // Copy one stream's content to another.
  Copy(newStream, oldStream);
}

在 C# 中使用 ASP.NET Core 建立 SOAP 服務

例如,對於客戶端,你可以使用我們之前展示的相同類。你需要開發一個在伺服器端實現合同的服務類:

public class SS : IPServ {
  public string P(string m) {
    return string.Join(string.Empty, m.Reverse());
  }
}

我們現在要做的就是在以下地址註冊服務實現:

public void ConfigServ(IServColl s) {
  s.AddSingleton(new PingService());
  s.AddMvc();
  // rest code goes here
}
public void Conf(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
  app.UseSoapEndpoint(path: "/PingService.svc", binding: new BasicHttpBinding());
  app.UseMvc();
  // rest code goes here
}

你可以實現自定義異常到字串轉換器,以從應該發生的任何異常中提取有意義的訊息,並將其作為故障字串提供給客戶端,如果你願意:

s.AddSoapExceptionTransformer((ex) = > ex.Message);

該程式碼將自定義中介軟體注入到 ASP.NET Core 管道中,該管道偵聽 HTTP POST 並檢查有效標頭。它從有效負載中提取操作方法和引數,然後將其轉發到指定的實現類。

需要考慮的幾點

  1. 不需要 .svc 副檔名;它只是提醒我們 WCF 以前需要它。
  2. 對於 PingService,你可以使用任何生命週期,而不僅僅是單例。
  3. 客戶端和伺服器繫結必須相同。
  4. 你將無法使用任何 ASP.NET Core 過濾器,因為它們將被忽略,但你可以改用依賴注入。

即使你肯定會使用此程式碼來實現向後相容性,但如果你需要在 .NET Core 中編寫 SOAP 服務(例如,如果你需要將其部署到 Docker),請注意以下限制:

  1. 不支援 WS - *標準。
  2. 不支援 MTOM。
  3. 除了 HTTPS 和 ASP.NET Core 內建的安全性之外,沒有對安全性的支援。
  4. 不會有節流或不當行為。
作者: Saad Aslam
Saad Aslam avatar Saad Aslam avatar

I'm a Flutter application developer with 1 year of professional experience in the field. I've created applications for both, android and iOS using AWS and Firebase, as the backend. I've written articles relating to the theoretical and problem-solving aspects of C, C++, and C#. I'm currently enrolled in an undergraduate program for Information Technology.

LinkedIn