C#获取客户端调用WebService接口原生的请求Xml

C#获取客户端调用WebService时生成的原生的请求xml字符串,生成的Xml可以直接在SoapUI中使用

新建Windows窗体应用程序GetRequestRawXmlForWebServiceDemo,将默认的Form1重命名为FormGetRequestRawXml,

FormGetRequestRawXml窗体设计如图:


添加测试可用的webservice【中英文双向翻译】: 

http://www.webxml.com.cn/WebServices/TranslatorWebService.asmx?wsdl

同时添加对System.Web的引用

新建Xml和实体类之间的转化以及XML格式化【换行、缩进、对齐】的操作类文件XmlSerializeUtil.cs

类XmlSerializeUtil源程序如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
 
namespace GetRequestRawXmlForWebServiceDemo
{
    /// <summary>
    /// XML与实例化类之间的转化
    /// </summary>
    public sealed class XmlSerializeUtil
    {
        /// <summary>
        /// 类的对象转换为xml字符串,
        /// 生成的xml的根节点就是T的类型名称
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string ObjectToXml<T>(T t, Encoding encoding)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                using (XmlTextWriter xmlWriter = new XmlTextWriter(ms, encoding))
                {
                    xmlSerializer.Serialize(xmlWriter, t);
                    return encoding.GetString(ms.ToArray()).Trim();
                }
            }
        }

        /// <summary>
        /// 将指定的对象写入Xml文件
        /// 又在MSDN上查找XmlIncludeAttribute的定义如下:允许 XmlSerializer 在它序列化或反序列化对象时识别类型。
        /// 所以我想是因为方法返回的类型其实是House类的子类,XmlSerializer在序列化时只能识别父类,而不能识别子类,所以导致序列化的错误。
        /// 所以我将[XmlInclude(typeof(SaleHouse))]和[XmlInclude(typeof(RentHouse))]同时加到WebService中,问题解决。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="xmlFilePath"></param>
        public static void ObjectToXml<T>(T t, string xmlFilePath, Encoding encoding)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
            using (StreamWriter writer = new StreamWriter(xmlFilePath, false, encoding))
            {
                xmlSerializer.Serialize(writer, t);
                writer.Close();
            }
        }

        /// <summary>
        /// 将实体对象转换成XML
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="obj">实体对象</param>
        public static string XmlSerialize<T>(T obj)
        {
            try
            {
                using (StringWriter sw = new StringWriter())
                {
                    Type t = obj.GetType();
                    XmlSerializer serializer = new XmlSerializer(obj.GetType());
                    serializer.Serialize(sw, obj);
                    sw.Close();
                    return sw.ToString();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("将实体对象转换成XML异常", ex);
            }
        }

        /// <summary>
        /// xml字符串转实体类,xml字符串的根节点一定要与类名一致,否则将产生错误
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlString"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static T XmlToObject<T>(string xmlString, Encoding encoding)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream(encoding.GetBytes(xmlString)))
            {
                return (T)xmlSerializer.Deserialize(ms);
            }
        }

        /// <summary>
        /// 将指定路径的xml文件转化为对应的T类型对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlFilePath"></param>
        /// <returns></returns>
        public static T XmlDeSerialize<T>(string xmlFilePath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (FileStream fs = new FileStream(xmlFilePath, FileMode.Open))
            {
                return (T)serializer.Deserialize(fs);
            }
        }

        /// <summary>
        /// 对xml节点进行换行,格式化对齐操作
        /// </summary>
        /// <param name="srcXml"></param>
        /// <returns></returns>
        public static string FormatXml(string srcXml)
        {
            string formattedXml = IndentedFormat(IndentedFormat(srcXml).Replace("><", ">\r\n<"));
            return formattedXml;
        }

        /// <summary>
        /// 对XML字符串进行换行缩进,格式化
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        private static string IndentedFormat(string xml)
        {
            string indentedText = string.Empty;
            try
            {
                XmlTextReader reader = new XmlTextReader(new StringReader(xml));
                reader.WhitespaceHandling = WhitespaceHandling.None;

                StringWriter indentedXmlWriter = new StringWriter();
                XmlTextWriter writer = CreateXmlTextWriter(indentedXmlWriter);
                writer.WriteNode(reader, false);
                writer.Flush();

                indentedText = indentedXmlWriter.ToString();
            }
            catch (Exception)
            {
                indentedText = xml;
            }
            return indentedText;
        }

        /// <summary>
        /// 写入四个缩进字符【空格】
        /// </summary>
        /// <param name="textWriter"></param>
        /// <returns></returns>
        private static XmlTextWriter CreateXmlTextWriter(TextWriter textWriter)
        {
            XmlTextWriter writer = new XmlTextWriter(textWriter);
            //将Tab转化为4个空格
            bool convertTabsToSpaces = true;
            if (convertTabsToSpaces)
            {
                writer.Indentation = 4;
                writer.IndentChar = ' ';
            }
            else
            {
                writer.Indentation = 1;
                writer.IndentChar = '\t';
            }
            writer.Formatting = Formatting.Indented;
            return writer;
        }
    }
}

新建类文件SoapUtil.cs,类SoapUtil用于获取客户端调用WebService时生成的原生的请求xml字符串,可以直接在SoapUI中使用。

