0

Good Day Everyone. I am creating a Xamarin.Forms Portable Application.

I want my Mobile Application to connect to the SQL Database I have in my VS2015 and return a LIST OF CUSTOMERS which should be display to my mobile phone.

In my solution, I have created a Xamarin Portable project and a WebForms project that will handle my Web Services and Database.

The problem is I WASN'T ABLE TO ACCESS THE DATA IN MY WEBFORMS project to my Mobile Device.

enter image description here

The WebServiceUrl I have in WebForms project is http://localhost:50857/api/Customer/

That is also the link I use in my RestClient.cs that supposed to display my List of Customers. My laptop and mobile is connected to the same WiFi.

I even changed the localhost to my laptop's ip address which is 192.168.1.11 but still the mobile wasn't able to access it.

Here's my code for CustomerController project which handles the getting of data from my Database:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using WebFormsDemo;
using WebFormsDemo.ViewModel;

namespace WebFormsDemo.Controllers
{
    public class CustomerController : ApiController
    {
        private EBMSEntities db = new EBMSEntities();

        // GET: api/Customer
        public IQueryable<CustomerViewModel> GetCustomerViewModels()

        {
            var displaycustomerInfo = from cust in db.CUSTOMERs
                                      select new CustomerViewModel
                                      {
                                          Id = cust.CUSTOMER_ID,
                                          CUSTOMER_CODE = cust.CUSTOMER_CODE,
                                          CUSTOMER_NAME = cust.CUSTOMER_NAME,
                                          CUSTOMER_MOBILE_NUMBER = cust.CUSTOMER_MOBILE_NUMBER,
                                          CUSTOMER_EMAIL_ADDRESS = cust.CUSTOMER_EMAIL_ADDRESS,
                                          CUSTOMER_CONTACT = cust.CUSTOMER_EMAIL_ADDRESS + "," + " " + cust.CUSTOMER_MOBILE_NUMBER
                                      };




            return displaycustomerInfo;
        }

    }
}

.

Here's my code for RestClient.cs :

   public class RestClient_Customer<T>
{


    private const string WebServiceUrl = "http://localhost:50857/api/Customer/";

    public async Task<List<T>> GetCustomerAsync()
    {

        var httpClient = new HttpClient();

        var json = await httpClient.GetStringAsync(WebServiceUrl);

        var taskModels = JsonConvert.DeserializeObject<List<T>>(json);

        return taskModels;
      }
  }

CustomerServices.cs

using Plugin.RestClient;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using XamarinFormsDemo.Models;

namespace XamarinFormsDemo.Services
{
    public class CustomerServices
    {


        public async Task<List<Customer>> GetCustomerAsync()
        {
            RestClient_Customer<Customer> restClient = new RestClient_Customer<Customer>();

            var customerList = await restClient.GetCustomerAsync(); //yung getasync ay pantawag as restclient

            return customerList;
        }


    }
}

CustomerViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using XamarinFormsDemo.Models;
using XamarinFormsDemo.Services;
using XamarinFormsDemo.Views;

namespace XamarinFormsDemo.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {


        private List<Customer> _customerList; // keep all customers
        private List<Customer> _searchedCustomerList; // keep a copy for searching
        private Customer _selectedCustomer = new Customer();

        private string _keyword = "";
        public string Keyword
        {
            get
            {
                return _keyword;
            }
            set
            {
                this._keyword = value;

                // while keyword changed we filter Employees
                //Filter();
            }
        }



        private void Filter()
        {
            if (string.IsNullOrWhiteSpace(_keyword))
            {
                CustomerList = _searchedCustomerList;

            }
            else
            {
                // var lowerKeyword = _keyword.ToLower();
                CustomerList = _searchedCustomerList.Where(r => r.CUSTOMER_NAME.ToLower().Contains(_keyword.ToLower())).ToList();
                //  EmployeesList = _searchedEmployeesList.Where(r => r.EMPLOYEE_NAME.Contains(_keyword)).ToList();


            }
        }




        public List<Customer> CustomerList
        {
            get
            {
                return _customerList;
            }
            set
            {
                _customerList = value;
                OnPropertyChanged();
            }
        }



        public CustomerVM()
        {
            InitializeDataAsync();

        }

        private async Task InitializeDataAsync()
        {
            var customerServices = new CustomerServices();
            _searchedCustomerList = await customerServices.GetCustomerAsync();
            CustomerList = await customerServices.GetCustomerAsync();

        }




        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

    }
}

What do you think I've done wrong? Please help me. Thanks a lot.

