How to Call a Wcf Service Using Ksoap2 on Android

How to call a WCF service using ksoap2 on android?

finally I got it to work
because the namespace missed a "/" in the end ,

following is my code

package cn.qing.ksop2test;

import java.io.Writer;

import org.ksoap2.*;
import org.ksoap2.serialization.*;
import org.ksoap2.transport.*;
import org.xmlpull.v1.XmlSerializer;

import android.app.Activity;
import android.os.Bundle;
import android.util.Xml;
import android.widget.TextView;

public class ksop2test extends Activity {
/** Called when the activity is first created. */

private static final String METHOD_NAME = "HelloWorldRequest";
// private static final String METHOD_NAME = "HelloWorld";

private static final String NAMESPACE = "http://tempuri.org/";
// private static final String NAMESPACE = "http://tempuri.org";

private static final String URL = "http://192.168.0.2:8080/HelloWCF/Service1.svc";
// private static final String URL = "http://192.168.0.2:8080/webservice1 /Service1.asmx";

final String SOAP_ACTION = "http://tempuri.org/IService1/HelloWorld";
// final String SOAP_ACTION = "http://tempuri.org/HelloWorld";
TextView tv;
StringBuilder sb;
private XmlSerializer writer;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
sb = new StringBuilder();
call();
tv.setText(sb.toString());
setContentView(tv);
}

public void call() {
try {

SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

request.addProperty("Name", "Qing");

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);

HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapPrimitive result = (SoapPrimitive)envelope.getResponse();

//to get the data
String resultData = result.toString();
// 0 is the first object of data

sb.append(resultData + "\n");
} catch (Exception e) {
sb.append("Error:\n" + e.getMessage() + "\n");
}

}

}

Consuming WCF service using ksoap2

Well, Thanks guys for your contribution but I have solved my problem. The issue was IIS Express Server in Visual Studio 2013. I was trying to access my web service from android but IIS Express was maybe not configured or something. Anyway the solution is to change your server from project properties. Change from IIS Express to ASP.Net Application Development Server.

PS: Visual Studio 2013 does not support Visual Studio Application Development Server anymore.

Calling WCF Service with KSoap2 with complex objects. WCF receives empty values

I have solved it after hours of investigation. I'll post the answer to help others in the same case.

Using SoapUI I have seen the namespaces and the XML to send and then trying with KSoap2 generating something similar to that.

In my class I have added the namespace in the getPropertyInfo method. It is the same namespace to all properties and this will generate an XML with the namespace in all tags. Different than the XML that I have mentioned in my question. But it's ok and is compatible.

@Override
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch(index)
{
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Arg1";
info.namespace = "http://schemas.datacontract.org/2004/07/Models.TrsApiModel"
break;
//...
default:
break;
}
}

Then in my class I have added a method to generate a SoapObject. The namespace is not the same as the properties inside the object.

public SoapObject getSoapRequest(String nameSpace, String name){
SoapObject soapRequest = new SoapObject(nameSpace, name);
for(int i = 0; i < this.getPropertyCount(); i++){
PropertyInfo prp = new PropertyInfo();
this.getPropertyInfo(i, null, prp);
prp.setValue(this.getProperty(i));
soapRequest.addProperty(prp);
}
return soapRequest;
}

Onse you have the SoapObject to send you have to add int to the Body SoapObject with addSoapObject method.

SoapObject body = new SoapObject(this.callHeader.getNamespace(), this.callHeader.getMethodName());
//soapObj is an instance using the getSoapRequest() method mentioned in my piece of code
body.addSoapObject(soapObj);
SoapSerializationEnvelope envelope = this.getWebServiceEnvelope();
envelope.setOutputSoapObject(body);

With that code everything seems to work but not completely. I have experienced that some of the parameters are received well by the server but not all of them. One more tricky thing is that the object properties must be in the same order as the parameters in the SoapUi request. So you have to modify the switches in the methods of the object to have the index in the same order as you can see in the SoapUI XML request.

Methods to pay attention at with the index to have the same order

public Object getProperty(int index)
public void setProperty(int index, Object value)
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info)

It takes me a lot of time to discover how WCF is such kind of detailed to receive the correct parameters. So hope my answer will help someone with same problems.

Consuming a localhost WCF service using kSOAP2 in emulator

Okay, I FINALLY figured out my problem(s). Several factors were at play which you would expect for someone new to these technologies. Hopefully my mistakes will save others some time.

The first problem I had was a parameter error in my code. The line

androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope);

was incorrect in that it should have listed the namespace for my web service followed by the method name. So I changed that line to this:

androidHttpTransport.call("http://sample.com/SayHello", envelope);

After this change I still had the line throw an exception but now I was getting a different exception which was at least a moral victory. The new exception said this:

