通过HttpWebRequest来请求webservice,Datatable无数据
webserivce似乎一下子变成远古的东西了。转到net6.0后,原引用服务的项目可以编译,但运行时提示找不到“System.ServiceModel”云云。那就不引用,直接用HttpWebRequest发送xml请求罗。
我们知道,asmx运行提示的内容已比较清晰的说明这个过程该如何调用。
好吧,其实早有人做好了。
https://www.cnblogs.com/weicanpeng/p/5755987.html
于是拿来使用,确实不错。可是在使用DataTable入参的时候有问题,服务端得不到DataTable的数据。其实问题就是上图的 xmlxml应是什么样的格式。于是想到WireShark监控一下net40下的网络数据来获取DataTable的XML格式。如果不知道如何用,推荐大家看一篇老文https://www.cnblogs.com/A-yes/p/9894215.html。
但没有经过网卡的请求不会被WireShark监控。怎么办?
我首先要解决的是,将webservice给其他电脑使用。我开发的笔记本操作系统是家庭版,没有IIS,而我们调试的项目跑起来似乎只会监控127.0.0.1,端口不会绑定到对外的IP上。想到了Nginx。好了,nginx转发网卡的某个端口到127.0.0.1上我的webservice的端口。其他电脑终可以访问。拿起放了几年的小米笔记本(它的键盘很硬,是放了太久了吗?),终于发现多台电脑的好处了。得到抓包数据后,比较了两者的XML差异,我几乎要哭起来。
正常的XML有一个节点是这样的
....><DocumentElement xmlns=""><....
不正常的XML对应的节点是这样的
...><DocumentElement><...
在DataSet入参时也有类似情况,但节点是NewDataSet
正常的XML有一个节点是这样的
...><NewDataSet xmlns=""><...
服务端DataSet的Table中没有数据的XML是这样的
...><NewDataSet><...
这个xmlns=""怎么看都不可能是一个关键内容。相反一些xmlns不提供也没有问题。真让人无语。怎么处理,直接文本replace。
修改了一个上面提到的文章中一个方法,https://www.cnblogs.com/weicanpeng/p/5755987.html
代码如下:
private static byte[] EncodeParsToSoap(Hashtable Pars, String XmlNs, String MethodName) { XmlDocument doc = new XmlDocument(); doc.LoadXml("<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"></s:Envelope>"); XmlElement soapBody = doc.CreateElement("s", "Body", "http://schemas.xmlsoap.org/soap/envelope/"); //soapBody.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");//缺失的xmlns,不加也行 //soapBody.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");//缺失的xmlns,不加也行 XmlElement soapMethod = doc.CreateElement(MethodName); soapMethod.SetAttribute("xmlns", XmlNs); foreach (string k in Pars.Keys) { XmlElement soapPar = doc.CreateElement(k); soapPar.InnerXml = ObjectToSoapXml(Pars[k]); soapMethod.AppendChild(soapPar); } soapBody.AppendChild(soapMethod); doc.DocumentElement.AppendChild(soapBody); //return Encoding.UTF8.GetBytes(doc.OuterXml); string content = doc.OuterXml; content = content.Replace("<DocumentElement>", "<DocumentElement xmlns=\"\">");//解决DataTable入参没有数据问题 content = content.Replace("<NewDataSet>", "<NewDataSet xmlns=\"\">");//解决DataSet入参没有数据问题。 return Encoding.UTF8.GetBytes(content); }
好了,我们写一个代理类(继承自DispatchProxy,在remoting时代用RealProxy),照着webservice写一个interface,借助代理类,WebServFactory写一个CreateClient方法,以后就可以这样来调用上面的asmx了。
IWebTest web = WebServFactory.CreateClient<IWebTest>("http://192.168.4.3:7492/TestService.asmx"); DataTable result = web.TransTable(table);
问题好象解决了:)
需注意,我们自己的入参有以下几个情况
DateTime,需格式化为yyyy-MM-ddTHH:mm:ss....+8:00,当然直接ToString("O")就行了。但如果是DateTime?为null时,需要提供<FieldName xsi:nil=“true" />,可用以下代码生成这种null的节点。
XmlElement element = doc.CreateElement(nodeName); XmlAttribute attr = doc.CreateAttribute("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance"); attr.Value = "true"; element.SetAttributeNode(attr);
Boolean,提示小写格式的true\false。