类SoapUtil源程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace GetRequestRawXmlForWebServiceDemo
{
    /// <summary>
    /// 获取客户端调用WebService时生成的原生的请求xml字符串,可以直接在SoapUI中使用
    /// 斯内科 2022-06-19
    /// </summary>
    public class SoapUtil
    {
        /// <summary>
        /// 获取请求WebService原生的XML
        /// </summary>
        /// <typeparam name="TWebService">一个WebService类,继承于SoapHttpClientProtocol</typeparam>
        /// <param name="methodName">接口方法名</param>
        /// <param name="parameters">实参列表需和接口方法定义的参数类型和个数一致,无参数时一定要传入null</param>
        /// <param name="defaultNamespace">Xml命名空间,可以是任意的</param>
        /// <returns></returns>
        public static string GetRawXml<TWebService>(string methodName, object[] parameters, string defaultNamespace = "web") where TWebService : System.Web.Services.Protocols.SoapHttpClientProtocol
        {
            Type t = typeof(TWebService);
            MethodInfo methodInfo = t.GetMethod(methodName);
            ParameterInfo[] parameterInfos = methodInfo.GetParameters();
            System.Web.Services.WebServiceBindingAttribute webServiceBindingAttribute = t.GetCustomAttribute<System.Web.Services.WebServiceBindingAttribute>();
            if (webServiceBindingAttribute == null)
            {
                throw new Exception($"不是标准的WebService类名,没有找到特性WebServiceBindingAttribute");
            }
            System.Web.Services.Protocols.SoapDocumentMethodAttribute soapDocumentAttribute = methodInfo.GetCustomAttribute(typeof(System.Web.Services.Protocols.SoapDocumentMethodAttribute))
                as System.Web.Services.Protocols.SoapDocumentMethodAttribute;
            if (soapDocumentAttribute == null)
            {
                throw new Exception($"不是标准的WebService接口方法,没有找到特性SoapDocumentMethodAttribute");
            }
            if (!(parameterInfos.Length == 0 && parameters == null)
                && !(parameters != null && parameterInfos.Length == parameters.Length))
            {
                throw new Exception($"如果是无参数的方法,传入的参数值必须为null。如果是有参数的方法,实参个数必须与接口定义参数个数一致");
            }
            //string defaultNamespace = "web";//Xml命名空间,可以是任意的
            StringBuilder sb = new StringBuilder();
            //methodName方法名下的每个参数名
            for (int i = 0; i < parameterInfos.Length; i++)
            {
                string paraName = parameterInfos[i].Name;
                Type type = parameterInfos[i].ParameterType;
                if ((type.IsArray || type.IsClass) && type != typeof(string))
                {
                    string xmlTemp = XmlSerializeUtil.XmlSerialize(parameters[i]);
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.LoadXml(xmlTemp);
                    string parameterXml = xmlDoc.DocumentElement.InnerXml;
                    sb.AppendLine($"<{defaultNamespace}:{paraName}>{parameterXml}</{defaultNamespace}:{paraName}>");
                }
                else
                {
                    sb.AppendLine($"<{defaultNamespace}:{paraName}>{parameters[i]}</{defaultNamespace}:{paraName}>");
                }
            }
            string requestNamespace = soapDocumentAttribute.RequestNamespace;//请求XML命名空间
            if (string.IsNullOrWhiteSpace(requestNamespace))
            {
                requestNamespace = webServiceBindingAttribute.Namespace;
            }
            string parameterArrayXml = sb.ToString().Trim();
            string requestXml = $@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:{defaultNamespace}=""{requestNamespace}"">
   <soapenv:Header/>
   <soapenv:Body>
              <{defaultNamespace}:{methodName}>{parameterArrayXml}</{defaultNamespace}:{methodName}>
   </soapenv:Body>
</soapenv:Envelope>";
            //return requestXml;
            string formattedXml = XmlSerializeUtil.FormatXml(requestXml);
            return formattedXml;
        }
    }
}

窗体FormGetRequestRawXml主要程序如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GetRequestRawXmlForWebServiceDemo
{
    public partial class FormGetRequestRawXml : Form
    {
        public FormGetRequestRawXml()
        {
            InitializeComponent();
        }

        private void btnGetRequestXml_Click(object sender, EventArgs e)
        {
            rtxtRequestXml.Clear();
            try
            {
                rtxtRequestXml.AppendText("-----------------------第一个请求原生Xml:【中->英】-----------------------\n");
                TranslatorWebService.TranslatorWebService translatorWebService = new TranslatorWebService.TranslatorWebService();
                translatorWebService.Url = "http://www.webxml.com.cn/WebServices/TranslatorWebService.asmx?wsdl";
                translatorWebService.Timeout = 8000;
                string word = "中国";
                string xml = SoapUtil.GetRawXml<TranslatorWebService.TranslatorWebService>("getEnCnTwoWayTranslator", new object[] { word });
                rtxtRequestXml.AppendText(xml);
                string[] resultArray = translatorWebService.getEnCnTwoWayTranslator(word);
                MessageBox.Show(string.Join("\n", resultArray), "【中->英】翻译结果");

                rtxtRequestXml.AppendText("\n\n-----------------------第二个请求原生Xml:【英->中】-----------------------\n\n");

                word = "observer";
                xml = SoapUtil.GetRawXml<TranslatorWebService.TranslatorWebService>("getEnCnTwoWayTranslator", new object[] { word });
                rtxtRequestXml.AppendText(xml);
                resultArray = translatorWebService.getEnCnTwoWayTranslator(word);
                MessageBox.Show(string.Join("\n", resultArray), "【英->中】翻译结果");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "出错");
            }
        }
    }
}

运行结果如图:

 我们可以直接复制请求xml到SoapUI中进行测试,如图:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值