使用C# 搭建WebService接口,并按照ESB平台人员的要求,将命名空间改为"http://esb.webservice",使用Postman+ESB平台人员提供的入参示例进行测试时,callBussiness接口参数message始终为null。
以下是ESB平台提供的模版
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://esb.webservice">
<soapenv:Header/>
<soapenv:Body>
<esb:callBussiness>
<message>
message>
esb:callBussiness>
soapenv:Body>
soapenv:Envelope>
using System;
using System.IO;
using System.Text;
using System.Web.Services;
using System.Xml;
using System.Xml.Serialization;
using Rss_WebServer.code;
namespace ESB
{
///
/// WebService 的摘要说明
///
[WebService(Namespace = "http://esb.webservice")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
[WebMethod(Description = "调用业务")]
public string callBussiness(string message)
{
return message;
}
}
}
POST http://localhost:55305/WebService.asmx?op=callBussiness| KEY | VALUE | DESCRIPTION |
|---|---|---|
| Content-Type | text/xml; charset=utf-8 | |
| SOAPAction | “http://esb.webservice/callBussiness” |
XML(text/xml)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://esb.webservice">
<soapenv:Header/>
<soapenv:Body>
<esb:callBussiness>
<message>
少莫千华 370763160@qq.com ]]>
message>
esb:callBussiness>
soapenv:Body>
soapenv:Envelope>


根本问题是ESB平台提供的参数模版并没有完全按照标准的WebService协议进行编写,导致使用官方搭建的WebService接口无法正常的解析参数,所以要想解决此问题,有两个途径:
WebService参数对callBussiness接口的message参数添加命名空间缩写esb
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://esb.webservice">
<soapenv:Header/>
<soapenv:Body>
<esb:callBussiness>
<esb:message>
esb:message>
esb:callBussiness>
soapenv:Body>
soapenv:Envelope>
对callBussiness接口的使用完整的命名空间。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<callBussiness xmlns="http://esb.webservice">
<message>
message>
callBussiness>
soapenv:Body>
soapenv:Envelope>
WebService参数从请求对象base.Context.Request中重新获取所有Body内容(InputStream),然后再进行自定义解析。
注:因为是搭建的标准的WebService接口Body内容(InputStream)在进去函数内部前已经被SOAP协议解析过一次,所以InputStream的起始内容位置Position 指向数据流的结尾,所以在读取之前,先要将InputStream的起始内容位置Position设置为0,否则读取的内容为空('')
using System;
using System.IO;
using System.Text;
using System.Web.Services;
using System.Xml;
using System.Xml.Serialization;
using Rss_WebServer.code;
namespace ESB
{
///
/// WebService 的摘要说明
///
[WebService(Namespace = "http://esb.webservice")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
[WebMethod(Description = "调用业务")]
public string callBussiness(string message)
{
try
{
if (string.IsNullOrEmpty(message))
{
message = WebServiceAnalysis(base.Context.Request, nameof(message));
}
return message;
}
catch(Exception exp)
{
return exp.Message;
}
}
///
/// 重新解析 WebService
///
///
///
///
private string WebServiceAnalysis(System.Web.HttpRequest request,string name)
{
try
{
if(request.ContentLength == 0)
{
throw new Exception($"Body(xml数据) 无数据");
}
// 获取请求内容
Stream inputStream = request.InputStream;
// 重新获取内容
inputStream.Position = 0;
// 读取请求主体内容
using (StreamReader reader = new StreamReader(inputStream, Encoding.UTF8))
{
string requestBody = reader.ReadToEnd();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(requestBody);
XmlNode strNode = xmlDoc.SelectSingleNode($"//{name}");
if (strNode != null)
{
return strNode.InnerText;
}
else
{
throw new Exception($"未在Body(xml数据)找到{name}节点");
}
}
}
catch(Exception exp)
{
throw exp;
}
}
}
}