【WebService】C#搭建的标准WebService接口,在使ESB模版作为参数无法获取参数数据

一、问题说明

1.1 问题描述

使用C# 搭建WebService接口,并按照ESB平台人员的要求,将命名空间改为"http://esb.webservice",使用Postman+ESB平台人员提供的入参示例进行测试时,callBussiness接口参数message始终为null

以下是ESB平台提供的模版

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://esb.webservice">
   <soapenv:Header/>
   <soapenv:Body>
      <esb:callBussiness>
         <!--Optional:-->
         <message>
        <![CDATA[...]]>
         </message>
      </esb:callBussiness>
   </soapenv:Body>
</soapenv:Envelope>

1.2 C# WebService代码

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
{
    /// <summary>
    /// WebService 的摘要说明
    /// </summary>
    [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; 
        }
   }
}

1.3 Postman 测试参数

  • POST http://localhost:55305/WebService.asmx?op=callBussiness
  • Headers
KEYVALUEDESCRIPTION
Content-Typetext/xml; charset=utf-8
SOAPAction“http://esb.webservice/callBussiness”
  • Body
    • raw XML(text/xml)
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://esb.webservice">
   <soapenv:Header/>
   <soapenv:Body>
      <esb:callBussiness>
         <!--Optional:-->
         <message>
        <![CDATA[<root><author>少莫千华</author><email>370763160@qq.com</email></root>]]>
         </message>
      </esb:callBussiness>
   </soapenv:Body>
</soapenv:Envelope>

在这里插入图片描述

在这里插入图片描述

二、问题分析

根本问题是ESB平台提供的参数模版并没有完全按照标准的WebService协议进行编写,导致使用官方搭建的WebService接口无法正常的解析参数,所以要想解决此问题,有两个途径:

  • 与ESB平台人员沟通,要求其标准化参数模版
  • 自己重新解构WebService参数

三、解决方案

3.1 与ESB平台人员沟通,要求其标准化参数模版

3.1.1 标准模版 - 使用命名空间缩写

callBussiness接口的message参数添加命名空间缩写esb

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://esb.webservice">
   <soapenv:Header/>
   <soapenv:Body>
      <esb:callBussiness>
         <!--Optional:-->
         <esb:message>
        <![CDATA[...]]>
         </esb:message>
      </esb:callBussiness>
   </soapenv:Body>
</soapenv:Envelope>

3.1.1 标准模版 - 使用完整的命名空间

callBussiness接口的使用完整的命名空间<callBussiness xmlns="http://esb.webservice">

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <callBussiness xmlns="http://esb.webservice">
         <!--Optional:-->
         <message>
        <![CDATA[...]]>
         </message>
      </callBussiness>
   </soapenv:Body>
</soapenv:Envelope>

3.2 自己重新解构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
{
    /// <summary>
    /// WebService 的摘要说明
    /// </summary>
    [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;
            }
            
        }
        /// <summary>
        /// 重新解析 WebService
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        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;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中调用WebService接口传递参数时,如果发生网络断开的情况,你可以使用一些方法来实现断网重传的功能。以下是一个简单的示例代码,用于演示如何实现断网重传: ```csharp using System; using System.Net; using System.Web.Services.Protocols; class Program { static void Main() { // 构造WebService代理对象 MyWebService myWebService = new MyWebService(); // 设置断网重传的次数 int retryCount = 3; int currentRetry = 0; bool success = false; while (!success && currentRetry < retryCount) { try { // 调用WebService接口方法,传递参数 myWebService.MyMethod(parameter1, parameter2, ...); success = true; // 如果没有发生异常,则表示调用成功 } catch (WebException ex) { Console.WriteLine("网络连接异常: " + ex.Message); currentRetry++; // 增加重试计数 } } if (success) { Console.WriteLine("调用WebService接口成功"); } else { Console.WriteLine("无法连接到WebService接口"); } } } ``` 在上述代码中,我们通过一个`while`循环来进行断网重传。如果发生`WebException`异常(表示网络连接失败),则增加重试计数并继续重试,直到达到重试次数上限或成功调用WebService接口为止。 你需要将`MyWebService`替换为实际的WebService代理类,`MyMethod`替换为实际的WebService接口方法名,并根据实际情况传递正确的参数。 请注意,这只是一个简单的示例代码,你可以根据具体需求进行修改和扩展,例如添加重试间隔、增加日志记录等。另外,断网重传功能也可以通过其他方法实现,如使用定时任务或消息队列等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值