How to call ASP.Net Web API service from Android?

In my previous posts, I discussed how we can consume the ASP.Net Web API with RestSharp and HttpClient. In this small one, I would like to show how we can make a demo application in Android consuming ASP.Net Web API service. To save time, I already prepare a sample REST web service made by ASP.NET Web API with only one resource at http://restwebserviceforandroid.apphb.com/api/products. You can access the service without any authentication for your testing purposes. On the server, I use Entity Framework to connect to a SQL Server behind with following structure

Entity Framework Model

The resource Product allows following HTTP actions

public class ProductsController : ApiController
{
	private ProductEntities productEntities = new ProductEntities();

	public IEnumerable<Product> Get()
	{
		return productEntities.Products.AsEnumerable();
	}

	public Product Get(int id)
	{
		return productEntities.Products.Where(x => x.Id == id).FirstOrDefault();
	}

	public Product Post(string name, decimal price, string description)
	{
		Product product = new Product()
		{
			Name = name,
			Price = price,
			Description = description
		};

		productEntities.Products.Add(product);
		productEntities.SaveChanges();
		return product;
	}

	public Product Post(Product product)
	{
		Product foundProduct = productEntities.Products.Where(x => x.Id == product.Id).FirstOrDefault();
		if (foundProduct != null)
		{
			foundProduct.Name = product.Name;
			foundProduct.Price = product.Price;
			foundProduct.Description = product.Description;
		}
		productEntities.SaveChanges();
		return foundProduct;
	}

	public void Delete(int id)
	{
		Product product = productEntities.Products.Where(x => x.Id == id).FirstOrDefault();
		if (product != null)
		{
			productEntities.Products.Remove(product);
		}
		productEntities.SaveChanges();
	}
}

Like other RESTful service, I have to support basic actions for creating/reading/updating/deleting. However in this case, instead of using PUT action for updating, you see that I use the POST action updating product. There are two functions for handling POST action in the controller. The function with simple types

public Product Post(string name, decimal price, string description)
{
}

is for creating product. These arguments will be given through URL parameters. Meanwhile for updating, I’ll post a complex object in HTTP body so that ASP.NET Web API service can understand and handle parameters correctly. This approach depends completely on how ASP.NET Web API works as I discussed in previous posts before. I think the code of service is pretty simple and explains itself. 🙂

On the client site, I make a lightweight Android application with some activities calling the web service and executing some CRUD actions. The image below show how application looks like

Project structure

The start activity is MainActivity. From this one, I can go to other activities to create a product, list all of them, modify one or delete it. For example, AllProductsActivity is a list view activity for enumerating all available products in database.

List all products activity

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <ListView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@android:id/list"/>
</LinearLayout>

or a normal activity with some controls for adding new product

Add new product activity

These activities work with “same” procedure. They start, draw the controls and then call appropriate web service action in background to get or modify data. When the task finishes, the activity will be reloaded with fresh data from service. For example the code of AllProductsActivity looks like following

