Click here to Skip to main content
Click here to Skip to main content

Calling ASP.NET Webservice (ASMX) from an Android Application, the Simplest Way

By , 22 Dec 2011
 

Introduction

There are several tutorials already present over the internet on this topic. But while going through some of these tutorials, I realized that either they are too complicated for a layman or are not explained properly. This is an important aspect of Android apps as it can easily be used to use existing business logic in Android rather than rewriting them. Another important aspect of this application is that you can easily use a global database to store the data that can be shared by different phones as against common practice of using in built SQLLite database for Android.

Using the Code

First let us look at a simple webservice.

<%@ WebService language="C#" class="MyLocal" %>
using System;
using System.Web.Services;
using System.Xml.Serialization;
public class MyLocal {
    [WebMethod]
    public int Add(int a, int b) {
        return a + b;
    } 
}

While creating this webservice, it asks for a namespace and here the namespace is www.tempura.org (pretty much the default namespace which I have not changed!). You can open this service from http://grasshoppernetwork.com/NewFile.asmx.

When you open this webservice in browser, you can see a window like in the figure below:

figure-1.png

I have marked it to show how to get the namespace name. It will also show the list of methods, which you cannot test. So how to know the arguments and return type? Click on the method and see the figure below:

Figure2-soap_structure.png

Now you know what function you are calling, its arguments, return type and namespace (and of course URL).

For calling this method you need ksoap library, which you can download from here.

Copy the downloaded zip file in any appropriate location. This is an external jar file which you need to include in your Android project.

Start an Android project and select Android API. Right click on the project node in the workspace, properties->java build path->libraries->Add external jar.

Browse and select your ksoap jar file.

All we have to do now is to write a method which can call the web service and return the result. Remember that Android gives you an exception if you try any socket operation from main activity thread. Therefore it is better to write a separate class and isolate soap related functions.

Let us now understand the logic of this class.

package my.MySOAPCallActivity.namespace; 
import org.ksoap2.SoapEnvelope; 
import org.ksoap2.serialization.PropertyInfo; 
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class CallSoap 
{
public final String SOAP_ACTION = "http://tempuri.org/Add";

public  final String OPERATION_NAME = "Add"; 

public  final String WSDL_TARGET_NAMESPACE = "http://tempuri.org/";

public  final String SOAP_ADDRESS = "http://grasshoppernetwork.com/NewFile.asmx";
public CallSoap() 
{ 
}
public String Call(int a,int b)
{
SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE,OPERATION_NAME);
PropertyInfo pi=new PropertyInfo();
pi.setName("a");
        pi.setValue(a);
        pi.setType(Integer.class);
        request.addProperty(pi);
        pi=new PropertyInfo();
        pi.setName("b");
        pi.setValue(b);
        pi.setType(Integer.class);
        request.addProperty(pi);

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

envelope.setOutputSoapObject(request);

HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS);
Object response=null;
try
{
httpTransport.call(SOAP_ACTION, envelope);
response = envelope.getResponse();
}
catch (Exception exception)
{
response=exception.toString();
}
return response.toString();
}
}
  • First SOAP_ACTION = namespace as seen in figure 1+function name;
  • OPERATION_NAME = name of the web method;
  • WSDL_TARGET_NAMESPACE = namespace of the webservice;
  • SOAP_ADDRESS = absolute URL of the webservice;

SOAP works on request response pair. So first you need to build a request object which can call the web service.

SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE,OPERATION_NAME);

Now the operation or the method that you intend to call has some arguments which you need to attach to the request object. This is done through PropertyInfo Instance pi. The important thing to notice here is that the name that you use in setName() method must be the exact name of the property that you have seen in the figure above and in setType(), the data type of the variable must be specified. Using addProperty(), add all the arguments.

Using setValue() method, set the value to the property.

PropertyInfo pi=new PropertyInfo(); 
pi.setName("a"); 
pi.setValue(a); 
pi.setType(Integer.class); 
request.addProperty(pi);

Create a serialized envelope which will be used to carry the parameters for SOAP body and call the method through HttpTransportSE method.

Now you are very much ready with techniques for calling web method and getting the result. For simplicity, we have made a simple Android GUI with two EditText and one Button.

See the main.xml code as below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<EditText 
        android:id="@+id/editText1"
    android:layout_width="230dp"
    android:layout_height="wrap_content" >
    <requestFocus />
