在前面第一篇介绍的WinFrom Client 端程序为了送出request时要产生SoapHeader﹐而另外撰写了一个ClientHeader类库﹐并且必须在组态加入对应的设定﹐手续看起来有些复杂。实际上﹐有时会希望是以WebRequest的原生方式自行组合Soap 格式数据来进行数据的交换。
在开始之前需要先知道一些数据的规则﹐首先由wsdl规格中可以找到SOAPAction。
前面的介绍过程中在使用Fiddler观察数据时﹐可以看到送出的标准Soap数据格式﹐这是现在在程序中要自行组合的字符串﹐其中包含了SoapHeader﹐要调用的方法与传递的参数。
1:
2:
3: 账号
4: 密码
5:
6:
7:
8: test
9:
10:
11:
有了SoapAction和Soap数据的格式﹐接下来就使用三种平台的方式来撰写。
1. .Net 的调用方式
1: string wsdlUri = "http://kevin-h:905/basicHttpSoapHeader.host/MyProducts.svc?singleWsdl";
2: string username = System.Configuration.ConfigurationManager.AppSettings["username"].ToString();
3: string pwd = System.Configuration.ConfigurationManager.AppSettings["pwd"].ToString();
4: ?
5: private void btnCallSaySomething_Click(object sender, EventArgs e) {
6: try {
7: HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(wsdlUri);
8: webRequest.Method = "POST";
9: webRequest.ContentType = "text/xml;charset=UTF-8";
10: webRequest.Headers.Add("SOAPAction:"http://tempuri.org/IProductService/SaySomething""); //11: StringBuilder soapStr = new StringBuilder(Environment.NewLine);12: soapStr.Append("" + Environment.NewLine);13: soapStr.Append(" " + Environment.NewLine);14: soapStr.Append(" "+username+"" + Environment.NewLine);15: soapStr.Append(" "+pwd+"" + Environment.NewLine);16: soapStr.Append(" " + Environment.NewLine);17: soapStr.Append(" " + Environment.NewLine);18: soapStr.Append(" " + Environment.NewLine);19: soapStr.Append(" test" + Environment.NewLine);20: soapStr.Append(" " + Environment.NewLine);21: soapStr.Append(" " + Environment.NewLine);22: soapStr.Append("" + Environment.NewLine);23: ?24: byte[] buffer = Encoding.UTF8.GetBytes(soapStr.ToString());25: webRequest.ContentLength = buffer.Length;26: Stream post = webRequest.GetRequestStream();27: post.Write(buffer, 0, buffer.Length);28: post.Close();29: ?30: HttpWebResponse response;31: response = (HttpWebResponse)webRequest.GetResponse();32: Stream respostData = response.GetResponseStream();33: StreamReader sr = new StreamReader(respostData);34: string strResponseXml = sr.ReadToEnd();35: ?36: txtOutputValue.Text = strResponseXml;37: } catch (Exception er) {38: if (er.InnerException != null) {39: txtSaySomethingMsg.Text = "InnerException:" + er.InnerException.Message;40: } else {41: txtSaySomethingMsg.Text = "Exception:" + er.Message;42: }43: }44: }上述的程序执行之后所得到的结果为以下的XML格式数据﹐只要Parse这个数据就可以得到想要的东西。
1:2:3:4: You say [test].5:6:7:2. Java 的调用方式
1: package wcf.com;2: ?3: import java.io.BufferedReader;4: import java.io.ByteArrayOutputStream;5: import java.io.InputStreamReader;6: import java.io.OutputStream;7: import java.net.HttpURLConnection;8: import java.net.URL;9: import java.net.URLConnection;10: ?11: public class wcfClient {12: public static void main(String[] args) {13: String responseString = "";14: String outputString = "";15: String wsURL = "http://kevin-h:905/basicHttpSoapHeader.host/MyProducts.svc?wsdl";16: ?17: try{18: URL url = new URL(wsURL);19: URLConnection connection = url.openConnection();20: HttpURLConnection httpConn = (HttpURLConnection)connection;21: ByteArrayOutputStream bout = new ByteArrayOutputStream();22:23: StringBuilder xmlInput=new StringBuilder();24: xmlInput.append("n");25: xmlInput.append(" n");26: xmlInput.append(" testmann");27: xmlInput.append(" a123456n");28: xmlInput.append(" n");29: xmlInput.append(" n");30: xmlInput.append(" n");31: xmlInput.append(" 中文字测试n");32: xmlInput.append(" n");33: xmlInput.append(" n");34: xmlInput.append("n");35:36: byte[] buffer=new String(xmlInput).getBytes();37: bout.write(buffer);38: byte[] b = bout.toByteArray();39: String SOAPAction ="http://tempuri.org/IProductService/SaySomething";40:41: //设定适当的Http参数42: httpConn.setRequestProperty("Content-Length",String.valueOf(b.length));43: httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");44: httpConn.setRequestProperty("SOAPAction", SOAPAction);45: httpConn.setRequestMethod("POST");46: httpConn.setDoOutput(true);47: httpConn.setDoInput(true);48: OutputStream out = httpConn.getOutputStream();49: out.write(b);50: out.close();51: ?52: InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());53: BufferedReader in = new BufferedReader(isr);54:55: while ((responseString = in.readLine()) != null) {56: outputString = outputString + responseString;57: }58: ?59:60: System.out.println(outputString);61: }catch(Exception er){62: er.printStackTrace();63: }64: }65: }执行后可以看到输出的结果和前面.Net得到的结果相同﹐接下就要自行parse XML了。
Ps.在使用eclipse撰写时﹐送出request并能正确的接回数据﹐但后来在传递的值改为中文后就一直失败。直觉是编码出了问题﹐查了许久才发现﹐eclipse在windows时文件存档时默认文件格式编码为MS950﹐如果将文件改存为UTF-8则传递中文的问题就解决了。
3. Android 的调用方式
时下最流行的移动设备﹐当然也必须要能调用WCF才行﹐以下的示范是以Android 4.2.2版本为例。
在Android 3.0之后在主线程上不能直接进行网络活动﹐否则将会得到NetworkOnMainThreadException错误消息。因此在这里先建立一个SoapObjec的class﹐在主线程上再以另一个Thread来执行。
SoapObject.java
1: package com.example.callwcftest;2: ?3: import java.io.IOException;4: ?5: import org.apache.http.HttpEntity;6: import org.apache.http.HttpResponse;7: import org.apache.http.client.ClientProtocolException;8: import org.apache.http.client.ResponseHandler;9: import org.apache.http.client.methods.HttpPost;10: import org.apache.http.entity.ByteArrayEntity;11: import org.apache.http.impl.client.DefaultHttpClient;12: import org.apache.http.params.HttpConnectionParams;13: import org.apache.http.params.HttpParams;14: import org.apache.http.params.HttpProtocolParams;15: import org.apache.http.util.EntityUtils;16: ?17: import android.util.Log;18: ?19: public class SoapObject {20: private String wsURL="";21: private String soapAction="";22: private String soapBody="";23:24: public void setWsURL(String wsURL){25: this.wsURL=wsURL;26: }27:28: public void setSoapAction(String soapAction){29: this.soapAction=soapAction;30: }31:32: public void setSoapBody(String soapBody){33: this.soapBody=soapBody;34: }35: ?36: public String sendRequest(){37: String responseString="";38: final DefaultHttpClient httpClient=new DefaultHttpClient();39: // request 参数40: HttpParams params = httpClient.getParams();41: HttpConnectionParams.setConnectionTimeout(params, 10000);42: HttpConnectionParams.setSoTimeout(params, 15000);43: // set parameter44: HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), true);45: ?46: // POST the envelope47: HttpPost httppost = new HttpPost(this.wsURL);48: // add headers49: httppost.setHeader("soapaction", this.soapAction);50: httppost.setHeader("Content-Type", "text/xml; charset=utf-8");51:52: try {53: // the entity holds the request54: // HttpEntity entity = new StringEntity(envelope);55: HttpEntity entity = new ByteArrayEntity(this.soapBody.getBytes("UTF-8"));56: httppost.setEntity(entity);57: ?58: // Response handler59: ResponseHandler rh = new ResponseHandler() {60: // invoked when client receives response61: public String handleResponse(HttpResponse response)62: throws ClientProtocolException, IOException {63: // get response entity64: HttpEntity entity = response.getEntity();65: ?66: // read the response as byte array67: StringBuffer out = new StringBuffer();68: byte[] b = EntityUtils.toByteArray(entity);69: ?70: // write the response byte array to a string buffer71: out.append(new String(b, 0, b.length));72: return out.toString();73: }74: };75: ?76: responseString = httpClient.execute(httppost, rh);77: } catch (Exception e) {78: Log.v("exception", e.toString());79: }80: ?81: // close the connection82: httpClient.getConnectionManager().shutdown();83:84: return responseString;85: }86: }接着撰写主线程的部分
1: package com.example.callwcftest;2: ?3: import android.app.Activity;4: import android.os.Bundle;5: import android.util.Log;6: import android.view.Menu;7: import android.view.View;8: import android.widget.Button;9: import android.widget.TextView;10: ?11: public class MainActivity extends Activity {12: ?13: Button btnCallWcf;14: TextView txtMsg;15: @Override16: protected void onCreate(Bundle savedInstanceState) {17: super.onCreate(savedInstanceState);18: setContentView(R.layout.activity_main);19:20: btnCallWcf=(Button)this.findViewById(R.id.btnCallWcf);21: txtMsg=(TextView)this.findViewById(R.id.txtMsg);22:23: btnCallWcf.setOnClickListener(WcfCall);24: }25:26: private Button.OnClickListener WcfCall=new Button.OnClickListener(){27: ?28: @Override29: public void onClick(View arg0) {30: runOnUiThread(new Runnable() {31: @Override32: public void run() {33: try{34: String wsURL="http://xxx.xxx.xxx.xxx:905/basicHttpSoapHeader.host/MyProducts.svc?singleWsdl";35: String soapAction="http://tempuri.org/IProductService/SaySomething";36: StringBuilder soapBody=new StringBuilder();37: soapBody.append("n");38: soapBody.append(" n");39: soapBody.append(" testmann");40: soapBody.append(" a123456n");41: soapBody.append(" n");42: soapBody.append(" n");43: soapBody.append(" n");44: soapBody.append(" 中文 & english 测试n");45: soapBody.append(" n");46: soapBody.append(" n");47: soapBody.append("n");48:49: SoapObject client=new SoapObject();50: client.setWsURL(wsURL);51: client.setSoapAction(soapAction);52: client.setSoapBody(soapBody.toString());53:54: txtMsg.setText(client.sendRequest());55: Log.v("success", txtMsg.getText().toString());56: }catch(Exception er){57: Log.d("MAIN err", er.getMessage());58: }59:60: }61: });62:63: }64:65: };66: ?67: }执行的结果
有了这些做法﹐应该可以应付很多状况了。
原文:大专栏 WCF安全性认证:SoapHeader(二)使用HTTP Request调用
原文地址:https://www.cnblogs.com/petewell/p/11516574.html
时间: 2024-08-02 19:12:55