在 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