</EditText> 
<EditText
    android:id="@+id/editText2"
    android:layout_width="232dp"
    android:layout_height="wrap_content" />
<Button
    android:id="@+id/button1"
    android:layout_width="229dp"
    android:layout_height="wrap_content"
    android:text="@string/btnStr" />
</LinearLayout>

We want to call the method from button click event from activity class.

See the code below:

package my.MySOAPCallActivity.namespace;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class SimpleAsmxSOAPCallActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b1=(Button)findViewById(R.id.button1);
       final  AlertDialog ad=new AlertDialog.Builder(this).create();
         
        b1.setOnClickListener(new OnClickListener() { 
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
CallSoap cs=new CallSoap();

try
{
EditText ed1=(EditText)findViewById(R.id.editText1);
EditText ed2=(EditText)findViewById(R.id.editText2);
int a=Integer.parseInt(ed1.getText().toString());
int b=Integer.parseInt(ed2.getText().toString());

ad.setTitle("OUTPUT OF ADD of "+a+" and "+b);

String resp=cs.Call(a, b);
ad.setMessage(resp);
}catch(Exception ex)
{
ad.setTitle("Error!");
ad.setMessage(ex.toString());
}
ad.show(); }
});
    }
}

All you do now is get the values for a and b from EditTexts and pass the values to call method. Call method returns the result of the web method.

String resp=cs.Call(a, b);
ad.setMessage(resp);

Once you get this up and running, you are very much likely to get an error like android.os.NetworkOnMainThreadException.

That is because Android does not permit you to run socket related operations from main thread as we had already discussed. So you need to run a thread or create a thread from where you can perform these operations. You can easily model the CallSoap class as one implementing runnable and get the stuff. But I wanted to have the calling part as a separate entity. So I just made a separate thread class for calling the CallSoap method. It gives a nice layered implementation so that the thread that is calling the function where SOAP related activities are performed is completely different.

But now the problem is your activity thread and the network thread are in multi-thread operation and chances are your main thread ends before getting the result from the SOAP operation. So I used a primitive way of waiting for the result to arrive and then using it.

The caller class.

public class Caller  extends Thread  
{ public CallSoap cs;       public int a,b; 

       public void run(){

            try{

               cs=new CallSoap();

               String resp=cs.Call(a, b);

MySOAPCallActivity.rslt=resp;}catch(Exception ex)

{MySOAPCallActivity.rslt=ex.toString();
}    
}
}

Modified OnClick method of the button in activity thread which calls SOAP through this simple caller class.

package my.MySOAPCallActivity.namespace;
import android.app.Activity;
import android.os.Bundle;
import android.app.AlertDialog;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MySOAPCallActivity extends Activity {
public static String rslt="";    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b1=(Button)findViewById(R.id.button1);
        final  AlertDialog ad=new AlertDialog.Builder(this).create();
          
         b1.setOnClickListener(new OnClickListener() {
  
@Override public void onClick(View arg0) {
// TODO Auto-generated method stub 

 try
{ 
EditText ed1=(EditText)findViewById(R.id.editText1);
EditText ed2=(EditText)findViewById(R.id.editText2); 
int a=Integer.parseInt(ed1.getText().toString());
int b=Integer.parseInt(ed2.getText().toString()); rslt="START"; 
Caller c=new Caller(); c.a=a;
c.b=b; c.ad=ad;
c.join(); c.start();
while(rslt=="START") {
try {
Thread.sleep(10); 

}catch(Exception ex) {

 }
} ad.setTitle("RESULT OF ADD of "+a+" and "+b);
ad.setMessage(rslt); 

}catch(Exception ex) {
ad.setTitle("Error!"); ad.setMessage(ex.toString());
}
ad.show(); 
} });
    }
}

Finally you get the results as shown below:

fig_4.png

Points of Interest

Though returning a Complex class like Employee or Person or anything like that is not as simple as the technique explained here. They need to have another serializable class. But if you love simplicity, you can return the values of the properties of the class embedded in a single string like "Name#Age#Phone".

Where ‘#’ is a delimiter. Remember that DataReader is not serializable. So your web method must convert DataReader to string format and after receiving the result, you can separate the fields with simple string splitting method.

You can download the complete code from:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Grasshopper.iics
CEO Grasshopper Network
India India
Member
Organisation
38 members

