使用ASIHttpRequest调用WebService

转自  http://www.cocoachina.com/bbs/read.php?tid=98388


工作中,使用iPhone作为已有产品的移动终端,目前做能想到最理想的方式就是恳求产品提供WebService了,还是老习惯,坚决不要零散的代码,继续整理为通用的类,便于拉壮丁快速开发,虽然目前的壮丁就俺一个,hoho

再次利用现有的资源,使用了ASIHttpRequest v1.8.1,因为项目中使用了Windows集成验证,而这个东西正好提供了响应的验证方式,爽歪歪了。

还是那句话:只是单纯的希望,大家都能有共享学习的精神!

再一个,项目都是.Net相关的,在浏览器中访问.Net WebService的asmx文件时,会返回一系列帮助文件,让我们了解这个WebService有几个调用方法,每个方法的入口参数是什么,返回值是什么,这次使用了SOAP1.1的规范。

再再一个,这个类并不完善,WebService某个方法的参数,必须是简单的数据类型,如数值、字符等等,不支持数据集等对象,等以后需要了再完善吧,呵呵。

再再再一个,调用后的响应解析,是另一个课题,不在这里讲啦,预报下,如果响应中包含了.Net的数据集,也是自己写了通用类可以解析滴,嘎嘎。

再再再再一个,保证是最后一个再了,代码里面看到这个 [Constant sharedConstant].P_SYSTEM_URL ,就去看看前一篇文章吧,单例模式实现常量存储,哈哈。



1、先看看调用说明:
自定义WebService访问类,需要使用下面这个字符串作为SOAP请求,通过POST的方式,提交给WebService

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. POST /iwscooperationws/todocenter.asmx HTTP/1.1  
  2. Host: 192.168.1.11  
  3. Content-Type: text/xml; charset=utf-8  
  4. Content-Length: length  
  5. SOAPAction: "http://iws.CP.ws/GetWorkflowToDoCount"  
  6.    
  7. <?xml version="1.0" encoding="utf-8"?>  
  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/">  
  9.   <soap:Body>  
  10.     <GetWorkflowToDoCount xmlns="http://iws.CP.ws/">  
  11.       <UserName>string</UserName>  
  12.     </GetWorkflowToDoCount>  
  13.   </soap:Body>  
  14. </soap:Envelope>  


?
在上述的XML中,可以看到这个asmx提供了一个GetWorkflowToDoCount的方法,其参数是UserName,其中的 http://iws.CP.ws/ 是WebService中自己定义的命名空间。经过对几个WebService的实验发现,除了这几个字符串之外,都是不变的东西,那么这个长长的串串,就复制粘贴留下来,等下一步利用之。



2、.h文件中的声明,注释都放到了.m文件中,这是个人习惯:
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. + (ASIHTTPRequest *)getASISOAP11Request:(NSString *) WebURL  
  2.                          webServiceFile:(NSString *) wsFile  
  3.                            xmlNameSpace:(NSString *) xmlNS  
  4.                          webServiceName:(NSString *) wsName  
  5.                            wsParameters:(NSMutableArray *) wsParas;  
  6.    
  7. + (NSString *)getSOAP11WebServiceResponse:(NSString *) WebURL  
  8.                            webServiceFile:(NSString *) wsFile  
  9.                              xmlNameSpace:(NSString *) xmlNS  
  10.                            webServiceName:(NSString *) wsName  
  11.                              wsParameters:(NSMutableArray *) wsParas;  
  12.    
  13. + (NSString *)getSOAP11WebServiceResponseWithNTLM:(NSString *) WebURL  
  14.                                    webServiceFile:(NSString *) wsFile  
  15.                                      xmlNameSpace:(NSString *) xmlNS  
  16.                                    webServiceName:(NSString *) wsName  
  17.                                      wsParameters:(NSMutableArray *) wsParas  
  18.                                         userName:(NSString *) userName  
  19.                                          passWord:(NSString *) passWord;  
  20.    
  21. + (NSString *)checkResponseError:(NSString *) theResponse;  


