C# 调用Java的WebService的3种方式

摘要:
˃[系统配置][系统配置][系统配置]相信就是soapenv:Header这里的问题了,C#没soapenv:Header这些东西的网上查了好多类似下面的https://www.cnblogs.com/o2ds/p/4093413.htmlC#访问Java的WebService添加SOAPHeader验证的问题都没有用后来尝试sopui及xmlspy创建soap,直接发送xml,终于试出来了,然后C#使用httppost调用webservice,成功了。
C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll调用、动态调用

关于soapheader调用,可以参考

C#调用Java的WebService添加SOAPHeader验证

1.问题描述

调用的Java的webservice

string Invoke(string func, string reqXml)

使用C#直接调用一直报错。

webservice提供方有说明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
身份验证采用对SOAP身份认证(用户名/密码验证/序列号)的方式部署,设定用户名和密码由系统配置,所有文本内容编码选择UTF-8编码规范
<?xmlversion='1.0' encoding='utf-8'?>
<soapenv:Envelopexmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<vc:Authenticationxmlns: vc ="http://ant.com">
<vc:Username>[系统配置] </vc:Username>
<vc:Password>[系统配置]</vc:Password>
<vc:SerialNo>[系统配置]</vc:SerialNo>
</vc:Authentication>
</soapenv:Header>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>

相信就是soapenv:Header这里的问题了,C# 没soapenv:Header这些东西的

网上查了好多类似下面的

https://www.cnblogs.com/o2ds/p/4093413.html

C#访问Java的WebService添加SOAPHeader验证的问题

都没有用

后来尝试sopui及xmlspy创建soap,直接发送xml,终于试出来了,然后C#使用http post调用webservice,成功了。

2.问题解决1

C#拼接的需要http post的soap字符串如下

</SOAP-ENV:Header> 照搬给的文档里的字符串
<SOAP-ENV:Body> 为调用函数,string Invoke(string func, string reqXml) 函数名Invoke,两个参数,自行理解吧
注意:里面的 换行标志都要保留,不然都是报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
stringsoap ="<?xml version="1.0" encoding="utf-8"?> "+
"<SOAP-ENV:Envelope "+
"xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" "+
"xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" "+
"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" "+
"xmlns:xsd="http://www.w3.org/2001/XMLSchema"> "+
"<SOAP-ENV:Header> "+
"<vc:Authentication "+
"xmlns:vc="http://ant.com"> "+
"<vc:Username>xx</vc:Username> "+
"<vc:Password>xxx</vc:Password> "+
"<vc:SerialNo>xxxx</vc:SerialNo> "+
"</vc:Authentication> "+
"</SOAP-ENV:Header> "+
"<SOAP-ENV:Body> "+
"<m:Invoke "+
"xmlns:m="http://tempuri.org/"> "+
"<m:func>"+ jkid +"</m:func> "+
"<m:reqXml>"+ HttpUtility.HtmlEncode(xml) +"</m:reqXml> "+
"</m:Invoke> "+
"</SOAP-ENV:Body> "+
"</SOAP-ENV:Envelope>";