public class AllProductsActivity extends ListActivity {
    ArrayList<HashMap<String, String>> productList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);    //To change body of overridden methods use File | Settings | File Templates.
        setContentView(R.layout.all_products);

        initializeComponents();

        productList = new ArrayList<HashMap<String, String>>();
        new LoadAllProducts().execute();
    }

    private void initializeComponents() {
        ListView listView = getListView();
        listView.setOnItemClickListener(listViewItemClickListener);
    }

    private AdapterView.OnItemClickListener listViewItemClickListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            int productId = Integer.parseInt(((TextView) view.findViewById(R.id.textViewId)).getText().toString());
            Intent intent = new Intent(getApplicationContext(), EditProductActivity.class);
            intent.putExtra(Product.PRODUCT_ID, productId);
            startActivityForResult(intent, RequestCode.PRODUCT_DETAILS);
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);    //To change body of overridden methods use File | Settings | File Templates.
        if (resultCode == ResultCode.PRODUCT_UPDATE_SUCCESS || resultCode == ResultCode.PRODUCT_DELETE_SUCCESS) {
            Intent intent = getIntent();
            finish();
            startActivity(intent);
        }
    }

    class LoadAllProducts extends AsyncTask<String, String, String> {
        private ProgressDialog progressDialog;

        @Override
        protected String doInBackground(String... params) {
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
            JSONHttpClient jsonHttpClient = new JSONHttpClient();
            Product[] products = jsonHttpClient.Get(ServiceUrl.PRODUCT, nameValuePairs, Product[].class);
            if (products.length > 0) {

                for (Product product : products) {
                    HashMap<String, String> mapProduct = new HashMap<String, String>();
                    mapProduct.put(Product.PRODUCT_ID, String.valueOf(product.getId()));
                    mapProduct.put(Product.PRODUCT_NAME, product.getName());
                    productList.add(mapProduct);
                }

            } else {
                Intent intent = new Intent(getApplicationContext(), NewProductActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
            }
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();    //To change body of overridden methods use File | Settings | File Templates.
            progressDialog = new ProgressDialog(AllProductsActivity.this);
            progressDialog.setMessage("Loading products. Please wait...");
            progressDialog.show();
        }

        @Override
        protected void onPostExecute(String s) {
            progressDialog.dismiss();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ListAdapter adapter = new SimpleAdapter(AllProductsActivity.this, productList, R.layout.list_item, new String[]{"Id", "Name"}, new int[]{R.id.textViewId, R.id.textViewName});
                    setListAdapter(adapter);
                }
            });
        }
    }
}
public class ServiceUrl {
    public static final String REST_SERVICE_URL = "http://restwebserviceforandroid.apphb.com/api/";
    public static final String PRODUCT = REST_SERVICE_URL + "products";
}
public class Product {
    public int getId() {
        return Id;
    }

    public void setId(int id) {
        this.Id = id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        this.Name = name;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        this.Description = description;
    }

    public double getPrice() {
        return Price;
    }

    public void setPrice(double price) {
        this.Price = price;
    }

    private int Id;
    private String Name;
    private String Description;
    private double Price;

    public static final String PRODUCT_ID = "Id";
    public static final String PRODUCT_NAME = "Name";
}

You know that I come from Visual Studio therefore I would like to keep code structure as same as possible in Java environment. In onCreate() function, I make an initializeComponents() function where I initialize the references to all of controls I would like to access later. Task for loading data will be called after this function. The task class inherits AsyncTask so that I won’t freeze the user interface while executing it in background by loading data (long run process) in doInBackground() function.

The code of doInBackground() function will get all of products and populate them into the list view. The custom JSONHttpClient class makes a HTTP GET to web service, parse the result of JSON format into array of products and fill in the productList. When data was loaded, the doInBackground() was done, list view will be populated with a SimpleAdapter with predefined layout R.layout.list_item and data from productList. The xml code of R.layout.list_item is in listing below.


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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="New Text"
 android:id="@+id/textViewId" android:visibility="gone"/>
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="New Text"
 android:id="@+id/textViewName" android:layout_gravity="right|center_vertical"
 android:textSize="17dp" android:textStyle="bold" android:padding="10dp" android:textColor="#f3f3f3"/>

</LinearLayout>

After all products are displayed on screen, you can edit each product by clicking/tapping on the row where product locates. The event OnItemClickListener of list view should be handled and takes user to edit activity so that he can edit the selected product. On the EditProductActivity, I receive the product Id given in Extra section, start to load product details, show them on screen and allow user to edit

public class EditProductActivity extends Activity {
    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);    //To change body of overridden methods use File | Settings | File Templates.
        setContentView(R.layout.edit_product);

        initializeComponents();

        Intent intent = getIntent();
        productId = intent.getIntExtra(Product.PRODUCT_ID, 0);
        new GetProductDetails().execute();

    }
	
	...
	
}

