使用ASIHttpRequest调用WebService
再次利用现有的资源,使用了ASIHttpRequest v1.8.1,因为项目中使用了Windows集成验证,而这个东西正好提供了响应的验证方式。
还是那句话:只是单纯的希望,大家都能有共享学习的精神!
再一个,项目都是.Net相关的,在浏览器中访问.Net WebService的asmx文件时,会返回一系列帮助文件,让我们了解这个WebService有几个调用方法,每个方法的入口参数是什么,返回值是什么,这次使用了SOAP1.1的规范。
再再一个,这个类并不完善,WebService某个方法的参数,必须是简单的数据类型,如数值、字符等等,不支持数据集等对象,等以后需要了再完善吧,呵呵。
再再再一个,调用后的响应解析,是另一个课题,不在这里讲啦,预报下,如果响应中包含了.Net的数据集,也是自己写了通用类可以解析滴,嘎嘎。
再再再再一个,保证是最后一个再了,代码里面看到这个 [Constant sharedConstant].P_SYSTEM_URL ,就去看看前一篇文章吧,单例模式实现常量存储,哈哈。
1、先看看调用说明:
自定义WebService访问类,需要使用下面这个字符串作为SOAP请求,通过POST的方式,提交给WebService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
POST /iwscooperationws/todocenter.asmx HTTP/1.1
Host: 192.168.1.11
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://iws.CP.ws/GetWorkflowToDoCount"
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
soap:Envelope
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd
=
"http://www.w3.org/2001/XMLSchema"
xmlns:soap
=
"http://schemas.xmlsoap.org/soap/envelope/"
>
<
soap:Body
>
<
GetWorkflowToDoCount
xmlns
=
"http://iws.CP.ws/"
>
<
UserName
>string</
UserName
>
</
GetWorkflowToDoCount
>
</
soap:Body
>
</
soap:Envelope
>
|
在上述的XML中,可以看到这个asmx提供了一个GetWorkflowToDoCount的方法,其参数是UserName,其中的 http://iws.CP.ws/是WebService中自己定义的命名空间。经过对几个WebService的实验发现,除了这几个字符串之外,都是不变的东西,那么这个长长的串串,就复制粘贴留下来,等下一步利用之。
2、.h文件中的声明,注释都放到了.m文件中,这是个人习惯:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
+ (ASIHTTPRequest *)getASISOAP11Request:(
NSString
*) WebURL
webServiceFile:(
NSString
*) wsFile
xmlNameSpace:(
NSString
*) xmlNS
webServiceName:(
NSString
*) wsName
wsParameters:(
NSMutableArray
*) wsParas;
+ (
NSString
*)getSOAP11WebServiceResponse:(
NSString
*) WebURL
webServiceFile:(
NSString
*) wsFile
xmlNameSpace:(
NSString
*) xmlNS
webServiceName:(
NSString
*) wsName
wsParameters:(
NSMutableArray
*) wsParas;
+ (
NSString
*)getSOAP11WebServiceResponseWithNTLM:(
NSString
*) WebURL
webServiceFile:(
NSString
*) wsFile
xmlNameSpace:(
NSString
*) xmlNS
webServiceName:(
NSString
*) wsName
wsParameters:(
NSMutableArray
*) wsParas
userName:(
NSString
*) userName
passWord:(
NSString
*) passWord;
+ (
NSString
*)checkResponseError:(
NSString
*) theResponse;
|
3、.m文件的实现之一,生成ASIHttpRequest请求:
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
|
/*
//Mark: 生成SOAP1.1版本的ASIHttp请求
参数 webURL: 远程WebService的地址,不含*.asmx
参数 webServiceFile: 远程WebService的访问文件名,如service.asmx
参数 xmlNS: 远程WebService的命名空间
参数 webServiceName: 远程WebService的名称
参数 wsParameters: 调用参数数组,形式为[参数1名称,参数1值,参数2名称,参数2值⋯⋯],如果没有调用参数,此参数为nil
*/
+ (ASIHTTPRequest *)getASISOAP11Request:(
NSString
*) WebURL
webServiceFile:(
NSString
*) wsFile
xmlNameSpace:(
NSString
*) xmlNS
webServiceName:(
NSString
*) wsName
wsParameters:(
NSMutableArray
*) wsParas
{
//1、初始化SOAP消息体
NSString
* soapMsgBody1 = [[
NSString
alloc] initWithFormat:
@
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n"
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n"
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n"
"<%@ xmlns=\"%@\">\n"
, wsName, xmlNS];
NSString
* soapMsgBody2 = [[
NSString
alloc] initWithFormat:
@
"</%@>\n"
"</soap:Body>\n"
"</soap:Envelope>"
, wsName];
//2、生成SOAP调用参数
NSString
* soapParas = [[
NSString
alloc] init];
soapParas = @
""
;
if
(![wsParas isEqual:
nil
]) {
int
i = 0;
for
(i = 0; i < [wsParas count]; i = i + 2) {
soapParas = [soapParas stringByAppendingFormat:@
"<%@>%@</%@>\n"
,
[wsParas objectAtIndex:i],
[wsParas objectAtIndex:i+1],
[wsParas objectAtIndex:i]];
}
}
//3、生成SOAP消息
NSString
* soapMsg = [soapMsgBody1 stringByAppendingFormat:@
"%@%@"
, soapParas, soapMsgBody2];
//请求发送到的路径
NSURL
* url = [
NSURL
URLWithString:[
NSString
stringWithFormat:@
"%@%@"
, WebURL, wsFile]];
//NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
ASIHTTPRequest * theRequest = [ASIHTTPRequest requestWithURL:url];
NSString
*msgLength = [
NSString
stringWithFormat:@
"%d"
, [soapMsg length]];
//以下对请求信息添加属性前四句是必有的,第五句是soap信息。
[theRequest addRequestHeader:@
"Content-Type"
value:@
"text/xml; charset=utf-8"
];
[theRequest addRequestHeader:@
"SOAPAction"
value:[
NSString
stringWithFormat:@
"%@%@"
, xmlNS, wsName]];
[theRequest addRequestHeader:@
"Content-Length"
value:msgLength];
[theRequest setRequestMethod:@
"POST"
];
[theRequest appendPostData:[soapMsg dataUsingEncoding:
NSUTF8StringEncoding
]];
[theRequest setDefaultResponseEncoding:
NSUTF8StringEncoding
];
return
theRequest;
}
|
4、.m文件的实现之二,同步调用WebService请求,返回响应字符串
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
|
#pragma mark -
/*
//Mark: 使用SOAP1.1同步调用WebService请求
参数 webURL: 远程WebService的地址,不含*.asmx
参数 webServiceFile: 远程WebService的访问文件名,如service.asmx
参数 xmlNS: 远程WebService的命名空间
参数 webServiceName: 远程WebService的名称
参数 wsParameters: 调用参数数组,形式为[参数1名称,参数1值,参数2名称,参数2值⋯⋯],如果没有调用参数,此参数为nil
*/
+ (
NSString
*)getSOAP11WebServiceResponse:(
NSString
*) WebURL
webServiceFile:(
NSString
*) wsFile
xmlNameSpace:(
NSString
*) xmlNS
webServiceName:(
NSString
*) wsName
wsParameters:(
NSMutableArray
*) wsParas
{
//创建请求
ASIHTTPRequest * theRequest = [
self
getASISOAP11Request:WebURL
webServiceFile:wsFile
xmlNameSpace:xmlNS
webServiceName:wsName
wsParameters:wsParas];
//显示网络请求信息在status bar上
[ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:
YES
];
//同步调用
[theRequest startSynchronous];
NSError
*error = [theRequest error];
if
(!error) {
return
[theRequest responseString];
}
else
{
//出现调用错误,则使用错误前缀+错误描述
return
[
NSString
stringWithFormat:@
"%@%@"
, [Constant sharedConstant].G_WEBSERVICE_ERROR, [error localizedDescription]];
}
}
|
5、.m文件实现之三,同步调用需要Windows集成验证的WebService请求,返回响应字符串:
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
|
#pragma mark -
/*
//Mark: 使用SOAP1.1同步调用WebService请求,需提供Windows集成验证的用户名、密码和域
参数 webURL: 远程WebService的地址,不含*.asmx
参数 webServiceFile: 远程WebService的访问文件名,如service.asmx
参数 xmlNS: 远程WebService的命名空间
参数 webServiceName: 远程WebService的名称
参数 wsParameters: 调用参数数组,形式为[参数1名称,参数1值,参数2名称,参数2值⋯⋯],如果没有调用参数,此参数为nil
参数 userName 用户名--目前来看,不需要输入域信息
参数 passWord 密码
*/
+ (
NSString
*)getSOAP11WebServiceResponseWithNTLM:(
NSString
*) WebURL
webServiceFile:(
NSString
*) wsFile
xmlNameSpace:(
NSString
*) xmlNS
webServiceName:(
NSString
*) wsName
wsParameters:(
NSMutableArray
*) wsParas
userName:(
NSString
*) userName
passWord:(
NSString
*) passWord
{
//创建请求
ASIHTTPRequest * theRequest = [
self
getASISOAP11Request:WebURL
webServiceFile:wsFile
xmlNameSpace:xmlNS
webServiceName:wsName
wsParameters:wsParas];
//集成验证NTLM用户名,密码和域设置
[theRequest setUsername:userName];
[theRequest setPassword:passWord];
//[theRequest setDomain:doMain];
//显示网络请求信息在status bar上
[ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:
YES
];
//同步调用
[theRequest startSynchronous];
NSError
*error = [theRequest error];
if
(!error) {
return
[theRequest responseString];
}
else
{
//出现调用错误,则使用错误前缀+错误描述
return
[
NSString
stringWithFormat:@
"%@%@"
, [Constant sharedConstant].G_WEBSERVICE_ERROR, [error localizedDescription]];
}
}
|
6、.m文件实现之四,响应字符串中是否包含错误信息,简单处理了下错误消息的中文显示:
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
|
#pragma mark -
/*
//Mark: 检查WebService的Response是否包含错误信息
如果未包含错误,则返回零长度字符串
否则返回错误描述
错误信息格式:错误前缀\n错误描述
*/
+ (
NSString
*)checkResponseError:(
NSString
*) theResponse
{
//检查消息是否包含错误前缀
if
(![theResponse hasPrefix:[Constant sharedConstant].G_WEBSERVICE_ERROR]) {
return
@
""
;
}
else
{
NSMutableString
*sTemp = [[
NSMutableString
alloc] initWithString:theResponse];
//获取错误前缀的范围
NSRange
range=[sTemp rangeOfString:[Constant sharedConstant].G_WEBSERVICE_ERROR];
//剔除错误前缀
[sTemp replaceCharactersInRange:range withString:@
""
];
NSString
* errMsg = sTemp;
//Authentication needed
if
([sTemp isEqualToString:@
"Authentication needed"
]) {
errMsg = @
"用户登录失败!"
;
}
//The request timed out
if
([sTemp isEqualToString:@
"The request timed out"
]) {
errMsg = @
"访问超时,请检查远程地址等基本设置!"
;
}
//The request was cancelled
if
([sTemp isEqualToString:@
"The request was cancelled"
]) {
errMsg = @
"请求被撤销!"
;
}
//Unable to create request (bad url?)
if
([sTemp isEqualToString:@
"Unable to create request (bad url?)"
]) {
errMsg = @
"无法创建请求,错误的URL地址!"
;
}
//The request failed because it redirected too many times
if
([sTemp isEqualToString:@
"The request failed because it redirected too many times"
]) {
errMsg = @
"请求失败,可能是因为被重定向次数过多!"
;
}
//A connection failure occurred
if
([sTemp isEqualToString:@
"A connection failure occurred"
]) {
errMsg = @
"网络连接错误,请检查无线或3G网络设置!"
;
}
return
errMsg;
}
}
|
7、开始调用啦:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//创建WebService的调用参数
NSMutableArray
* wsParas = [[
NSMutableArray
alloc] initWithObjects:
@
"UserName"
, [Constant sharedConstant].P_USER_NAME,
nil
];
//调用WebService,获取响应
NSString
* theResponse = [WebService getSOAP11WebServiceResponseWithNTLM:[Constant sharedConstant].P_SYSTEM_URL
webServiceFile:[Constant sharedConstant].G_WS_TODOCENTER
xmlNameSpace:[Constant sharedConstant].G_WEBSERVICE_NAMESPACE
webServiceName:[Constant sharedConstant].G_WS_TODOCENTER_GETWORKFLOWTODOCOUNT
wsParameters:wsParas
userName:[Constant sharedConstant].P_USER_NAME
passWord:[Constant sharedConstant].P_PASSWORD];
//检查响应中是否包含错误
NSString
* errMsg = [WebService checkResponseError:theResponse];
//接下来的代码就是检查errMsg有没有内容
//再接下来就是theResponse响应字符串的解析了
|