FubarDevelopment / restsharp.portable

Some kind of a RestSharp port to PCL
BSD 2-Clause "Simplified" License
95 stars 33 forks source link

Port from RestSharp for a Xamarin Forms Project #86

Closed bolenton closed 7 years ago

bolenton commented 8 years ago
using System;
using System.Collections.Generic;
using RestSharp.Portable;
using RestSharp.Portable.Authenticators;
using RestSharp.Portable.HttpClient;

namespace ApiWrapper {
    public class BaseApiSet<T> where T : new()
    {
        private readonly string _baseUrl;
        private string _username;
        private string _password;
        private readonly ContentType _contentType;
        private IDictionary<string, string> _parameters;

        public string BaseUrl { get { return _baseUrl; } }

        public BaseApiSet(string baseUrl, string username, string password) {
            _baseUrl = baseUrl;
            _username = username;
            _password = password;
        }

        public T Execute(string serviceName) {
            this._parameters = new Dictionary<string, string>();
            this._parameters.Add("srv", serviceName);
            var request = CreateRestRequest(Method.GET, _baseUrl);

            var results = ExecuteRequest(request);
            return results.Data;
        }

        public T Execute(string serviceName, Dictionary<string, string> parameters) {
            this._parameters = new Dictionary<string, string>();
            this._parameters.Add("srv", serviceName);

            foreach (var current in parameters) {
                this._parameters.Add(current.Key, current.Value);
            }

            var request = CreateRestRequest(Method.GET, _baseUrl);

            var results = ExecuteRequest(request);
            return results.Data;
        }

        public T Execute(string serviceName, QueryObject qo) {
            this._parameters = new Dictionary<string, string>();
            this._parameters.Add("srv", serviceName);
            var request = CreateRestRequest(Method.GET, _baseUrl);

            foreach (var pair in qo.ToDictionary()) {
                request.AddParameter(pair.Key, pair.Value);
            }

            var results = ExecuteRequest(request);
            return results.Data;
        }

        public S Execute<S>(string serviceName, Dictionary<string, string> parameters) where S : new() {
            this._parameters = new Dictionary<string, string>();
            this._parameters.Add("srv", serviceName);

            foreach (var current in parameters) {
                this._parameters.Add(current.Key, current.Value);
            }

            var request = CreateRestRequest(Method.GET, _baseUrl);

            var results = ExecuteGenericRequest<S>(request);
            return results.Data;
        }

        internal T Update(string serviceName, string formValues, Dictionary<string, string> parameters) {
            var updateUrl = _baseUrl + "?srv=" + serviceName;

            foreach (var pair in parameters) {
                updateUrl += "&" + pair.Key + "=" + pair.Value;
            }

            this._parameters = new Dictionary<string, string>();
            var request = CreateRestRequest(Method.POST, updateUrl);

            request.AddParameter("application/x-www-form-urlencoded", formValues, ParameterType.RequestBody);
            var results = ExecuteRequest(request);
            return results.Data;
        }

        internal T Create(string serviceName, string formValues) {
            var createUrl = _baseUrl + "?srv=" + serviceName;
            this._parameters = new Dictionary<string, string>();
            var request = CreateRestRequest(Method.POST, createUrl);
            request.AddParameter("application/x-www-form-urlencoded", formValues, ParameterType.RequestBody);
            var results = ExecuteRequest(request);
            return results.Data;
        }

        internal S Create<S>(string serviceName, string formValues) where S : new() {
            var createUrl = _baseUrl + "?srv=" + serviceName;
            this._parameters = new Dictionary<string, string>();
            var request = CreateRestRequest(Method.POST, createUrl);
            request.AddParameter("application/x-www-form-urlencoded", formValues, ParameterType.RequestBody);
            var results = ExecuteGenericRequest<S>(request);
            return results.Data;
        }

        internal T CreateWithXml(string serviceName, string xml) {
            var createUrl = _baseUrl + "?srv=" + serviceName;   
            this._parameters = new Dictionary<string, string>();
            var request = CreateRestRequest(Method.POST, createUrl, "application/xml");
            request.AddParameter("application/xml", xml, ParameterType.RequestBody);
            var results = ExecuteRequest(request);
            return results.Data;
        }

        protected IRestResponse<T> ExecuteRequest(IRestRequest request) {
            var client = new RestClient(_baseUrl);
            client.Authenticator = new HttpBasicAuthenticator(this._username, this._password);
            var response = client.Execute<T>(request);

            // Code always hangs around here. Code base was using RestSharp, I made changes to use RestSharp.Portable
            // Don't know what else to do to get this to work. I would love any assistance getting this port to fully work.

            if ((int)response.Result.StatusCode > 300) {
                throw new Exception(response.Result.StatusDescription);
            }
            else if (!string.IsNullOrEmpty(response.Exception.Message)) {
                throw new Exception(response.Exception.Message);
            }

            return response.Result;
        }

        protected IRestResponse<S> ExecuteGenericRequest<S>(IRestRequest request) where S : new() {
            var client = new RestClient(_baseUrl);
            client.Authenticator = new HttpBasicAuthenticator(this._username, this._password);
            var response = client.Execute<S>(request);

            if ((int)response.Result.StatusCode > 300) {
                throw new Exception(response.Result.StatusDescription);
            }
            else if (!string.IsNullOrEmpty(response.Exception.Message)) {
                throw new Exception(response.Exception.Message);
            }

            return response.Result;
        }

        private RestRequest CreateRestRequest(Method method, string url, string contentType = null) {

            //var test = JRest.Get<string>("http://pokepedia.com/api/getbyname/pikachu").Result;

            var request = new RestRequest(method) {
                Resource = url
            };

            if (method == Method.POST && string.IsNullOrEmpty(contentType)) {
                contentType = "application/x-www-form-urlencoded";
            }
            else {
                request.Serializer.ContentType = _contentType == ContentType.JSON ? "application/json" : "application/xml";
                //request.RequestType = _contentType == ContentType.JSON ? DataFormat.Json : DataFormat.Xml;
            }
            request.AddHeader("Accept-Encoding", "gzip,deflate");
            request.AddHeader("Content-Type", !string.IsNullOrEmpty(contentType) ? contentType : _contentType == ContentType.XML ? "application/xml" : "application/json");

            if (_parameters != null && _parameters.Count > 0) {
                foreach (var current in _parameters) {
                    request.AddParameter(current.Key, current.Value);
                }
            }

            return request;
        }

        //
        // Summary:
        //     Data formats
        public enum DataFormat
        {
            Json = 0,
            Xml = 1
        }
    }
}

Code base was using RestSharp, I made changes to use RestSharp.Portable. Don't know what else to do to get this to work. I would love any assistance getting this port to fully work. Code seem to always hang when I try to Execute.

The problem mostly stems form the ExecuteRequest(IRestRequest request) or the CreateRestRequest(Method method, string url, string contentType = null) Any help would be greatly appreciated.

fubar-coder commented 7 years ago

There are several incompatible changes in RestSharp.Portable when compared to the original RestSharp project:

  1. There is no DataFormat type. The format is chosen by setting the Serializer.
  2. The API is completely async.
  3. Setting Accept-Encoding shouldn't be necessary, but you can use your own IEncoding implementation or the ones provided in the encoding NuGet package
  4. Don't set application/x-www-form-urlencoded manually. It will automatically be set when you have a GetOrPost parameter in a HTTP POST request.

There are several other changes and I'll help answering them when needed.