expected START_TAG{http://schemas.xmlsoap.org/soap/envelope/} Envelope(position:START_TAG<html>@1:6 in java.io.InputStreamReader@d3el2cc4)

This message is rampant on the internet but none of the solutions I found worked for me. After lots of trial and error I found my particular problem. My web service is created in Visual Studio 2008 and I am testing it simply by running it inside Visual Studio and then trying to consume it from my Android emulator. It turns out that there is a security setting in the VS2008 "sandbox" IIS that rejects any requests beyond the local PC -- and apparently the emulator is not considered the local PC.

To correct that issue I took the following steps in Visual Studio 2008:

  1. Exit Visual Studio and open it using Administrative rights (I am using Windows 7).
  2. With my project open I viewed the project properties.
  3. On the "Web" tab I changed the "Servers" section's radio button to "Use Local IIS Web server", entered "http://localhost/Sample" for my Project URL and clicked the "Create Virtual Directory" button.

After completing these steps I ran my web service again, launched my Android app in the emulator and finally got by the line that has been throwing an exception all along. This time, however, the next line threw an exception. Another moral victory and a step closer. This new exception was:

org.ksoap2.serialization.SoapPrimitive

A quick Google search solved this one for me. The lines

SoapObject response = (SoapObject)envelope.getResponse();
String resultValue = response.getProperty(0).toString();

in my original code needed to be changed to this:

SoapPrimitive response = (SoapPrimitive)envelope.getResponse();
String resultValue = response.toString();

After that change I had a working application.

Final working code

Web service (created in Visual Studio 2008 and running on local IIS web server as configured in project properties)

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;

namespace Sample {
[WebService(Namespace = "http://sample.com/")]
public class Service1 : System.Web.Services.WebService {
[WebMethod]
public string SayHello() {
return "Hello, Android. From your friend, WCF";
}
}
}

Android class

package com.sample;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import org.ksoap2.*;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.*;
import org.ksoap2.serialization.SoapPrimitive;

public class Sample extends Activity {
TextView result;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

result = (TextView)findViewById(R.id.textViewResult);

final String SOAP_ACTION = "http://sample.com/SayHello";
final String METHOD_NAME = "SayHello";
final String NAMESPACE = "http://sample.com/";
final String URL = "http://192.168.1.72/Sample/Service1.asmx";

try {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);

HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

androidHttpTransport.call(SOAP_ACTION, envelope);
SoapPrimitive response = (SoapPrimitive)envelope.getResponse();
String resultValue = response.toString();

result.setText(resultValue);
}
catch (Exception e) {
result.setText(e.getMessage());
}
}
}

Consuming WCF service on Android using ksoap2 - Internal Server Error

If you have choice, it is best to not use SOAP on Android. SOAP is way more complex than REST and requires a sophisticated framework which is not available for Android, at least for now.

passing objects to wcf soap service from android using ksoap2; it sends and receives 0

I finally got it to work!

Turns out my android ksoap2 code didn't like the default namespace(tempuri.org) set by WCF in the SOAP service.

My guess is that with the default namespace, the request envelop was unable to map the passed testadd object to the datacontract in which the testadd class is defined in the service. By defining a namespace explicitly to the servicecontract and datacontract in the WCF service, this changes/rearranges the wsdl and makes the datacontract accessible.

I followed this tutorial to get rid of the tempuri.org namespace-
http://blogs.msdn.com/b/endpoint/archive/2011/05/12/how-to-eliminate-tempuri-org-from-your-service-wsdl.aspx

I added the following in the appropriate places in the service code (VB)

<ServiceContract(Namespace:="http://wcfservicetest.org/Service1")> _
<DataContract(Namespace:="http://wcfservicetest.org/Service1")> _
<ServiceBehavior(Namespace:="http://wcfservicetest.org/Service1")> _

I changed my namespace to "http://wcfservicetest.org/Service1" and edited NAMESPACE and SOAP_ACTION in the android java code with the new namespace.

After doing this I got the result I wanted!

Here is the soap request:

<v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
<v:Header />
<v:Body>
<ksoapAdd xmlns="http://wcfservicetest.org/Service1" id="o0" c:root="1">
<n0:num1 xmlns:n0="http://wcfservicetest.org/Service1">
<number_1>25</number_1>
<number_2>25</number_2>
</n0:num1>
</ksoapAdd>
</v:Body>
</v:Envelope>

soap response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ksoapAddResponse xmlns="http://wcfservicetest.org/Service1">
<ksoapAddResult>50</ksoapAddResult>
</ksoapAddResponse>
</s:Body>
</s:Envelope>

So my advice to anyone else learning SOAP services with ksoap2, do no use the default namespace, set your own namespace. I wasted a week trying to figure this out.

Hope this helps someone someday!!

Send data to WCF from Android using KSOAP2

Try setting the ItemName on the CollectionDataContract attribute. For example:

[CollectionDataContract(Name = "Custom{0}List", ItemName = "CustomItem")]
public class Items : List<clsitems>
{
}

The CollectionDataContractAttribute is intended to ease interoperability when working with data from non- providers and to control the exact shape of serialized instances. To this end, the ItemName property enables you to control the names of the repeating items inside a collection. This is especially useful when the provider does not use the XML element type name as the array item name, for example, if a provider uses "String" as an element type name instead of the XSD type name "string".

Taken from here

Consuming WCF Soap Service running on Mono from Android KSoap2

Firstly, you want to catch the actual SOAP request on the wire. You can do this using Fiddler or SoapUI - they both act as proxies through which local requests are passed, allowing you to inspect the actual XML request for anomalies. You might discover something obvious by doing this, or you can at least update your question with more information.

Following that, and without any further information, I can only offer a memorable experience with talking to WCF services from non-.NET applications:

WCF specifies the XML request that it expects, but it actually requires object properties to be in a specific order. This can be a declared order in the datacontract, or it can be an implicit alphabetical order. Either way, if you don't provide object properties in the specified order you will be stung and things won't work.



Related Topics



Leave a reply



Submit