然后发送,随便找个http post的代码就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
publicstaticstringGetSOAPReSource(stringurl,stringdatastr)
{
try
{
//request
Uri uri =newUri(url);
WebRequest webRequest = WebRequest.Create(uri);
webRequest.ContentType ="text/xml; charset=utf-8";
webRequest.Method ="POST";
using(Stream requestStream = webRequest.GetRequestStream())
{
byte[] paramBytes = Encoding.UTF8.GetBytes(datastr.ToString());
requestStream.Write(paramBytes, 0, paramBytes.Length);
}
//response
WebResponse webResponse = webRequest.GetResponse();
using(StreamReader myStreamReader =newStreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
{
stringresult ="";
returnresult = myStreamReader.ReadToEnd();
}
}
catch(Exception ex)
{
throwex;
}
}

3.问题解决2

发现还是报错,http 500错误,和之前不一样,但依然不对

研究webservice的wsdl发现了问题

C# 调用Java的WebService的3种方式第1张

调用时加上

1
<strong>webRequest.Headers.Add("SOAPAction","http://tempuri.org/IAjsjService/Invoke");<br><br></strong>终于成功了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
publicstaticstringGetSOAPReSource(stringurl,stringdatastr)
{
try
{
//request
Uri uri =newUri(url);
WebRequest webRequest = WebRequest.Create(uri);
webRequest.ContentType ="text/xml; charset=utf-8";
webRequest.Headers.Add("SOAPAction","http://tempuri.org/IAjsjService/Invoke");
webRequest.Method ="POST";
using(Stream requestStream = webRequest.GetRequestStream())
{
byte[] paramBytes = Encoding.UTF8.GetBytes(datastr.ToString());
requestStream.Write(paramBytes, 0, paramBytes.Length);
}
//response
WebResponse webResponse = webRequest.GetResponse();
using(StreamReader myStreamReader =newStreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
{
stringresult ="";
returnresult = myStreamReader.ReadToEnd();
}
}
catch(Exception ex)
{
throwex;
}
}

其他调用webservice的方式:

上一篇链接如上,更像是Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)来处理xml,解决复杂的认证

又遇到一家

复制代码
身份验证采用对SOAP身份认证(用户名/密码验证/序列号)的方式部署,设定用户名和密码由系统配置,所有文本内容编码选择UTF-8编码规范
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<vc:Authentication xmlns: vc ="http://ant.com">
<vc:Username>[系统配置] </vc:Username>
<vc:Password>[系统配置]</vc:Password>
<vc:SerialNo>[系统配置]</vc:SerialNo >
</vc:Authentication>
</soapenv:Header>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope> 
复制代码

wsdl的xml如下

<?xml version="1.0" encoding="utf-8"?><wsdl:definitions name="AjsjService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"><wsdl:types><xsd:schema targetNamespace="http://tempuri.org/Imports"><xsd:import schemaLocation="vehcheck0.xml" namespace="http://tempuri.org/"/><xsd:import schemaLocation="vehcheck1.xml" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/></xsd:schema></wsdl:types><wsdl:message name="IAjsjService_Invoke_InputMessage"><wsdl:part name="parameters" element="tns:Invoke"/></wsdl:message><wsdl:message name="IAjsjService_Invoke_OutputMessage"><wsdl:part name="parameters" element="tns:InvokeResponse"/></wsdl:message><wsdl:message name="IAjsjService_TrffpnCall_InputMessage"><wsdl:part name="parameters" element="tns:TrffpnCall"/></wsdl:message><wsdl:message name="IAjsjService_TrffpnCall_OutputMessage"><wsdl:part name="parameters" element="tns:TrffpnCallResponse"/></wsdl:message><wsdl:portType name="IAjsjService"><wsdl:operation name="Invoke"><wsdl:input wsaw:Action="http://tempuri.org/IAjsjService/Invoke" message="tns:IAjsjService_Invoke_InputMessage"/><wsdl:output wsaw:Action="http://tempuri.org/IAjsjService/InvokeResponse" message="tns:IAjsjService_Invoke_OutputMessage"/></wsdl:operation><wsdl:operation name="TrffpnCall"><wsdl:input wsaw:Action="http://tempuri.org/IAjsjService/TrffpnCall" message="tns:IAjsjService_TrffpnCall_InputMessage"/><wsdl:output wsaw:Action="http://tempuri.org/IAjsjService/TrffpnCallResponse" message="tns:IAjsjService_TrffpnCall_OutputMessage"/></wsdl:operation></wsdl:portType><wsdl:binding name="BasicHttpBinding_IAjsjService" type="tns:IAjsjService"><soap:binding transport="http://schemas.xmlsoap.org/soap/http"/><wsdl:operation name="Invoke"><soap:operation soapAction="http://tempuri.org/IAjsjService/Invoke"  /><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body use="literal"/></wsdl:output></wsdl:operation><wsdl:operation name="TrffpnCall"><soap:operation soapAction="http://tempuri.org/IAjsjService/TrffpnCall"  /><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body use="literal"/></wsdl:output></wsdl:operation></wsdl:binding><wsdl:service name="AjsjService"><wsdl:port name="BasicHttpBinding_IAjsjService" binding="tns:BasicHttpBinding_IAjsjService"><soap:address location="http://ip:8000/v"/></wsdl:port></wsdl:service></wsdl:definitions>

使用添加服务引用加到项目里

C# 调用Java的WebService的3种方式第4张

不要用高级那里的添加web引用添加,不然后面没法做

生成的Reference.cs如下

复制代码
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:4.0.30319.1026
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

namespace v {
    
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="V.IAjsjService")]
    public interface IAjsjService {
        
        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAjsjService/Invoke", ReplyAction="http://tempuri.org/IAjsjService/InvokeResponse")]
        string Invoke(string func, string reqXml);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public interface IAjsjServiceChannel : v.IAjsjService, System.ServiceModel.IClientChannel {
    }
    
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public partial class AjsjServiceClient : System.ServiceModel.ClientBase<v.IAjsjService>, v.IAjsjService {
        
        public AjsjServiceClient() {
        }
        
        public AjsjServiceClient(string endpointConfigurationName) : 
                base(endpointConfigurationName) {
        }
        
        public AjsjServiceClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }
        
        public AjsjServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }
        
        public AjsjServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress) {
        }
        
        public string Invoke(string func, string reqXml) {
            return base.Channel.Invoke(func, reqXml);
        }
    }
}
复制代码