?

3、.m文件的实现之一,生成ASIHttpRequest请求:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2. //Mark: 生成SOAP1.1版本的ASIHttp请求 
  3.  参数 webURL:                远程WebService的地址,不含*.asmx 
  4.  参数 webServiceFile:        远程WebService的访问文件名,如service.asmx 
  5.  参数 xmlNS:                    远程WebService的命名空间 
  6.  参数 webServiceName:        远程WebService的名称 
  7.  参数 wsParameters:            调用参数数组,形式为[参数1名称,参数1值,参数2名称,参数2值⋯⋯],如果没有调用参数,此参数为nil 
  8.  */  
  9. + (ASIHTTPRequest *)getASISOAP11Request:(NSString *) WebURL  
  10.                          webServiceFile:(NSString *) wsFile  
  11.                            xmlNameSpace:(NSString *) xmlNS  
  12.                          webServiceName:(NSString *) wsName  
  13.                            wsParameters:(NSMutableArray *) wsParas  
  14. {  
  15.     //1、初始化SOAP消息体  
  16.     NSString * soapMsgBody1 = [[NSString alloc] initWithFormat:  
  17.                                @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"  
  18.                                "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n"  
  19.                                "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n"  
  20.                                "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"  
  21.                                "<soap:Body>\n"  
  22.                                "<%@ xmlns=\"%@\">\n", wsName, xmlNS];  
  23.     NSString * soapMsgBody2 = [[NSString alloc] initWithFormat:  
  24.                                @"</%@>\n"  
  25.                                "</soap:Body>\n"  
  26.                                "</soap:Envelope>", wsName];  
  27.        
  28.     //2、生成SOAP调用参数  
  29.     NSString * soapParas = [[NSString alloc] init];  
  30.     soapParas = @"";  
  31.     if (![wsParas isEqual:nil]) {  
  32.         int i = 0;  
  33.         for (i = 0; i < [wsParas count]; i = i + 2) {  
  34.             soapParas = [soapParas stringByAppendingFormat:@"<%@>%@</%@>\n",  
  35.                          [wsParas objectAtIndex:i],  
  36.                          [wsParas objectAtIndex:i+1],  
  37.                          [wsParas objectAtIndex:i]];  
  38.         }  
  39.     }  
  40.        
  41.     //3、生成SOAP消息  
  42.     NSString * soapMsg = [soapMsgBody1 stringByAppendingFormat:@"%@%@", soapParas, soapMsgBody2];  
  43.        
  44.     //请求发送到的路径  
  45.     NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", WebURL, wsFile]];  
  46.        
  47.     //NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];  
  48.     ASIHTTPRequest * theRequest = [ASIHTTPRequest requestWithURL:url];  
  49.     NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMsg length]];  
  50.        
  51.     //以下对请求信息添加属性前四句是必有的,第五句是soap信息。  
  52.     [theRequest addRequestHeader:@"Content-Type" value:@"text/xml; charset=utf-8"];  
  53.     [theRequest addRequestHeader:@"SOAPAction" value:[NSString stringWithFormat:@"%@%@", xmlNS, wsName]];  
  54.        
  55.     [theRequest addRequestHeader:@"Content-Length" value:msgLength];  
  56.     [theRequest setRequestMethod:@"POST"];  
  57.     [theRequest appendPostData:[soapMsg dataUsingEncoding:NSUTF8StringEncoding]];  
  58.        
  59.     [theRequest setDefaultResponseEncoding:NSUTF8StringEncoding];  
  60.        
  61.     return theRequest;  
  62. }  


?