gasshopper.iics is a group of like minded programmers and learners in codeproject. The basic objective is to keep in touch and be notified while a member contributes an article, to check out with technology and share what we know. We are the "students" of codeproject.
 
This group is managed by Rupam Das, an active author here. Other Notable members include Ranjan who extends his helping hands to invaluable number of authors in their articles and writes some great articles himself.
 
Rupam Das is mentor of Grasshopper Network,founder and CEO of Integrated Ideas Consultancy Services, a research consultancy firm in India. He has been part of projects in several technologies including Matlab, C#, Android, OpenCV, Drupal, Omnet++, legacy C, vb, gcc, NS-2, Arduino, Raspberry-PI. Off late he has made peace with the fact that he loves C# more than anything else but is still struck in legacy style of coding.
Rupam loves algorithm and prefers Image processing, Artificial Intelligence and Bio-medical Engineering over other technologies.
 
He is frustrated with his poor writing and "grammer" skills but happy that coding polishes these frustrations.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: ThankgroupGrasshopper.iics22 Sep '12 - 6:10 
It can return dataset but not data reader. Data readers are not serializable. You can convert dataReaders to string and resturn.
GeneralRe: Thankmemberanasbazbaz22 Sep '12 - 11:29 
i am not understand Sigh | :sigh:
can you give example
thnank
 

++++++++++++++
String bar;
cmd = new SqlCommand(select ItemDesc from items where ItemBarcode=\"+ Barcode + "\, con);
 
                reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    bar = reader.GetString(0);
 
                    reader.Close();
                    cmd.Dispose();
                    return bar;
                }
+++++++++
GeneralRe: ThankgroupGrasshopper.iics23 Sep '12 - 1:14 
String bar="";
cmd = new SqlCommand(select ItemDesc from items where ItemBarcode=\"+ Barcode + "\, con);
 
                reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    bar = reader.GetString(0);
 
                    reader.Close();
                    cmd.Dispose();
                    
                }
return bar;

GeneralRe: Thankmemberanasbazbaz24 Sep '12 - 9:48 
Yes
I worked this Code
, but android Receive of Data from the Web Servers Return values any type ​​
GeneralMy vote of 4memberkaramusti15 Aug '12 - 0:22 
Good skill but when irun the code i've got this error:
org.xmlpull.v1.xmlpullparserexception expected start_tag http //schemas.xmlsoap.org/soap/envelope/}
 
please help me how i can resolve this? thanks....
Questiondownload sourcecodememberSjubussen10 Jul '12 - 20:41 
The sourcecode for this article is not available for download unless i register as user on another site. Why is this?
Sjubussen
AnswerRe: download sourcecodegroupGrasshopper.iics12 Jul '12 - 15:04 
The site is built with mybb, which unfortunately do not permit a download for 'Guest User'.
Questionunfortunately, WebService has stoppedmemberazimgoogle4 Jul '12 - 7:12 
Whenever i press the button 'Calling Add' it is saying that 'Unfortunately, WS has stopped'. Can you tell me where am i making wrong?
AnswerRe: unfortunately, WebService has stoppedgroupGrasshopper.iics4 Jul '12 - 15:14 
This is probably a Network Error! Cause It is working Fine. One more stuff that you need to ensure is if you have permission to access web services ( See at your firewall settings!)
And if you are executing your own code, Checkout AndroidManifest file.
 
If you have internet security enabled you can add grasshoppernetwork.com in the exception of your chrome browser or include the same in Trusted Sites in IE.
GeneralRe: unfortunately, WebService has stoppedmemberazimgoogle4 Jul '12 - 16:52 
Still i am getting the same error. I am not sure why it is, but thinking it is may be because of the KSOAP jar. Because my 'LogCat' is showing the messages below whenever i am pressing the button:
 
07-05 02:46:25.457: E/AndroidRuntime(564): FATAL EXCEPTION: Thread-75
07-05 02:46:25.457: E/AndroidRuntime(564): java.lang.NoClassDefFoundError: org.ksoap2.serialization.SoapObject
07-05 02:46:25.457: E/AndroidRuntime(564): at my.MySOAPCallActivity.namespace.CallSoap.Call(CallSoap.java:27)
07-05 02:46:25.457: E/AndroidRuntime(564): at my.MySOAPCallActivity.namespace.Caller.run(Caller.java:22)
 
