- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一些数据需要以 SOAP 格式发送到服务器。该服务器将立即确认它收到了消息。几个小时后,我收到(可能来自另一台服务器)一条 SOAP 消息,其中包含有关已处理数据的信息。
我读了Stackoverflow: How to send SOAP request and receive response .然而,答案是 8 岁。尽管它们可能仍然有效,但可能有更新的技术。
而且看起来确实如此:Microsoft 有 System.Web.Services.Protocols,其中有类似 SoapMessage 的类, SoapClientMessage, SoapServerMessage 等
查看这些类,我发现很多类似 SOAP 的类( header 、扩展、客户端消息、服务器消息......通常提供的示例会告诉我这些类如何协同工作以及如何使用它们。在MSDN 文档我只能找到如何处理已经存在的 SOAP 消息的示例。
Given some data that needs to be sent, how can I wrap this data somehow in one of these SOAP classes and send this message?
这些类(class)是为了这个目的吗?还是我应该坚持使用 2011 年的方法,如上面提到的 Stackoverflow 问题所暗示的那样,您自己通过将 XML 数据格式化为 soap 格式来创建 SOAP Web 请求?
非常抱歉,通常我会写下我尝试过的东西。 las,我看不到 provided SoapMessage classes 之间的关系.我不知道如何使用它们。
评论后补充
我正在使用 Windows Server/Visual Studio(最新版本)/.NET(最新版本)/C#(最新版本)。
与服务器的通信是相互认证的。我需要用来与服务器通信的证书采用 PEM (CER/CRT) 格式。私钥是RSA。该证书由适当的 CA 颁发,服务器也将使用适当的 CA 使用的证书。所以我不需要创建新的证书(事实上,它不会被接受)。如果需要,我愿意使用 OpenSsl 等程序转换证书。
我曾尝试使用 Apache TomCat 进行通信,但我觉得这对于每天发送一条 SOAP 消息并每天等待一个答复的任务来说太过分了。
可能因为java对我来说是一个全新的技术,所以我很难看到接收到的消息的内容。那么回到 C# 和 .NET。
我正计划创建一个 DLL,供控制台应用程序使用。该函数将流中的一些数据作为输入。它将创建 soap 消息,发送它,等待消息被正确接收的回复,并等待(可能几个小时)包含处理数据结果的新 Soap 消息。为了使正确的报告和取消成为可能,我想最好使用 async-await 来完成此操作
如果不能在一个应用程序中完成发送订单和等待结果,我愿意创建一个监听输入的 Windows 服务,但我更愿意保持简单。
(虚拟)计算机将仅用于此任务,因此没有其他人需要监听端口 443。每天将发送一条订单消息,每天发送一条结果消息。
最佳答案
这是使用 HTTPS 的示例 C# 控制台客户端和服务器代码(它们在同一个示例中,但这当然仅用于演示目的)。
对于客户端,我们重用了 SoapHttpClientProtocol
类,但是对于服务器端,不幸的是,我们不能重用任何东西,因为类完全依赖于 ASP.NET (IIS) 的 HttpContext
类
对于服务器端,我们使用 HttpListener
,因此,根据您的配置,服务器端可能需要管理员权限才能调用 HttpListener
的 Prefixes.Add(url)
.
该代码不使用客户端证书,但您可以在我放置//TODO 注释的位置添加它
该代码假定存在与使用的 url 和端口关联的证书。如果没有(使用 netsh http show sslcert
转储所有关联的证书),您可以使用此处描述的过程添加一个:https://stackoverflow.com/a/11457719/403671
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
namespace SoapTests
{
class Program
{
static void Main(string[] args)
{
// code presumes there is an sslcert associated with the url/port below
var url = "https://127.0.0.1:443/";
using (var server = new MyServer(url, MyClient.NamespaceUri))
{
server.Start(); // requests will occur on other threads
using (var client = new MyClient())
{
client.Url = url;
Console.WriteLine(client.SendTextAsync("hello world").Result);
}
}
}
}
[WebServiceBinding(Namespace = NamespaceUri)]
public class MyClient : SoapHttpClientProtocol
{
public const string NamespaceUri = "http://myclient.org/";
public async Task<string> SendTextAsync(string text)
{
// TODO: add client certificates using this.ClientCertificates property
var result = await InvokeAsync(nameof(SendText), new object[] { text }).ConfigureAwait(false);
return result?[0]?.ToString();
}
// using this method is not recommended, as async is preferred
// but we need it with this attribute to make underlying implementation happy
[SoapDocumentMethod]
public string SendText(string text) => SendTextAsync(text).Result;
// this is the new Task-based async model (TAP) wrapping the old Async programming model (APM)
public Task<object[]> InvokeAsync(string methodName, object[] input, object state = null)
{
if (methodName == null)
throw new ArgumentNullException(nameof(methodName));
return Task<object[]>.Factory.FromAsync(
beginMethod: (i, c, o) => BeginInvoke(methodName, i, c, o),
endMethod: EndInvoke,
arg1: input,
state: state);
}
}
// server implementation
public class MyServer : TinySoapServer
{
public MyServer(string url, string namespaceUri)
: base(url)
{
if (namespaceUri == null)
throw new ArgumentNullException(nameof(namespaceUri));
NamespaceUri = namespaceUri;
}
// must be same as client namespace in attribute
public override string NamespaceUri { get; }
protected override bool HandleSoapMethod(XmlDocument outputDocument, XmlElement requestMethodElement, XmlElement responseMethodElement)
{
switch (requestMethodElement.LocalName)
{
case "SendText":
// get the input
var text = requestMethodElement["text", NamespaceUri]?.InnerText;
text += " from server";
AddSoapResult(outputDocument, requestMethodElement, responseMethodElement, text);
return true;
}
return false;
}
}
// simple generic SOAP server
public abstract class TinySoapServer : IDisposable
{
private readonly HttpListener _listener;
protected TinySoapServer(string url)
{
if (url == null)
throw new ArgumentNullException(nameof(url));
_listener = new HttpListener();
_listener.Prefixes.Add(url); // this requires some rights if not used on localhost
}
public abstract string NamespaceUri { get; }
protected abstract bool HandleSoapMethod(XmlDocument outputDocument, XmlElement requestMethodElement, XmlElement responseMethodElement);
public async void Start()
{
_listener.Start();
do
{
var ctx = await _listener.GetContextAsync().ConfigureAwait(false);
ProcessRequest(ctx);
}
while (true);
}
protected virtual void ProcessRequest(HttpListenerContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
// TODO: add a call to context.Request.GetClientCertificate() to validate client cert
using (var stream = context.Response.OutputStream)
{
ProcessSoapRequest(context, stream);
}
}
protected virtual void AddSoapResult(XmlDocument outputDocument, XmlElement requestMethodElement, XmlElement responseMethodElement, string innerText)
{
if (outputDocument == null)
throw new ArgumentNullException(nameof(outputDocument));
if (requestMethodElement == null)
throw new ArgumentNullException(nameof(requestMethodElement));
if (responseMethodElement == null)
throw new ArgumentNullException(nameof(responseMethodElement));
var result = outputDocument.CreateElement(requestMethodElement.LocalName + "Result", NamespaceUri);
responseMethodElement.AppendChild(result);
result.InnerText = innerText ?? string.Empty;
}
protected virtual void ProcessSoapRequest(HttpListenerContext context, Stream outputStream)
{
// parse input
var input = new XmlDocument();
input.Load(context.Request.InputStream);
var ns = new XmlNamespaceManager(new NameTable());
const string soapNsUri = "http://schemas.xmlsoap.org/soap/envelope/";
ns.AddNamespace("soap", soapNsUri);
ns.AddNamespace("x", NamespaceUri);
// prepare output
var output = new XmlDocument();
output.LoadXml("<Envelope xmlns='" + soapNsUri + "'><Body/></Envelope>");
var body = output.SelectSingleNode("//soap:Body", ns);
// get the method name, select the first node in our custom namespace
bool handled = false;
if (input.SelectSingleNode("//x:*", ns) is XmlElement requestElement)
{
var responseElement = output.CreateElement(requestElement.LocalName + "Response", NamespaceUri);
body.AppendChild(responseElement);
if (HandleSoapMethod(output, requestElement, responseElement))
{
context.Response.ContentType = "application/soap+xml; charset=utf-8";
context.Response.StatusCode = (int)HttpStatusCode.OK;
var writer = new XmlTextWriter(outputStream, Encoding.UTF8);
output.WriteTo(writer);
writer.Flush();
handled = true;
}
}
if (!handled)
{
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
}
public void Stop() => _listener.Stop();
public virtual void Dispose() => _listener.Close();
}
}
关于c# - 如何将数据作为 SoapMessage 发送并获得回复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55568246/
我正在从 SOAP 消息中获取附件并在我的应用程序中使用它们。 我不会从原始消息中删除附件。之后,我尝试使用以下代码将原始 包含附件 (SwA) 的 SOAPMessage 转换为字符串: ByteA
我正在调用第三方soap,其中每个元素都必须有一个命名空间。我正在从 Java 调用 .NET 服务。在某些元素中,我必须包含“http://abc.com”。其他时候,我必须包括 xmlns:""。
我有一个 SOAPMessage(位于 javax.xml.soap.SOAPMessage 中)。 然而,打印它的唯一方法似乎是 soapMessage.writeTo(System.out); 然
我正在尝试调用一些 WS。我的本地计算机上有服务器和客户端。我 100% 确定消息内容,并且它从服务器发送到客户端,没有任何更改。问题是客户端创建的 SOAPMessage 对象不正确,soapPar
SOAPMessage 具有 writeTo() 方法,用于将其内容打印到流中。但是如何将 SOAPMessage 内容写入 StringBuffer? 代码行“message.writeTo(Sys
我想为 SOAPMessage 实现 GZIP。下面是正常的 SOAP 客户端调用代码 - // Create a new SOAP message from the factory and
我尝试将一些外语的 unicode 字符串发送到 SOAPMessage.writeTo()但它并没有逃脱它。 当我尝试发送 XML 转义字符串 StringEscapeUtils.escapeXml
我使用 SOAPMessage.writeTo(OutputStream)记录网络服务消息。一个问题是它也写附件。它占用空间并且二进制附件不可读。有什么方法可以记录没有附件的消息,例如 wrapper
我有一些数据需要以 SOAP 格式发送到服务器。该服务器将立即确认它收到了消息。几个小时后,我收到(可能来自另一台服务器)一条 SOAP 消息,其中包含有关已处理数据的信息。 我读了Stackover
我的环境是:Windows7 32,jboss-5.1.0.GA,jdk1.6.0_20。 尝试运行 SOAP 消息时,出现以下错误: 简而言之: #java.lang.UnsupportedOper
我有这样的代码: import javax.xml.transform.Source; import org.apache.cxf.binding.soap.SoapMessage; public c
各位,我不明白如果message.getSOAPBody()打印为null,那么为什么unmarshaller.unmarshal(message.getSOAPBody(), Person.clas
我正在尝试使用下面的代码将字符串 xml 转换为soapMessage, System.out.println("response:" + response.toString());
下面是将 java 对象编码到 SOAPMessage 中的代码: public static SOAPMessage encode(String key,Object object) th
我的应用程序中的 SOAP 消息包含从文件创建的附件。当我多次调用 soapMessage.writeTo(System.out); 时,它会引发以下异常: SEVERE: SAAJ0540: Err
我在字符串中有以下消息, " someEncryptedTextGoesHere " 我试图在 SOAPMessage 中转换它并
我想知道有什么方法可以将字符串转换为 SOAPMessage 吗? 假设我有一个字符串如下: String send = "" + "" + "" +
我正在尝试在 JBoss 5.1.0 上的 WAR 应用程序中部署一些 Web 服务。 我已经使用 JAX-WS 工具 wsgen 从现有 wsdl 创建了源文件。这创建了服务文件和 @XmlType
我正在开发一个网络服务,它将两个字符串值作为输入参数。第一个标识用于导入 xml 数据的服务,第二个是 XML 数据字符串。这是 SOAP 请求的示例
我正在开发一个网络服务,它将两个字符串值作为输入参数。第一个标识用于导入 xml 数据的服务,第二个是 XML 数据字符串。这是 SOAP 请求的示例
我是一名优秀的程序员,十分优秀!