4、.m文件的实现之二,同步调用WebService请求,返回响应字符串

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #pragma mark -  
  2. /* 
  3.  //Mark: 使用SOAP1.1同步调用WebService请求 
  4.  参数 webURL:                远程WebService的地址,不含*.asmx 
  5.  参数 webServiceFile:        远程WebService的访问文件名,如service.asmx 
  6.  参数 xmlNS:                    远程WebService的命名空间 
  7.  参数 webServiceName:        远程WebService的名称 
  8.  参数 wsParameters:            调用参数数组,形式为[参数1名称,参数1值,参数2名称,参数2值⋯⋯],如果没有调用参数,此参数为nil 
  9.  */  
  10. + (NSString *)getSOAP11WebServiceResponse:(NSString *) WebURL  
  11.                            webServiceFile:(NSString *) wsFile  
  12.                              xmlNameSpace:(NSString *) xmlNS  
  13.                            webServiceName:(NSString *) wsName  
  14.                              wsParameters:(NSMutableArray *) wsParas  
  15. {  
  16.     //创建请求  
  17.     ASIHTTPRequest * theRequest = [self getASISOAP11Request:WebURL  
  18.                                              webServiceFile:wsFile  
  19.                                                xmlNameSpace:xmlNS  
  20.                                              webServiceName:wsName  
  21.                                                wsParameters:wsParas];  
  22.        
  23.     //显示网络请求信息在status bar上  
  24.     [ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:YES];  
  25.        
  26.     //同步调用  
  27.     [theRequest startSynchronous];  
  28.     NSError *error = [theRequest error];  
  29.     if (!error) {  
  30.         return [theRequest responseString];  
  31.     }  
  32.     else {  
  33.         //出现调用错误,则使用错误前缀+错误描述  
  34.         return [NSString stringWithFormat:@"%@%@", [Constant sharedConstant].G_WEBSERVICE_ERROR, [error localizedDescription]];  
  35.     }  
  36. }  


?

5、.m文件实现之三,同步调用需要Windows集成验证的WebService请求,返回响应字符串:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #pragma mark -  
  2. /* 
  3.  //Mark: 使用SOAP1.1同步调用WebService请求,需提供Windows集成验证的用户名、密码和域 
  4.  参数 webURL:                远程WebService的地址,不含*.asmx 
  5.  参数 webServiceFile:        远程WebService的访问文件名,如service.asmx 
  6.  参数 xmlNS:                    远程WebService的命名空间 
  7.  参数 webServiceName:        远程WebService的名称 
  8.  参数 wsParameters:            调用参数数组,形式为[参数1名称,参数1值,参数2名称,参数2值⋯⋯],如果没有调用参数,此参数为nil 
  9.  参数 userName                用户名--目前来看,不需要输入域信息 
  10.  参数 passWord                密码 
  11.  */  
  12. + (NSString *)getSOAP11WebServiceResponseWithNTLM:(NSString *) WebURL  
  13.                                    webServiceFile:(NSString *) wsFile  
  14.                                      xmlNameSpace:(NSString *) xmlNS  
  15.                                    webServiceName:(NSString *) wsName  
  16.                                      wsParameters:(NSMutableArray *) wsParas  
  17.                                          userName:(NSString *) userName  
  18.                                          passWord:(NSString *) passWord  
  19. {  
  20.     //创建请求  
  21.     ASIHTTPRequest * theRequest = [self getASISOAP11Request:WebURL  
  22.                                              webServiceFile:wsFile  
  23.                                                xmlNameSpace:xmlNS  
  24.                                              webServiceName:wsName  
  25.                                                wsParameters:wsParas];  
  26.        
  27.     //集成验证NTLM用户名,密码和域设置  
  28.     [theRequest setUsername:userName];  
  29.     [theRequest setPassword:passWord];  
  30.     //[theRequest setDomain:doMain];  
  31.        
  32.     //显示网络请求信息在status bar上  
  33.     [ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:YES];  
  34.        
  35.     //同步调用  
  36.     [theRequest startSynchronous];  
  37.     NSError *error = [theRequest error];  
  38.     if (!error) {  
  39.         return [theRequest responseString];  
  40.     }  
  41.     else {  
  42.         //出现调用错误,则使用错误前缀+错误描述  
  43.         return [NSString stringWithFormat:@"%@%@", [Constant sharedConstant].G_WEBSERVICE_ERROR, [error localizedDescription]];  
  44.     }  
  45. }  