You can find more details how the code works, in attachment at the end of post. I think the code, in simple cases, makes always better explanation than thousand words. Only one question left is how was the HTTP GET/POST built and sent to server? Theses actions will be executed in JSONHttpClient class. This is my custom one, not from standard library of Android. I combine Gson (https://code.google.com/p/google-gson/) with generic class to build a .net equivalent HttpClient for Android. However in current version, this class can only work in synchronous mode, you can apply the same technique with AsycTask to make a PostAsync or GetAsync like in .net framework.

public class JSONHttpClient {
    public <T> T PostObject(final String url, final T object, final Class<T> objectClass) {
        DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        try {

            StringEntity stringEntity = new StringEntity(new GsonBuilder().create().toJson(object));
            httpPost.setEntity(stringEntity);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            httpPost.setHeader("Accept-Encoding", "gzip");

            HttpResponse httpResponse = defaultHttpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                InputStream inputStream = httpEntity.getContent();
                Header contentEncoding = httpResponse.getFirstHeader("Content-Encoding");
                if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
                    inputStream = new GZIPInputStream(inputStream);
                }

                String resultString = convertStreamToString(inputStream);
                inputStream.close();
                return new GsonBuilder().create().fromJson(resultString, objectClass);

            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (ClientProtocolException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }

    public <T> T PostParams(String url, final List<NameValuePair> params, final Class<T> objectClass) {
        String paramString = URLEncodedUtils.format(params, "utf-8");
        url += "?" + paramString;
        return PostObject(url, null, objectClass);
    }

    private String convertStreamToString(InputStream inputStream) {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String line = null;
        try {
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }

        return stringBuilder.toString();
    }

    public <T> T Get(String url, List<NameValuePair> params, final Class<T> objectClass) {
        DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
        String paramString = URLEncodedUtils.format(params, "utf-8");
        url += "?" + paramString;
        HttpGet httpGet = new HttpGet(url);
        try {

            httpGet.setHeader("Accept", "application/json");
            httpGet.setHeader("Accept-Encoding", "gzip");

            HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                InputStream inputStream = httpEntity.getContent();
                Header contentEncoding = httpResponse.getFirstHeader("Content-Encoding");
                if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
                    inputStream = new GZIPInputStream(inputStream);
                }

                String resultString = convertStreamToString(inputStream);
                inputStream.close();
                return new GsonBuilder().create().fromJson(resultString, objectClass);

            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (ClientProtocolException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }

    public boolean Delete(String url, final List<NameValuePair> params) {
        DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
        String paramString = URLEncodedUtils.format(params, "utf-8");
        url += "?" + paramString;
        HttpDelete httpDelete = new HttpDelete(url);

        HttpResponse httpResponse = null;
        try {
            httpResponse = defaultHttpClient.execute(httpDelete);
            return httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT;
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        return false;
    }
}

Again, the code is pretty simple and explains itself. 🙂 . For posting, we have to tell the server what kind of data format we are sending (in this case is JSON through setting Content-Type header), what kind of data format we are waiting for (in this case is JSON through header Accept) and if we can handle compression (optional). The HttpClient POST supports posting either with URL parameters or with complex object in body. Meanwhile HttpClient GET/DELETE supports only passing data with URL parameters. The approach will work with any normal RESTful web service.

The source code of Android client : https://bitbucket.org/hintdesk/android-how-to-call-asp.net-web-api-service-from-android

Please note that I use Intellij (http://www.jetbrains.com/idea/) as my Android development environment, you can easily open/import project if you are using this IDE too. If you use Eclipse, then search on Internet for instructions to import project into your Eclipse IDE.

UPDATE 08.07.2013

Source code of web service: http://hintdesk.com/Web/Source/rest_web_service_for_android.zip . You have to provide a correct connection string at connectionstrings section in Web.config


<connectionStrings>
<add name="AndroidEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=YOUR_MS_SQL_SERVER;initial catalog=YOUR_DATABASE;user id=YOUR_USER_NAME;password=YOUR_PASSWORD;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

43 thoughts on “How to call ASP.Net Web API service from Android?”

  1. Hi, if you have time. Pls. share and complete this tutorial. I’m very much interested learning this great stuff! thanks anyway

  2. @jayson: I think the post is complete. I uploaded the complete source code already. I don’t understand your point.

  3. Hi Sir, thanks for the quick responce. This one sir >To save time, I already prepare a sample REST web service made by ASP.NET Web API .. may you pls. share the code so that I can or we can test and study the complete system locally? btw, any clue I’m having 400 bad request – invalid host name.. whenever I’m accessing 10.0.2.2:[port]? from android emulator

  4. @jayson: The code of server contains sensitive information about the database, therefore I can’t simply publish it. If you need the source code of server you can download it here http://hintdesk.com/Web/Source/rest_web_service_for_android.zip . I removed all information of database from source code, you have to define your own database. Moreover the server is written in C# with ASP.NET Web API technique, you will need Visual Studio to compile.
    10.0.2.2 is special alias to your host loopback interface (i.e., 127.0.0.1 on your development machine). Accessing http://10.0.2.2:%5Bport%5D on emulator is as same as accessing http://127.0.01:%5Bport%5D at your computer. Error 400 means that there is no HTTP handling for given URL. Typical cases for this error are false URLs or web server is not available.

  5. Hi Sir, how about making a separate tutorial on how the server was created
    I wanna try to study test it on my android emulator locally
    using the above source code of the server, how do I define its own database??
    I know this was wrong I added this in the web.config
    name=”ProductDBContext”
    connectionString=”Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Products.mdf;Integrated Security=True” providerName=”System.Data.SqlClient”

  6. @Jayson : You have to config connectionStrings section. For example like this

    <connectionStrings>
        <add name="AndroidEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=YOUR_SQL_SERVER;initial catalog=YOUR_DATABASE;user id=USER_NAME;password=PASSWORD;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
      </connectionStrings>
    

    or just simply create an entity item of available database through wizard of Visual Studio

  7. Hi Sir, I’m really having a big trouble here. may you pls. share a working example with perfect connection string of the server?

  8. @jayson: The connection string you can get from my comment above. I don’t understand what you mean with perfect connection string of server? I can only say how connection string looks like, you have to fill out the formation of your SQL server. Take a look at some tutorials for Entity Framework if you don’t know how it works.
    @rio: The source code of web service is available in comment above or I already updated it in post.

  9. Hi Sir, I already made the server working.. however, I have problem connecting the client to android.

    got this logcat: I haven’t change anything from the android source only that 10.0.0.2:[port]

    07-08 14:16:28.922: E/AndroidRuntime(1916): FATAL EXCEPTION: AsyncTask #1
    07-08 14:16:28.922: E/AndroidRuntime(1916): java.lang.RuntimeException: An error occured while executing doInBackground()
    07-08 14:16:28.922: E/AndroidRuntime(1916): at android.os.AsyncTask$3.done(AsyncTask.java:299)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.lang.Thread.run(Thread.java:856)
    07-08 14:16:28.922: E/AndroidRuntime(1916): Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 10
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.Gson.fromJson(Gson.java:806)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.Gson.fromJson(Gson.java:761)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.Gson.fromJson(Gson.java:710)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.Gson.fromJson(Gson.java:682)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.hintdesk.How_to_consume_ASPNET_Web_Api.util.JSONHttpClient.Get(JSONHttpClient.java:110)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.hintdesk.How_to_consume_ASPNET_Web_Api.AllProductsActivity$LoadAllProducts.doInBackground(AllProductsActivity.java:75)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.hintdesk.How_to_consume_ASPNET_Web_Api.AllProductsActivity$LoadAllProducts.doInBackground(AllProductsActivity.java:1)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at android.os.AsyncTask$2.call(AsyncTask.java:287)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    07-08 14:16:28.922: E/AndroidRuntime(1916): … 4 more
    07-08 14:16:28.922: E/AndroidRuntime(1916): Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 10
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.stream.JsonReader.expect(JsonReader.java:339)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:306)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:70)
    07-08 14:16:28.922: E/AndroidRuntime(1916): at com.google.gson.Gson.fromJson(Gson.java:795)
    07-08 14:16:28.922: E/AndroidRuntime(1916): … 12 more
    07-08 14:16:29.471: E/WindowManager(1916): Activity com.hintdesk.How_to_consume_ASPNET_Web_Api.AllProductsActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b4fd0a68 V.E….. R……D 0,0-480,144} that was originally added here
    07-08 14:16:29.471: E/WindowManager(1916): android.view.WindowLeaked: Activity com.hintdesk.How_to_consume_ASPNET_Web_Api.AllProductsActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b4fd0a68 V.E….. R……D 0,0-480,144} that was originally added here
    07-08 14:16:29.471: E/WindowManager(1916): at android.view.ViewRootImpl.(ViewRootImpl.java:354)
    07-08 14:16:29.471: E/WindowManager(1916): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
    07-08 14:16:29.471: E/WindowManager(1916): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
    07-08 14:16:29.471: E/WindowManager(1916): at android.app.Dialog.show(Dialog.java:281)
    07-08 14:16:29.471: E/WindowManager(1916): at com.hintdesk.How_to_consume_ASPNET_Web_Api.AllProductsActivity$LoadAllProducts.onPreExecute(AllProductsActivity.java:98)
    07-08 14:16:29.471: E/WindowManager(1916): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
    07-08 14:16:29.471: E/WindowManager(1916): at android.os.AsyncTask.execute(AsyncTask.java:534)
    07-08 14:16:29.471: E/WindowManager(1916): at com.hintdesk.How_to_consume_ASPNET_Web_Api.AllProductsActivity.onCreate(AllProductsActivity.java:40)

    server client to android

  10. @jayson: The error shows that the json result from web service is not correct. Check if you can access your web service from your android client by browsing to your local webservice URL with browser in Android. Analyze the errors yourself helps you understand how it works. Read also this article http://hintdesk.com/how-to-get-android-emulator-working-with-fiddler/ to see if you call web service correctly. I think you should first use my sample web service to understand how system works before trying to build a local web service yourself.

  11. Hi I was wondering if I would have any trouble running the web api from localhost instead of a remote server

    Thanks

  12. @Luis: There is no problem if you let your webservice running at your local computer. But I think, at the end, when you want to publish your webservice over internet, you have to move it to a server which is accessible from internet.

  13. Hi admin .. can you please help me. I wrote java code on android to consume a wcf in Visual Stuido 2013. I can hit it perfectly with a web browser and it returns JSON. But when I use the 10.0.2.2 for the android call, I get a 400 bad request issue. If use an external WS call, it works fine. The local server I cannot hit. Any thoughts? Thanks in advance.
    George

  14. Hi George,
    where do you host your WCF service? In your local IIS or from Visual Studio Webserver (from Debug/Release from Visual Studio)?

    From your comment, I guess that you are currently hosting your WCF in Visual Studio Webserver. Android emulator can’t access server from Visual Studio Webserver.

    You have to move your WCF to be hosted in your local IIS then you can access it with IP 10.0.2.2.

    For publishing your WCF to IIS you can read more at http://hintdesk.com/wcf-publish-wcf-services-in-iis-7-step-by-step-for-dummies/ (it’s old but I think it still works)

    If your WCF service provides a httpBinding, then after publishing your WCF service to IIS, try to access your WCF service with 10.0.2.2 from Android first with a browser. When the browser in your Android emulator can access it, then your app can too.

  15. Please I need to create an application of search for products (ie): I have to enter criteria of searches as the description of the product and I have to obtain a list of the products which have the same description, I don’t know how to do that, could you help me please.

  16. Hi,
    I got error at StringEntity stringEntity = new StringEntity(new GsonBuilder().create().toJson(object));

    here, GsonBuilder() want to create own class?

  17. @Melina: I don’t have any example for you right now but the concept and implementation are very simple. I think you can do it yourself.

    @Vani: GsonBuilder is a class of Gson library. In that row of code, I make an instance of GsonBuilder –> call create() to create an instance of Gson class then use this Gson class to convert an object to JSON string . The documentation of GsonBuilder can be found here https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/GsonBuilder.html

  18. Hi,

    May I know if these sample codes are compatible with Microsoft visual studio 2008?

    Thank you
    .
    Regards,
    Jacqueline

  19. Hi i have been following the example but I am a bit confused about the asp.net part. I have created my own project in visual studio with my own database etc. for users instead of products but i am having trouble coming to grips with the what way to implement the IEnumerator GetEnumerator() and IEnumerator IEnumerable.GetEnumerator() methods in my User class which i have defiend as:

    public class User : IEnumerable
    {
    …..
    }
    I have implemented a list in my User class,

    List uList { get; set; }

    and have implemented the two methods above as follows:
    public IEnumerator GetEnumerator()
    {
    return uList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
    return uList.GetEnumerator();
    }

    I am trying to call my Post api, when the user clicks a POST button, with the username passed in from visual studio which I then create a user object with that name and then hard code email and password and save it to the database i have set up in Azure like you have above. I then have a get button which is supposed to display all the users in that database in a textfield when the user clicks a Get button but i have not been able to display the user. Can you help please?

  20. @carl: I would like to help but I don’t know where to start because what you ask is basic C# knowledge. I think you should start learning C# before continuing.

    I have a sample code below for your question. It’s just a concept. It doesn’t work with database but only with a List. I hope it helps.

    public class User
    {
    	public string Password { get; set; }
    
    	public string Username { get; set; }
    }
    
    public class UsersController
    {
    	private IList<User> users = new List<User>();
    
    	public IEnumerable<User> Get()
    	{
    		return users;		//replace this with code for getting user list from your database
    	}
    
    	public User Post(string userName, string password)
    	{
    		//replace this with code for saving user to your database
    		User user = new User() { Username = userName, Password = password };
    		users.Add(user);
    
    		return user;
    	}
    }
    

  21. Thanks for the reply. Yes I managed to figure out what I was looking for. I have the method in place to save it to a database, however I assume that my POST method in android client may not be working. Would you be able to help me see where I am going wrong? I have implemented this POST method rather than your one as follows:

    public static String POST(String url,String u){
    InputStream inputStream = null;
    String result = “”;
    try {
    //Create HttpClient
    HttpClient httpClient = new DefaultHttpClient();

    //make POST request to this url
    HttpPost httpPost = new HttpPost(url);
    String json = “”;

    //build json object
    JSONObject jsonObject = new JSONObject();
    jsonObject.accumulate(“UserName”, u);

    //convert json object to JSON to String
    json = jsonObject.toString();

    //set json to StringEntity
    StringEntity se = new StringEntity(json);

    //set HttpPost entity
    httpPost.setEntity(se);

    //set some headers to inform server about the type of content
    httpPost.setHeader(“Accept”, “application/json”);
    httpPost.setHeader(“Content-type”, “application/json”);

    //execute POST request to the specified URL
    HttpResponse httpResponse = httpClient.execute(httpPost);
    //receive response as inputStream
    inputStream = httpResponse.getEntity().getContent();

    if (inputStream != null) {
    result = convertInputStreamToString(inputStream);
    } else {
    result = “Did not work!”;
    }
    } catch (Exception e) {
    Log.d(“InputStream”, e.getLocalizedMessage());
    }
    return result;
    }

    private class HttpAsyncTask extends AsyncTask
    {
    @Override
    protected String doInBackground(String… urls) {
    String u = myName.getText().toString();
    return POST(urls[0], u);
    }
    protected void onPostExecute(String result)
    {
    Toast.makeText(getBaseContext(), “Data sent”, Toast.LENGTH_LONG).show();
    }
    }

    The onPostExecute runs and the “Data sent” text appears but when I check my azure database the data is not in their. Any ideas please?

  22. @carl: “Data sent” doesn’t mean that everything works. It just tells you that your POST action is finished. If web service is alive or POST action is successful or internet connection is available, we don’t know.

    I’m not familiar with JSONObject but I assume that you make correct JSON object. Then your code above is as same as mine. I suggest that you try with Fiddler to catch the traffic or manually make a POST to your web service and see what happens

    http://hintdesk.com/how-to-get-android-emulator-working-with-fiddler/
    http://hintdesk.com/how-to-consume-asp-net-web-api-rc-with-restsharp/

    For Azure I have also a post for it, in case that you want to have a reference

    http://hintdesk.com/android-how-to-consume-an-azure-mobile-services/

    Sorry if I can’t help so much.

  23. I have a ASP.Net 4.0 WebAPI which I hosted on IIS and I use port 9810 and use this url (e.g. http://mymachinename:9180/payments/api/payment), from my Android app. When I run the Android app in an emulator (in my case I tried in both a Google Nexus and Google Nexus S Emulators that I created) and make an AsyncTask call to the webapi I get connection refused error. This was not happening a month ago, but now suddenly it is. Not sure what is the issue. Hence I am asking if I change the port from 9810 to 8172 will it help. Also in my case I published the WebAPI using File System and converted the folder to an application with proper ApplicationPool(in my case .Net v4 ) selected. I am able to run my api independently using the sample url that I mentioned before.

    As per your advice I even tried to change the URL in the android app as http://10.0.2.2:9180/payments/api/payment
    with this it says bad Host. Not sure what I should do. Here’s my snippet of creating the HttpClient and such
    private class LongProcessAPI extends AsyncTask
    {
    //Try this way
    protected String doInBackground(String… params)
    {
    String urlString=params[0]; // URL to call
    String results = “”;
    String message = “”;
    HttpClient client = new DefaultHttpClient();
    HttpGet request = null;
    HttpResponse response = null;

    try
    {

    request = new HttpGet(urlString);
    request.setHeader(“Content-Type”, “text/xml”);
    if (request != null)
    response = client.execute(request);
    }
    ……….

  24. @PANKAJA : Use the web browser in emulator to check if you really can connect to your web service which is hosted at your computer.

    When your web browser can resolve the URL, so do your app. If not, your app can’t too.

    Moreover you have to be sure that you really host your web service under IIS (not Visual Studio Web Server), Android can’t connect to Debug Web Server of Visual Studio

  25. Hello Mr. Nguyen,
    I downloaded both projects, but in order to give it a try, i run the android app in my both emulator and device, in the main activity when i tap the ‘View Products’ button, it crashes and says “AndroidClient_Rest app stopped working”. Your service url is the same as you defined :”http://restwebserviceforandroid.apphb.com/api/products”

    I did not do anything with your code, what can be the problem Mr. Nguyen?

  26. Hello again,
    Solved the problem Mr. Nguyen. After importing the androidclient project in Android Studio, we just need to define the activities in the manifest file.Otherwise, it throws an ActivityNotFoundException. For example;

    Notice that we should define the activity with a dot before its name

  27. @ahmetGd : I can open project without any problem in Android Studio. You can check out from Bitbucket and try to compile it again.

  28. @admin, you may be right, some other people from stackoverflow, said the similar things, like clean project and rebuild it etc. I tried but it did throw the same exception, so i checked the AndroidManifest.xml file, there was only one activity there (.MainActivity) so i added the rest of the activities manually, and it worked.I wrote these in case anybody else can face the same problem.

    Thank you for your response.

  29. @admin you are right, normally it would not work without that activities.Your code is okay, probably when importing project i did something wrong.

    Thanks again for your responses Mr. Nguyen.

  30. I learned I lot form this article!
    Can you tell me how to make the PUT method form JSONHttpClient.
    Thanks a lot.

  31. Hey and thanks a lot for the tutorial. I have downloaded the sourcecode, but there is an error:
    GUI is called by non-GUI thread in NewProductActivity.java:

    @Override protected String doInBackground(String… params) {
    List args = new ArrayList();
    args.add(new BasicNameValuePair(“name”,
    editTextName.getText().toString()));
    How can that be? 🙂

  32. Hi Mr Nguyen, you are so kind and generous. Thanks a lot for spending some time writing this tutorial for everyone to see. You are such an UNSELFISH person!

Leave a Reply

Your email address will not be published. Required fields are marked *