Is it i am making wrong??
GeneralRe: unfortunately, WebService has stoppedmemberazimgoogle4 Jul '12 - 22:32 
My problem has been solved. Created a folder named 'libs' at the root directory of the project. Then copied the Jar file in 'libs' and referenced the jar in the project from this 'libs' folder.
GeneralMy vote of 5membermustafabayer28 May '12 - 2:19 
thank's. super..
QuestionI am getting error while executing this example.membersadvin14323 May '12 - 8:59 
I copied the whole code on my eclipse and then tried to execute it. but still i am not able to call the web service. i created same service as required in this example.
One thing which i didnt get in this example is in the main class file which is the last block of the code of this article the code "c.ad=ad;" what would this mean as it was giving error on my machine because caller class does not have any object named ad so what will "c.ad" would do.
I have linked the ksoap library also.
Still the error which i got is :
 
04-25 04:47:04.931: E/AndroidRuntime(1235): at com.web.service.Caller.run(Caller.java:13)
04-25 04:49:52.594: I/Process(1235): Sending signal. PID: 1235 SIG: 9
04-25 04:50:16.691: E/dalvikvm(1269): Could not find class 'org.ksoap2.serialization.SoapObject', referenced from method com.web.service.CallSoap.Call
04-25 04:50:16.691: W/dalvikvm(1269): VFY: unable to resolve new-instance 43 (Lorg/ksoap2/serialization/SoapObject;) in Lcom/web/service/CallSoap;
04-25 04:50:16.701: D/dalvikvm(1269): VFY: replacing opcode 0x22 at 0x0000
04-25 04:50:16.711: D/dalvikvm(1269): VFY: dead code 0x0002-0063 in Lcom/web/service/CallSoap;.Call (II)Ljava/lang/String;
04-25 04:50:16.711: W/dalvikvm(1269): threadid=9: thread exiting with uncaught exception (group=0x40015560)
04-25 04:50:16.731: E/AndroidRuntime(1269): FATAL EXCEPTION: Thread-10
04-25 04:50:16.731: E/AndroidRuntime(1269): java.lang.NoClassDefFoundError: org.ksoap2.serialization.SoapObject
04-25 04:50:16.731: E/AndroidRuntime(1269): at com.web.service.CallSoap.Call(CallSoap.java:23)
04-25 04:50:16.731: E/AndroidRuntime(1269): at com.web.service.Caller.run(Caller.java:13)
04-25 04:50:29.483: I/Process(1269): Sending signal. PID: 1269 SIG: 9
 
An solution for this would be really appritiated.
 
Thanks.
GeneralRe: I am getting error while executing this example. [modified]memberJelgab26 Jun '12 - 10:28 
I did this to fix that same error:
 
1. Renamed "ksoap2-android-assembly-2.6.5-jar-with-dependencies.zip" to "ksoap2.jar"
2. In Eclipse, on the Project Explorer right click the root of the project (Where the name of the project is), selected "New", "Folder" and created a new folder called libs
3. Went back to my file explorer. Right click "ksoap2.jar", "copy"
4. In Eclipse, right click the newly created "libs" folder and select "paste"
 
After that, it worked.
 
References:
could-not-find-class-soapobject[^]
 
exception-while-using-ksoap2-library-for-android[^]

modified 28 Jun '12 - 20:12.