?

6、.m文件实现之四,响应字符串中是否包含错误信息,简单处理了下错误消息的中文显示:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #pragma mark -  
  2. /* 
  3.  //Mark: 检查WebService的Response是否包含错误信息 
  4.     如果未包含错误,则返回零长度字符串 
  5.     否则返回错误描述 
  6.     错误信息格式:错误前缀\n错误描述 
  7.  */  
  8. + (NSString *)checkResponseError:(NSString *) theResponse  
  9. {  
  10.     //检查消息是否包含错误前缀  
  11.     if (![theResponse hasPrefix:[Constant sharedConstant].G_WEBSERVICE_ERROR]) {  
  12.         return @"";  
  13.     }  
  14.     else {  
  15.         NSMutableString *sTemp = [[NSMutableString alloc] initWithString:theResponse];  
  16.         //获取错误前缀的范围  
  17.         NSRange range=[sTemp rangeOfString:[Constant sharedConstant].G_WEBSERVICE_ERROR];  
  18.         //剔除错误前缀  
  19.         [sTemp replaceCharactersInRange:range withString:@""];  
  20.            
  21.         NSString * errMsg = sTemp;  
  22.         //Authentication needed  
  23.         if ([sTemp isEqualToString:@"Authentication needed"]) {  
  24.             errMsg = @"用户登录失败!";  
  25.         }  
  26.         //The request timed out  
  27.         if ([sTemp isEqualToString:@"The request timed out"]) {  
  28.             errMsg = @"访问超时,请检查远程地址等基本设置!";  
  29.         }  
  30.         //The request was cancelled  
  31.         if ([sTemp isEqualToString:@"The request was cancelled"]) {  
  32.             errMsg = @"请求被撤销!";  
  33.         }  
  34.         //Unable to create request (bad url?)  
  35.         if ([sTemp isEqualToString:@"Unable to create request (bad url?)"]) {  
  36.             errMsg = @"无法创建请求,错误的URL地址!";  
  37.         }  
  38.         //The request failed because it redirected too many times  
  39.         if ([sTemp isEqualToString:@"The request failed because it redirected too many times"]) {  
  40.             errMsg = @"请求失败,可能是因为被重定向次数过多!";  
  41.         }  
  42.         //A connection failure occurred  
  43.         if ([sTemp isEqualToString:@"A connection failure occurred"]) {  
  44.             errMsg = @"网络连接错误,请检查无线或3G网络设置!";  
  45.         }  
  46.            
  47.         return errMsg;  
  48.     }  
  49. }  


?

7、开始调用啦:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //创建WebService的调用参数  
  2. NSMutableArray * wsParas = [[NSMutableArray alloc] initWithObjects:  
  3.                             @"UserName", [Constant sharedConstant].P_USER_NAME,  
  4.                             nil nil];  
  5.    
  6. //调用WebService,获取响应  
  7. NSString * theResponse = [WebService getSOAP11WebServiceResponseWithNTLM:[Constant sharedConstant].P_SYSTEM_URL          
  8.                                                           webServiceFile:[Constant sharedConstant].G_WS_TODOCENTER  
  9.                                                             xmlNameSpace:[Constant sharedConstant].G_WEBSERVICE_NAMESPACE  
  10.                                                           webServiceName:[Constant sharedConstant].G_WS_TODOCENTER_GETWORKFLOWTODOCOUNT  
  11.                                                             wsParameters:wsParas  
  12.                                                                 userName:[Constant sharedConstant].P_USER_NAME  
  13.                                                                 passWord:[Constant sharedConstant].P_PASSWORD];  
  14.    
  15. //检查响应中是否包含错误  
  16. NSString * errMsg = [WebService checkResponseError:theResponse];  
  17.    
  18. //接下来的代码就是检查errMsg有没有内容  
  19. //再接下来就是theResponse响应字符串的解析了  


?
注意这个调用例子里面的WebService的参数UserName和调用windows集成验证时提供的userName,是两回事啊⋯⋯
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值