调用方法:

定义soapheader

复制代码
public class MySoapHeader
    {
        string username;//用户名
        string password;//密码
        string serialNo;//序列号

        public MySoapHeader()
        { }

        public MySoapHeader(string u, string p, string s)
        {
            Username = u;
            Password = p;
            SerialNo = s;
        }

        public string Username
        {
            get { return username; }
            set { username = value; }
        }

        public string Password
        {
            get { return password; }
            set { password = value; }
        }
        public string SerialNo
        {
            get { return serialNo; }
            set { serialNo = value; }
        }

    }
复制代码

调用

复制代码
MySoapHeader myHeader = new MySoapHeader(m_user, m_pw, m_serial);

            ServiceReference.AjsjServiceClient client = new ServiceReference.AjsjServiceClient("BasicHttpBinding_IAjsjService", m_serverUrl);
            using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
            {
               
               MessageHeader header = MessageHeader.CreateHeader("Authentication", "http://ant.com", myHeader);
                OperationContext.Current.OutgoingMessageHeaders.Add(header);
                client.Invoke(func, strXml);
               
复制代码

1.直接调用

已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL。这个比较常见也很简单

即有完整的webservice文件目录如下图所示,

C# 调用Java的WebService的3种方式第11张

也可以在本地IIS根据webservice文件目录新发布一个webservice,然后程序动态调用,修改Url

1
publicnewstringUrl {set;get; }

2.根据wsdl文件生成webservice 的.cs文件 及 生成dll C#调用

有时没有这么多文件,只有wsdl文件

wsdl文件可以有别人提供或者根据webservice地址获取:

http://localhost:8888/WS.asmx?wsdl

C# 调用Java的WebService的3种方式第12张

Visual Studio 2013->Visual Studio Tools->VS2013 开发人员命令提示

C# 调用Java的WebService的3种方式第13张

命令行输入

wsdlE:WS.wsdl/out:WS.cs

E:WS.wsdl是wsdl文件存储路径,也可以是http://localhost:8888/WS.asmx?wsdl
不报错的话,看路径下Program FilesMicrosoft Visual Studio 12.0WS.cs已经自动生成
.cs文件看函数声明,结构体等都非常方便
然后命令行执行
csc /t:libraryWS.cs
同样的路径下,生成了WS.dll,拷贝出去放到项目文件夹下,C# winform程序也可以添加引用了。
生成的文件默认在这里:
C# 调用Java的WebService的3种方式第14张
默认生成的SOAP版本为1.1,可以

G:Program FilesMicrosoft Visual Studio 12.0>wsdl E:e.wsdl /protocol:SOAP12 /out:e.cs

来指定1.2

3.C# 动态调用WebService

在C#程序中,若要调用WebService,一般是采用"添加Web引用"的方式来实现的。但如果此WebService的URL是在程序运行过程中才能获得的,那怎么办呢?那就必须是"动态"调用这个WebService了。

举个使用它的例子:
 object[] args = new object[1];  
 args.SetValue("cyy_JS", 0);             
DataTable dt = WebServiceHelper.InvokeWebService("http://192.168.0.10/DBMS_CYY/DBMS_Service.asmx", "GetUserTreeListData", args) as DataTable;
恩~有点麻烦,这意味着每次我都要把想调用的函数的参数组织成一个object[]才行,且每次调用InvokeWebService都是在内存中创建动态程序集,效率极低。则次种方法绝对没有直接用“实例名.方法名(参数列表)”来的舒服。
我把它放到一个叫WebServiceHelper.cs的类里面了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
usingSystem.IO;
usingSystem.Web.Services.Description;
usingMicrosoft.CSharp;
usingSystem.CodeDom.Compiler;
usingSystem.CodeDom;
/// <summary>
/// 动态调用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="classname">类名</param>
/// <param name="methodname">方法名(模块名)</param>
/// <param name="args">参数列表</param>
/// <returns>object</returns>
publicstaticobjectInvokeWebService(stringurl,stringclassname,stringmethodname,object[] args)
{
string@namespace="ServiceBase.WebService.DynamicWebLoad";
if(classname ==null|| classname =="")
{
classname = WebServiceHelper.GetClassName(url);
}
//获取服务描述语言(WSDL)
WebClient wc =newWebClient();
Stream stream = wc.OpenRead(url +"?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
ServiceDescriptionImporter sdi =newServiceDescriptionImporter();
sdi.AddServiceDescription(sd,"","");
CodeNamespace cn =newCodeNamespace(@namespace);
//生成客户端代理类代码
CodeCompileUnit ccu =newCodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc =newCSharpCodeProvider();
ICodeCompiler icc = csc.CreateCompiler();
//设定编译器的参数
CompilerParameters cplist =newCompilerParameters();
cplist.GenerateExecutable =false;
cplist.GenerateInMemory =true;
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");
//编译代理类
CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
if(true== cr.Errors.HasErrors)
{
System.Text.StringBuilder sb =newStringBuilder();
foreach(CompilerError ceincr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
thrownewException(sb.ToString());
}
//生成代理实例,并调用方法
System.Reflection.Assembly assembly = cr.CompiledAssembly;
Type t = assembly.GetType(@namespace+"."+ classname,true,true);
objectobj = Activator.CreateInstance(t);
System.Reflection.MethodInfo mi = t.GetMethod(methodname);
returnmi.Invoke(obj, args);
}
privatestaticstringGetClassName(stringurl)
{
string[] parts = url.Split('/');
string[] pps = parts[parts.Length - 1].Split('.');
returnpps[0];
}

参考http://blog.csdn.net/chuxiamuxiang/article/details/5731988

免责声明:文章转载自《C# 调用Java的WebService的3种方式》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C++连接mysql数据库的两种方法【学习笔记】卷积神经网络下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Cxf -wsdl2java 使用参数介绍

wsdl2java -h 可以得到详细的参考文档: G:cxfapache-cxf-3.1.6in>wsdl2java -h wsdl2java -fe|-frontend <front-end-name> -db|-databinding <data-binding-name> -wv <wsdl-version...

对Collections的遍历删除方式

以collections的子类List(Arraylist)为例 List<String> list=new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d");...

字符串补位

7.1.6 插入和填充字符串String类包含了在一个字符串中插入新元素的方法,可以用Insert在任意位置插入任意字符。而使用PadLeft/PadRight方法,可以在一个字符串的左右两侧进行字符填充。 1.Insert方法Insert方法用于在一个字符串的指定位置插入另一个字符串,从而构造一个新的串。Insert方法也有多个重载形式,最常用的为: p...

【转】C#字符串连接的效率问题

C#字符串连接常用的四种方式:StringBuilder、+、string.Format、List<string>。 1.+的方式 string sql = "update tableName set int1=" + int1.ToString() + ",int2=" + int2.ToString() + ",int3=" + int3....

HBase性能优化方法总结

4.1 HBase性能优化方法总结(一):表的设计 4.1.1 Pre-Creating Regions 默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候,所有的HBase客户端都向这一个region写数据,直到这个region足够大了才进行切分。一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样...

phpmyadmin误删表后的恢复过程(心惊胆跳啊)

话说今天不知道是抽风了还是失魂了,在用phpmyadmin删除测试数据时,竟然将整个表删除了: 等程序运行出错时,才出现整个表都没有了,而且之前也没有备份好!这下蛋疼了,这个可是production服务器,里面的数据可不能丢啊! 服务器是linux的,我不是很熟悉,也不知道mysql装在哪。 无奈之下,google,发现有不少人也有像我一样犯傻的一回,...