AnswerRe: I am getting error while executing this example.memberahmed sherif shawkat15 Nov '12 - 6:23 
I have the same error please help us :(
BugLink Broked. [modified]memberColadela2 Feb '12 - 8:46 
Hi,
 
Tk´s for you help us, I´m getting a error when I´m try to download the source code.
 
MyBB has experienced an internal SQL error and cannot continue.
 
SQL Error:
145 - Table '.\mybb\mybb_sessions' is marked as crashed and should be repaired
Query:
DELETE FROM mybb_sessions WHERE ip='187.75.179.36'
 

Can you help me ?
 
Rodrigo Coladela

modified 2 Feb '12 - 15:17.

GeneralRe: Link Broked.groupGrasshopper.iics2 Feb '12 - 20:41 
Hello the Link is corrected now. It might be because some spammer used a banned IP '187.75.179.36'
 
Hope it works fine now.
GeneralRe: Link Broked.memberColadela3 Feb '12 - 5:17 
OK, I´m having another problem now, I´m trying to registrate, and is ocurring this error:
SQL Error:
145 - Table '.\mybb\mybb_captcha' is marked as crashed and should be repaired
Query:
INSERT INTO mybb_captcha (`imagehash`,`imagestring`,`dateline`) VALUES ('a84595a34a457307fc09cd028bc6b770','uR7nj','1328285633')
GeneralRe: Link Broked.groupGrasshopper.iics3 Feb '12 - 18:31 
The issue is fixed! Sorry for Inconvenience! Cheers.
GeneralRe: Link Broked.memberColadela6 Feb '12 - 4:18 
Thank you very much!!!
GeneralMy vote of 3membermaq_rohit25 Dec '11 - 7:28 
Why you are using KSOAP instead of can choose default one by Android!!!\
GeneralRe: My vote of 3groupGrasshopper.iics25 Dec '11 - 21:07 
Hello and Thanks for Voting. But is there really any Libraries in Android for WebService Connectivity? I am honestly not aware of it. The only other way to get it done is by writing a Socket Application. Calling SOAP through sockets is just not the best of the solutions.
 
Could you please mention any reference articles or books that shows an Android connectivity with Android Inbuilt functions? That help will really be appreciable.
GeneralRe: My vote of 3membermaq_rohit8 Jan '12 - 23:27 
Hi sorry for late response.. yes you can consume service by this function
 
 
public static String ConsumerService(Context ctx,String url, String method, ArrayList<ServiceParam> params)
                throws MalformedURLException, IOException {
                
         String response = "";
         HttpURLConnection conn = null;
         
         try {
                String sParams = ServiceParam.ConvertParamToSOAPFormat(params);
                conn = (HttpURLConnection) new URL(url).openConnection();
                conn.setRequestProperty("content-type", "text/xml; charset=utf-8");
                conn.setRequestProperty("SOAPAction", method);
                     conn.setRequestMethod("POST");
                     conn.setDoOutput(true);
                     
                     StringBuilder soapEnvelope = new StringBuilder();
                     soapEnvelope.append("<?xml version='1.0' encoding='utf-8'?>");
                     soapEnvelope.append("<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>");
                     soapEnvelope.append("<soap:Header><SessionHeader xmlns='http://soap.sforce.com/schemas/class/CustomerRecoService'><sessionId>"); 
                     soapEnvelope.append(LoginUser.SessionID);
                     soapEnvelope.append("</sessionId></SessionHeader></soap:Header>");
                     soapEnvelope.append("<soap:Body>");
                     soapEnvelope.append("<" + method + " xmlns='http://soap.sforce.com/schemas/class/CustomerRecoService'>");
                     soapEnvelope.append(sParams);
                     soapEnvelope.append("</" + method + ">");
                     soapEnvelope.append("</soap:Body></soap:Envelope>");
                     
                     conn.getOutputStream().write(soapEnvelope.toString().getBytes("UTF-8"));
                     
                
                InputStream is = null;
                
                     is =conn.getInputStream(); 
                     response = read(is);
                } catch (Exception e) {
                     // Error Stream contains JSON that we can parse to a FB error
                     response = read(conn.getErrorStream());
                     response = readErrorMessage(response);
                     if(response== "")
                     {
                          response = "Network Error!!!";
                     }
                     //ShowToast(ctx, response);
                     //response = "";
                }
                
                return response;
         }
 
I am in hurry so cant update too much about this but i hope you will get idea Smile | :)
GeneralRe: My vote of 3memberJaydeep Jadav16 Jun '12 - 3:16 
this will return you the XML with method response tag. And in android the parsing and writing Parser for complex XML is quite hard. Instead of we can use KSOAP lib as it will return the SOAPOBJECT in response and the parsing of data from SoapObject is very easy, even webservice returns the Dataset it is easier to parse in KSOAP lib than typical XML. Big Grin | :-D
GeneralRe: My vote of 3memberRamon Ll. Felip8 Jan '12 - 21:32 
As fas as I know, Android does not have native classes that encapsulates native handling of SOAP WebServices, so the "native" options is to format httprequests. Hence, KSOAP is the most common and used option around.
 
Anyway, I could be wrong of course, so if there are any native alternatives I'm not aware of, please tell us!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 22 Dec 2011
Article Copyright 2011 by Grasshopper.iics
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid