通过HttpWebRequest来请求webservice,Datatable无数据


webserivce似乎一下子变成远古的东西了。转到net6.0后,原引用服务的项目可以编译,但运行时提示找不到“System.ServiceModel”云云。那就不引用,直接用HttpWebRequest发送xml请求罗。

我们知道,asmx运行提示的内容已比较清晰的说明这个过程该如何调用。

好吧,其实早有人做好了。

于是拿来使用,确实不错。可是在使用DataTable入参的时候有问题,服务端得不到DataTable的数据。其实问题就是上图的 xmlxml应是什么样的格式。于是想到WireShark监控一下net40下的网络数据来获取DataTable的XML格式。如果不知道如何用,推荐大家看一篇老文。

但没有经过网卡的请求不会被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。

修改了一个上面提到的文章中一个方法,

代码如下:

private static byte[] EncodeParsToSoap(Hashtable Pars, String XmlNs, String MethodName)
{            
    XmlDocument doc = new XmlDocument();
    doc.LoadXml("");
    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("", "");//解决DataTable入参没有数据问题
    content = content.Replace("", "");//解决DataSet入参没有数据问题。
    return Encoding.UTF8.GetBytes(content);
}

好了,我们写一个代理类(继承自DispatchProxy,在remoting时代用RealProxy),照着webservice写一个interface,借助代理类,WebServFactory写一个CreateClient方法,以后就可以这样来调用上面的asmx了。

IWebTest web = WebServFactory.CreateClient("http://192.168.4.3:7492/TestService.asmx");
DataTable result = web.TransTable(table);

问题好象解决了:)

相关