Jaycee Evangelista
  • 1,107
  • 6
  • 22
  • 52
  • Are you able to access the IP directly from your mobile browser? – Rohit Vipin Mathews Aug 04 '16 at 14:04
  • @Rohit the word 'localhost' here Sir is the one I replaced with my laptop's IP address. So from "http://localhost:50857/api/Customer/"; I changed it to "http://192.168.1.11:50857/api/Customer/"; but I still cannot access the webservice. – Jaycee Evangelista Aug 05 '16 at 02:02
  • 1
    You may need to do some configuring to get it to work and also create an inbound rule in your firewall. If you google it there's a number of articles explaining how to do it. Here's one: [Calling Localhost Web APIs from Visual Studio 2015 Android Emulator](http://briannoyesblog.azurewebsites.net/2016/03/06/calling-localhost-web-apis-from-visual-studio-android-emulator/). – jsanalytics Aug 05 '16 at 02:39
  • @jstreet Sir what specific rule shoud I create in my firewall? – Jaycee Evangelista Aug 05 '16 at 03:16
  • You need an **Inbound Rule** for the port your service is running on. – jsanalytics Aug 05 '16 at 03:33
  • @jstreet Sir I'm done creating a new Inbound Rule by following the link you provided. I even added another binding like this : but still I wasn't able to access it in my mobile phone or in another pc. In my RestClient.cs I also changed the word 'localhost' to my IP address so it becomes "http://192.168.1.11:50857/api/Customer/" and still get the same result. – Jaycee Evangelista Aug 05 '16 at 05:57
  • What result do you get? – jsanalytics Aug 05 '16 at 06:04
  • @jstreet Webpage not available Sir. – Jaycee Evangelista Aug 05 '16 at 06:08
  • What's in `var json` ? – jsanalytics Aug 05 '16 at 06:13
  • @jstreet It is being called by my CustomerServices and the CustomerServices is being called by the CustomerViewModel which is connected to my XAML page that should display the List of Customers. I'll add the code above. – Jaycee Evangelista Aug 05 '16 at 06:16
  • if you place a break point inside `GetCustomerAsync()`, what's in `var json`? – jsanalytics Aug 05 '16 at 06:23
  • @jstreet json = null Sir – Jaycee Evangelista Aug 05 '16 at 06:35
  • 1
    Ok... that's a major problem right there.... you're not getting anything back from the service.... – jsanalytics Aug 05 '16 at 06:37
  • If you point your browser to `http://192.168.1.11:50857/api/Customer/` do you get data? – jsanalytics Aug 05 '16 at 06:38
  • @jstreet no Sir. just a "Bad Request - Invalid Hostname" thing. Even when I use my mobile phone to browse http://192.168.1.11:50857/api/Customer/ I still don't get any data. – Jaycee Evangelista Aug 05 '16 at 06:45
  • This means either you have the wrong IP or your web api service is not working at all.... – jsanalytics Aug 05 '16 at 06:46
  • But if you use `localhost` instead of the IP then you get data, right? – jsanalytics Aug 05 '16 at 06:47
  • @jstreet Yes Sir you're right. In my laptop if I use "http://localhost:50857/api/Customer/"; I was able to see data. But browsing this in my mobile doesn't display anything. Even if i change the 'localhost' to my IP address. – Jaycee Evangelista Aug 05 '16 at 06:50
  • The emulator does not know `localhost`, you have to use the IP number. Make sure you're using the correct IP number for your local machine. Use `ipconfig /all` in the windows command line. The link i sent you is not very detailed but it has everything you need to do to get it working. If you need more details, google it and find other articles but you have to do the whole thing with the configuration file and the firewall. – jsanalytics Aug 05 '16 at 06:57
  • @jstreet Sir what I did is this. In the root folder ofmy program, I go to applicationhost.config. I have added this to my bindings and saved It. Next is I go to Windows Firewall > Advanced Settings > then added a new Inbound Rule. I added the 50857 as my specific port, allow connection, and named it. Do you think what I've done is enough Sir? I've read many articles and almost got the same answers. But still I don't know what's the reason behind this thing. :( – Jaycee Evangelista Aug 05 '16 at 07:54
  • It sounds correct.... You may also want to add the IP address for your Android emulator to the `applicationhost.config`. One suggestion: create a `Console` application and call your web API from there. – jsanalytics Aug 05 '16 at 13:11
  • Another suggestion: right.click your `Droid` project and select **Properties/Android Manifest/Required permissions** and make sure that **INTERNET** is enabled / selected. – jsanalytics Aug 05 '16 at 13:18
  • @jstreet Sir I was able to browse it now using my ip address just like this : http://192.168.1.11:50857/api/Customer/. I was also able to browse it using my phone thru it's internet browser. But the problem is I still wasn't able to get the List of Clients that should be displayed in my mobile. – Jaycee Evangelista Aug 06 '16 at 08:18
  • what's in `var json` now? are you using an actual android device or an emulator? did you try calling the web API from a console client? – jsanalytics Aug 06 '16 at 13:35
  • Please show how you're binding your `CustomerViewModel` to your `ContentPage`. – jsanalytics Aug 06 '16 at 16:11
  • @jstreet Sir the var jason still has a null value. I'm using an actual android Device sir. – Jaycee Evangelista Aug 08 '16 at 09:34
  • @jstreet I'm binding the CustomerViewModel to my ContentPage by using LINQ Expression Sir. Like what I've added above. – Jaycee Evangelista Aug 08 '16 at 09:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120412/discussion-between-jaycee-evangelista-and-jstreet). – Jaycee Evangelista Aug 08 '16 at 09:48

1 Answers1

1

Json.net can deserialize JSON objects, but not XML based ones.

You can either:

  • set the Accept header of your request as application/json if your service is an ASP.NET Web API one: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

  • Change your client code to deserialize received xml data using XmlSerializer.

Your partially edited code:

public async Task<List<T>> GetCustomerAsync()
{
    var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var json = await httpClient.GetStringAsync(WebServiceUrl);

    var taskModels = JsonConvert.DeserializeObject<List<T>>(json);

    return taskModels;
  }
Community
  • 1
  • 1
Benjamin Soulier
  • 2,223
  • 1
  • 18
  • 30