Forum Xamarin.iOS

Using HttpClient for Rest service

Hi guys,

I have to consume a Rest Service, created using Asp.Net Web API (but this is not important), on a project with Xamarin iOS.
I know that I can use ServiceStack or RestSharp but I want to try to use HttpClient.

To deserialise response I need to use method "ReadAsAsync" contained in "System.Net.Http.Formatting" but this It's not included in Framework. I've tried to use assembly contained in Mono 3.2.3 but I have this error:

Error CS1705: Assembly System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' referencesSystem.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' which has a higher version number than imported assembly `System.Net.Http, Version=2.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' (CS1705)

I want to ask to you how properly use HttpClient to consume Rest Service?

I want simply to execute this code on my Xamarin.iOS app:

HttpResponseMessage response = client.GetAsync("api/products").Result; // Blocking call!
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
var products = response.Content.ReadAsAsync<IEnumerable>().Result;
foreach (var p in products)
{
Console.WriteLine("{0}\t{1};\t{2}", p.Name, p.Price, p.Category);
}
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}

I hope you help me.

Thanks!!

Posts

  • DannyCDannyC US ✭✭✭✭

    @mapo80 not sure if you are returning XML or Json but would suggest returning JSON and parsing with Json.net. Check out the store component.

    http://components.xamarin.com/view/json.net

  • MatteoPolitoMatteoPolito ITMember ✭✭

    Yes, rest service returns JSON. Yes, now I'm using json.net with this code:

    string path = "";
    HttpResponseMessage response = Client.GetAsync(path).Result;
    if (response.IsSuccessStatusCode)
    {
    var object = JsonConvert.DeserializeObject (response.Content.ReadAsStringAsync ().Result);

    }

    Is this right? So, it's not possible to use System.Net.Http.Formatting!

    Thanks for your answer.

  • SpartanSpartan USMember

    To use Formatting please install the PCL library Microsoft ASP.NET Web API 2 Client using Nuget.

  • MatteoPolitoMatteoPolito ITMember ✭✭

    Great, thanks! I'll try it.

  • GrantCauseGrantCause AUMember ✭✭

    @mapo80 here is what I would do:

    `
    Create a product item class file as follows:

    public class ProductItem
    {
        public ProductItem ()
        {
        }
    
        public string name { get; set; }
        public string price { get; set; }
        public string category { get; set; }
    }
    

    This task can be made easier by using http://json2csharp.com/ and giving it the JSON output from your call or the URL for the call.

    Once you have this then use the following to make the HTTP request / response calls where SearchRequest is the URL Encoded http web address of your API. Note only URL encode the parameters to the request usually this is the stuff after &param= in quotes:

        private string UrlEncodeParameter(string paramToEncode)
        {
            string urlEncodedParam = string.Empty;
    
            // remove whitespace from search parameter and URL encode it
            urlEncodedParam = paramToEncode.Trim();
            urlEncodedParam = Uri.EscapeDataString(urlEncodedParam);
    
            return urlEncodedParam;
        }
    
        private HttpWebRequest SetHttpRequest(string apiCredentials, string SearchRequest)
        {
            _httpRequest = (HttpWebRequest)null;
    
            if (string.IsNullOrEmpty(SearchRequest))
                throw new ArgumentNullException(string.Format("A search request is required by the Search method"));
    
            // Attempt to establish http request
            try
            {
                _httpRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri(SearchRequest));
                _httpRequest.Credentials = new NetworkCredential (apiCredentials, apiCredentials);
            } catch (Exception ex) {
                string message = string.Format("Error creating request.  Check inner details for more info: {0}", SearchRequest);
                var requestException = new ApplicationException(message, ex);
                throw requestException;
            }
    
            return _httpRequest;
        }
    
    
        public HttpWebResponse Search()
        {
            // Attempt to get http response
            HttpWebResponse response = (HttpWebResponse)null;
            try
            {
                response = (HttpWebResponse)apiSearchParameters.HttpRequest.GetResponse();
                if (response.StatusCode != HttpStatusCode.OK) {
                    throw new Exception(String.Format("Server error (HTTP {0}: {1}).", response.StatusCode,
                        response.StatusDescription));
                }
                return response;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return response;
            }
        }
    

    Now using Newtonsoft.Json.Net deserialise the Product Item from the JSON response:

            // Create a basic search request
            HttpWebRequest httpWebRequest = SetHttpRequest("your api credentials", “your URL encoded http url for the API");
            Console.WriteLine("httpWebRequest = " + httpWebRequest.Address.AbsoluteUri);
    
            // Perform search
            try
            {
                HttpWebResponse httpRes = Search();
                if (httpRes != null)
                {
                    var responseStream = httpRes.GetResponseStream();
    
                    var json = (JsonObject)JsonObject.Load(responseStream);
    
                    var deserializedJsonRecords = JsonConvert.DeserializeObject<ProductItem>(json.ToString());
    
                   var searchResults = new List<ProductItem>();
    
                   searchResults = (
                      from result in deserializedJsonRecords
                      select new ProductItem {
                          name = result.name,
                          price = result.price, 
                          category = result.category
                      }
                   ).ToList();
                }
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
    

    Hope this helps.
    `

  • MatteoPolitoMatteoPolito ITMember ✭✭

    Ok, thanks for your answer.

  • SKallSKall USMember ✭✭✭✭

    Don't use a blocking web call. Here is an example client which uses abstracted serializers (and supports Json.NET and ServiceStack plugins):

    https://github.com/sami1971/SimplyMobile/blob/master/Core/SimplyMobile.Web/RestClient.cs

  • MatteoPolitoMatteoPolito ITMember ✭✭

    Great thanks.

    My goal is to create a project for my rest service that I can use in my MonoDroid and MonoTouch application.

    I don't want to create a project for every application. I've seen that HttpClient is platform specific (http://forums.xamarin.com/discussion/7719/using-httpclient).

    I've to use pcl version of HttpClient?

  • SKallSKall USMember ✭✭✭✭

    HttpClient can be PCL if you don't want WP8 support. If you do, then either create an interface for the web client and then use DI at runtime. Using Microsoft's async HttpClient PCL library has been troublesome.

  • softlionsoftlion FRBeta ✭✭✭
    edited December 2013

    HttpClient can be PCL if you don't want WP8 support

    That is not true. I have http client set up in the same pcl project used by all 3 platforms.

    Using Microsoft's async HttpClient PCL library has been troublesome.

    In fact, it is Xamarin error messages which are buried, especially for iOS compilation (it should be better for the next release). It works perfectly with no problem. Just never install the HttpClient PCL package in your ios/android project, only in pcl projects. Just reference System.Http from mono in android/ios. And also never add the Microsoft.Bcl package in your ios/android project (ignore the warning).

  • ShamnadShamnad USMember ✭✭✭
    edited April 2014

    can anyone can help me to retriving value from a server using json webservice

  • ShamnadShamnad USMember ✭✭✭
    edited April 2014

    anyone can help me to retriving value from a server using json webservice

  • h8tow8h8tow8 USMember

    can anyone help me to understand why when I use similar code to Richard's I get the following error:

    {System.Net.WebException: Error: ConnectFailure (Connection timed out) ---> System.Net.Sockets.SocketException: Connection timed out
    at System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP) [0x00000] in :0
    at System.Net.Web...

    I post the same json string to the same url using fiddler and have no problems but does not matter what i do i always get this error calling PostAsync from android.

  • SKallSKall USMember ✭✭✭✭

    Are you trying to call a service on a localhost? If so, try address 10.0.2.2 instead of localhost or 127.0.0.1. If not, check that you can connect to the address in question from the Android device.

  • h8tow8h8tow8 USMember

    Sami, thank you for your advise that got me thinking ;~).
    I was 100% convinced that these is something to do with android/xamarin and portable libraries i use but it turned out the firewall on my windows.

  • PriyabrataDashPriyabrataDash USMember ✭✭

    I faced in adding the Microsoft HttpClient Libraries reference to Xamarin Studio using NuGet Pachage manager.
    After a lot of digging I found out the problem is with "Target Frameworks" Build options.
    If you have checked "Silverlight 4" as a target Framework for your project you may face Adding reference issue.
    If this is the case with you simply go to 'Project->Options->Build->General->Under Target Framework, untick Silverlight 4 option.

    Just refresh the Project & Build. It worked for me.

  • MikeKenyon.7267MikeKenyon.7267 USMember

    I am having no success with 10.0.2.2, is there something else to try?

  • MartinUshimaMartinUshima USMember

    @h8tow8 did you try in a device?

    I'm getting the same error, (ConnectFailure (Connection timed out)), when using HttpClient and testing in a device.

  • h8tow8h8tow8 USMember

    my problem was silly - i had a firewall turned on on a pc where the web service was running ;~)
    once i disabled it - all was good

  • MartinUshimaMartinUshima USMember

    Fixed.

    It was a DNS setting and the IT area help me solve it.

    Thanks!

  • ShamnadShamnad USMember ✭✭✭

    hai guys,

              i have a problem on populating table view in xamarin ios 
              i have a string in an url, which is like this (25*SALADS*36.png$28*OMELETTE*36.png$29*PASTA*36.png$30*MEAT  DISHES*36.png$32*SALADS*food2.png$33*SOUPS*food.png$) 
    

    i need to populate table view using this String i can fetch the data to an array
    but how can i populate table view using that array?

    this is my code in controller

        using System;
        using System.CodeDom.Compiler;
        using System.Collections.Generic;
        using System.Drawing;
        using System.Net;
        using System.Threading;
        using System.IO;
        using System.Net.Http;
        using System.Collections;
        using System .Linq; 
        using System.Diagnostics;
        using System.Threading.Tasks;
        using MonoTouch.Foundation;
        using MonoTouch.UIKit;
        namespace project
        {
    
    public class cm_item
        {
            // category id
            public int cat_id { get; set; }
            // category Name 
            public string cat_name { get; set; }
            // image url from server
            public string cat_url { get; set; }
        }
    
            partial class specialViewController : UIViewController
            { 
                cm_item[]ns;//total records  
                public specialViewController (IntPtr handle) : base (handle)
                {
    
                }     
                public async override void ViewDidLoad()
                {
                    base.ViewDidLoad();              
                    var table = new UITableView (new RectangleF (0, 0, View.Bounds.Width, View.Bounds.Height));
    
                    View.Add (table);
    
                    Task<string> siz = getall ();           //  progress.Show(); 
                //    var s = await siz; 
                } 
                /// <summary>
                /// async data loading.
                /// </summary>
    
                async Task<string> getall() 
                { 
                    var req = "http://xam.dimindserver.co.in/category/display?id=1";// calling the string from the url 
                    HttpClient client = new HttpClient ();
                    Task<string> getStringTask = client.GetStringAsync (req);
                    string urlContents = await getStringTask;
                    if (urlContents != "") {
                        int inc = 0;
                        int totalRec = Convert.ToInt32 (urlContents.Split ('$').Count ());
                        ns = new cm_item[totalRec - 1];
                        foreach (System.String  mans in  urlContents.Split('$')) {
                            if (mans != "") {
                                System.String[] singCate = mans.ToString ().Split ('*');
                                if (singCate.Count () != 0) {                            
                                    cm_item Cm_Cate = new  cm_item ();
                                    Cm_Cate.cat_id = Convert.ToInt32 (singCate [0].ToString ());                    //id form db 
                                    Cm_Cate.cat_name = singCate [1].ToString ();  
                                    Cm_Cate.cat_url = singCate [2];
                                    ns [inc] = Cm_Cate; 
                                    inc++; 
                                }
    
                            }
                          }  
                        };
    
                    return "True"; 
    
                    } 
    
                }
                }
    

    i have another Class for data source

        using System;
        using System.Drawing;
    
        using MonoTouch.Foundation;
        using MonoTouch.UIKit;
    
        namespace project
        {
            public class itemsTableSource:UITableViewSource
            {
                cm_item[] _category;
                UINavigationController _controller;
                string cellIdentifier = "TableCell";
    
                public itemsTableSource (cm_item[] category, UINavigationController controller)
                {
                    _category = category;
                    _controller = controller;
                }
                public override int RowsInSection (UITableView tableview, int section)
                {
                    return _category.Length;
                }
                public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
                {
                    UITableViewCell cell = tableView.DequeueReusableCell("TableCell");
                    if (cell == null) {
                        cell = new UITableViewCell (UITableViewCellStyle.Subtitle, "TableCell");
                    }
    
                    cell.TextLabel.Text = _category[indexPath.Row].cat_name;
                    cell.Accessory = UITableViewCellAccessory.DetailDisclosureButton;
                    return cell;
                }
            }
    
    
        }
    

    how can i populate table view using that array

  • ShamnadShamnad USMember ✭✭✭

    i got my error ..with help of some other friends............

  • SagarPanwalaSagarPanwala USMember ✭✭✭

    @MartinUshima : Can you please tell me in detail , how you have fixed it? I'm facing this connect failure issue on user device also.

  • MartinUshimaMartinUshima USMember

    @SagarPanwala, the scenario that I was facing was that the services that I was consuming were outside my company network. So, I talked with the IT guys in my company, specified them the IPs addresses and URLs that I was trying to connect to. They register that info in the allowed or trusted source and that was it.

    It had nothing to do with code, just network settings.

    The issue is that those settings are managed by the IT area, nothing to do with me. :(

Sign In or Register to comment.