1. 程式人生 > >網路程式設計(二)SOAP, WSDL, Web Service

網路程式設計(二)SOAP, WSDL, Web Service

上篇文章講到了,使用網上一個工具WSDL2ObjC.app來把已有的 wsdl轉化為ios可使用的程式碼, 然後通過這部分程式碼進行soap的請求與獲取響應。

但是上面這種方式的劣勢也不言自明, 所以下面將用最原始的方式來做同樣的事情。

這裡首先需要感謝的提供這個網站供使用的網址:http://www.ripedevelopment.com/webservices/LocalTime.asmx

好, 我們開始吧!

1。 我們開啟上面這個網址,左邊, 我們可以看到兩個同名方法, LocalTimeByZipCode, 下面一個是用來binding LocalTimeSoap12的, 先不管它, 開啟上面這個。

開啟後, 可以看到這個方法的Overview描述資訊,Input Parameters, Output Parameters.

然後點開Test Form, 輸入一個zipcode可以進行線上測試,如輸入12345. 這個測試可以表明,這個web service目前是可以提供服務的。

再點選, Message Layout, 

好的, 我們可以看到有Soap, HTTP Get, HTTP Post三種方式的使用方法。 這裡我們側重於講SOAP方式。

SOAP部分中, 上面框中顯示的是發起請求時, 需要提交的SOAP內容包, 下面顯示提正常回復的SOAP資訊包。

這就是我們要看的內容:

POST /webservices/LocalTime.asmx


SOAPAction: http://www.ripedev.com/LocalTimeByZipCode
Content-Type: text/xml; charset=utf-8
Content-Length: string
Host: string

<?xml version="1.0" encoding="utf-16"?>
<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>
<LocalTimeByZipCode xmlns="http://www.ripedev.com/">
<ZipCode>string</ZipCode>
</LocalTimeByZipCode>
</soap:Body>
</soap:Envelope>

然後我們建立我們的xcode專案, 和先前的一樣, 建一個按鈕,再一個textView來進行顯示即可。

這是我按鈕的事件:

- (void)startRequestToWsdl2:(id)sender {

    NSString *soapMessage = [NSString stringWithFormat:

@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"

"<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/\">\n"

"<soap:Body>\n"

"<LocalTimeByZipCode xmlns=\"http://www.ripedev.com/\">"

"<ZipCode>12345</ZipCode>\n"

                            "</LocalTimeByZipCode>\n"

"</soap:Body>\n"

"</soap:Envelope>\n"];

// 順便插一句, SOAP中,Header部分可有可無 , Fault部分可有可無, 但Body和Envelope必須有.

    // 上面這部分幾乎按SOAP給的格式就行了。下面這個地址是來自於哪裡呢, 就來自於這個網址,即上面我們要感謝的這個網址:http://www.ripedevelopment.com/webservices/LocalTime.asmx

NSString *address =@"http://www.ripedevelopment.com/webservices/LocalTime.asmx";

NSURL* url = [NSURLURLWithString:address];

NSMutableURLRequest *theRequest = [NSMutableURLRequestrequestWithURL:url];

// 然後就是text/xml, 和content-Length必須有。

[theRequest addValue: @"text/xml; charset=utf-8"forHTTPHeaderField:@"Content-Type"];

    NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];

    [theRequest addValue: msgLength forHTTPHeaderField:@"Content-Length"];

// 下面這行, 後面SOAPAction是規範, 而下面這個網址來自哪裡呢,來自於上面加紅加粗的部分。

[theRequest addValue: @"http://www.ripedev.com/LocalTimeByZipCode"forHTTPHeaderField:@"SOAPAction"];

[theRequestsetHTTPMethod:@"POST"];

[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *theConnection = [[NSURLConnectionalloc] initWithRequest:theRequestdelegate:self];

    if(theConnection) {

        webData = [[NSMutableData data] retain];

    } else {

NSLog(@"theConnection is NULL");

    }

好的, 上面已經把請求給發起了, 下面我們接收資料,並進行XMLParse解析。

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

    [webDatasetLength: 0];

NSLog(@"connection: didReceiveResponse:1");

}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

    [webDataappendData:data];

NSLog(@"connection: didReceiveData:2");

}

//如果電腦沒有連線網路,則出現此資訊(不是網路伺服器不通)

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

NSLog(@"ERROR with theConenction");

    [connection release];

    [webDatarelease];

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

{

NSLog(@"3 DONE. Received Bytes: %d", [webDatalength]);

NSString *theXML = [[NSStringalloc] initWithBytes: [webDatamutableBytes] length:[webDatalength] encoding:NSUTF8StringEncoding];

NSLog(@"received data=%@", theXML);

    [theXML release];

//重新載入xmlParser

if(xmlParser) {

        [xmlParserrelease];

    }

xmlParser = [[NSXMLParseralloc] initWithData:webData];

    [xmlParsersetDelegate: self];

    [xmlParsersetShouldResolveExternalEntities:YES];

    [xmlParser parse];

    [connection release];

}

// 上面完成了資料的接收, 下面進行NSXMLParser 的解析。

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName

   attributes: (NSDictionary *)attributeDict

{

NSLog(@"4 parser didStarElemen: namespaceURI: attributes:%@", elementName);

if( [elementNameisEqualToString:@"LocalTimeByZipCodeResult"]) {

        if(!soapResults) {

            soapResults = [[NSMutableString alloc] init];

        }

recordResults =YES;

    }

}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

{

NSLog(@"5 parser: foundCharacters:");

if(recordResults) {

        [soapResultsappendString: string];

    }

}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

{

NSLog(@"6 parser: didEndElement:");

if( [elementNameisEqualToString:@"LocalTimeByZipCodeResult"]) {

recordResults =FALSE;

NSLog(@"receivedResult timezone=%@",soapResults);

        [soapResultsrelease];

        soapResults = nil;

NSLog(@"hoursOffset result");

    }

}

- (void)parserDidStartDocument:(NSXMLParser *)parser{

NSLog(@"-------------------start--------------");

}

- (void)parserDidEndDocument:(NSXMLParser *)parser{

NSLog(@"-------------------end--------------");

}


我們再查一下,這個web service返回的資料是怎麼樣的?如下: HTTP/1.0 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: string

<?xml version="1.0" encoding="utf-16"?>
<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>
<LocalTimeByZipCodeResponse xmlns="http://www.ripedev.com/">
<LocalTimeByZipCodeResult>string</LocalTimeByZipCodeResult>
</LocalTimeByZipCodeResponse>
</soap:Body>
</soap:Envelope>
// 從上面加粗, 加綠色的文字,我們可以知道, 我們要找的內容在這裡。所以這也是我們為什麼在Parse的解析中要使用這個LocalTimeByZipCodeResult的原因 好吧, 執行看看吧, 資料已經返回了。 (再PS一下, 上面是直接取數的, 真實的環境中, 應該採用執行緒的方式,以免影響介面主執行緒。)