All Downloads are FREE. Search and download functionalities are using the official Maven repository.

csharp.ApiClient.mustache Maven / Gradle / Ivy

There is a newer version: 3.0.0-rc1
Show newest version
{{>partial_header}}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using System.IO;
{{^netStandard}}
{{^supportsUWP}}
using System.Web;
{{/supportsUWP}}
{{/netStandard}}
using System.Linq;
using System.Net;
using System.Text;
using Newtonsoft.Json;
{{#netStandard}}
using RestSharp.Portable;
using RestSharp.Portable.HttpClient;
{{/netStandard}}
{{^netStandard}}
using RestSharp;
{{/netStandard}}

namespace {{packageName}}.Client
{
    /// 
    /// API client is mainly responsible for making the HTTP call to the API backend.
    /// 
    {{>visibility}} partial class ApiClient
    {
        private JsonSerializerSettings serializerSettings = new JsonSerializerSettings
        {
            ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
        };

        /// 
        /// Allows for extending request processing for  generated code.
        /// 
        /// The RestSharp request object
        partial void InterceptRequest(IRestRequest request);

        /// 
        /// Allows for extending response processing for  generated code.
        /// 
        /// The RestSharp request object
        /// The RestSharp response object
        partial void InterceptResponse(IRestRequest request, IRestResponse response);

        /// 
        /// Initializes a new instance of the  class
        /// with default configuration.
        /// 
        public ApiClient()
        {
            Configuration = {{packageName}}.Client.Configuration.Default;
            RestClient = new RestClient("{{{basePath}}}");
            {{#netStandard}}
            RestClient.IgnoreResponseStatusCode = true;
            {{/netStandard}}
        }

        /// 
        /// Initializes a new instance of the  class
        /// with default base path ({{{basePath}}}).
        /// 
        /// An instance of Configuration.
        public ApiClient(Configuration config)
        {
            Configuration = config ?? {{packageName}}.Client.Configuration.Default;

            RestClient = new RestClient(Configuration.BasePath);
            {{#netStandard}}
            RestClient.IgnoreResponseStatusCode = true;
            {{/netStandard}}
        }

        /// 
        /// Initializes a new instance of the  class
        /// with default configuration.
        /// 
        /// The base path.
        public ApiClient(String basePath = "{{{basePath}}}")
        {
           if (String.IsNullOrEmpty(basePath))
                throw new ArgumentException("basePath cannot be empty");

            RestClient = new RestClient(basePath);
            {{#netStandard}}
            RestClient.IgnoreResponseStatusCode = true;
            {{/netStandard}}
            Configuration = Client.Configuration.Default;
        }

        /// 
        /// Gets or sets the default API client for making HTTP calls.
        /// 
        /// The default API client.
        [Obsolete("ApiClient.Default is deprecated, please use 'Configuration.Default.ApiClient' instead.")]
        public static ApiClient Default;

        /// 
        /// Gets or sets an instance of the IReadableConfiguration.
        /// 
        /// An instance of the IReadableConfiguration.
        /// 
        ///  helps us to avoid modifying possibly global
        /// configuration values from within a given client. It does not guarantee thread-safety
        /// of the  instance in any way.
        /// 
        public IReadableConfiguration Configuration { get; set; }

        /// 
        /// Gets or sets the RestClient.
        /// 
        /// An instance of the RestClient
        public RestClient RestClient { get; set; }

        // Creates and sets up a RestRequest prior to a call.
        private RestRequest PrepareRequest(
            String path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody,
            Dictionary headerParams, Dictionary formParams,
            Dictionary fileParams, Dictionary pathParams,
            String contentType)
        {
            var request = new RestRequest(path, method);
            {{#netStandard}}
            // disable ResetSharp.Portable built-in serialization
            request.Serializer = null;
            {{/netStandard}}

            // add path parameter, if any
            foreach(var param in pathParams)
                request.AddParameter(param.Key, param.Value, ParameterType.UrlSegment);

            // add header parameter, if any
            foreach(var param in headerParams)
                request.AddHeader(param.Key, param.Value);

            // add query parameter, if any
            foreach(var param in queryParams)
                request.AddQueryParameter(param.Key, param.Value);

            // add form parameter, if any
            foreach(var param in formParams)
                request.AddParameter(param.Key, param.Value);

            // add file parameter, if any
            foreach(var param in fileParams)
            {
                {{#netStandard}}
                request.AddFile(param.Value);
                {{/netStandard}}
                {{^netStandard}}
                {{^supportsUWP}}
                request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType);
                {{/supportsUWP}}
                {{#supportsUWP}}
                byte[] paramWriter = null;
                param.Value.Writer = delegate (Stream stream) { paramWriter = ToByteArray(stream); };
                request.AddFile(param.Value.Name, paramWriter, param.Value.FileName, param.Value.ContentType);
                {{/supportsUWP}}
                {{/netStandard}}
            }

            if (postBody != null) // http body (model or byte[]) parameter
            {
                {{#netStandard}}
                request.AddParameter(new Parameter { Value = postBody, Type = ParameterType.RequestBody, ContentType = contentType });
                {{/netStandard}}
                {{^netStandard}}
                request.AddParameter(contentType, postBody, ParameterType.RequestBody);
                {{/netStandard}}
            }

            return request;
        }

        /// 
        /// Makes the HTTP request (Sync).
        /// 
        /// URL path.
        /// HTTP method.
        /// Query parameters.
        /// HTTP body (POST request).
        /// Header parameters.
        /// Form parameters.
        /// File parameters.
        /// Path parameters.
        /// Content Type of the request
        /// Object
        public Object CallApi(
            String path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody,
            Dictionary headerParams, Dictionary formParams,
            Dictionary fileParams, Dictionary pathParams,
            String contentType)
        {
            var request = PrepareRequest(
                path, method, queryParams, postBody, headerParams, formParams, fileParams,
                pathParams, contentType);

            // set timeout
            {{#netStandard}}RestClient.Timeout = TimeSpan.FromMilliseconds(Configuration.Timeout);{{/netStandard}}
            {{^netStandard}}RestClient.Timeout = Configuration.Timeout;{{/netStandard}}
            // set user agent
            RestClient.UserAgent = Configuration.UserAgent;

            InterceptRequest(request);
            {{#netStandard}}
            var response = RestClient.Execute(request).Result;
            {{/netStandard}}
            {{^netStandard}}
            {{^supportsUWP}}
            var response = RestClient.Execute(request);
            {{/supportsUWP}}
            {{#supportsUWP}}
            // Using async method to perform sync call (uwp-only)
            var response = RestClient.ExecuteTaskAsync(request).Result;
            {{/supportsUWP}}
            {{/netStandard}}
            InterceptResponse(request, response);

            return (Object) response;
        }
        {{#supportsAsync}}
        /// 
        /// Makes the asynchronous HTTP request.
        /// 
        /// URL path.
        /// HTTP method.
        /// Query parameters.
        /// HTTP body (POST request).
        /// Header parameters.
        /// Form parameters.
        /// File parameters.
        /// Path parameters.
        /// Content type.
        /// The Task instance.
        public async System.Threading.Tasks.Task CallApiAsync(
            String path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody,
            Dictionary headerParams, Dictionary formParams,
            Dictionary fileParams, Dictionary pathParams,
            String contentType)
        {
            var request = PrepareRequest(
                path, method, queryParams, postBody, headerParams, formParams, fileParams,
                pathParams, contentType);
            InterceptRequest(request);
            var response = await RestClient.Execute{{^netStandard}}TaskAsync{{/netStandard}}(request);
            InterceptResponse(request, response);
            return (Object)response;
        }{{/supportsAsync}}

        /// 
        /// Escape string (url-encoded).
        /// 
        /// String to be escaped.
        /// Escaped string.
        public string EscapeString(string str)
        {
            return UrlEncode(str);
        }

        /// 
        /// Create FileParameter based on Stream.
        /// 
        /// Parameter name.
        /// Input stream.
        /// FileParameter.
        public FileParameter ParameterToFile(string name, Stream stream)
        {
            if (stream is FileStream)
                return FileParameter.Create(name, ReadAsBytes(stream), Path.GetFileName(((FileStream)stream).Name));
            else
                return FileParameter.Create(name, ReadAsBytes(stream), "no_file_name_provided");
        }

        /// 
        /// If parameter is DateTime, output in a formatted string (default ISO 8601), customizable with Configuration.DateTime.
        /// If parameter is a list, join the list with ",".
        /// Otherwise just return the string.
        /// 
        /// The parameter (header, path, query, form).
        /// Formatted string.
        public string ParameterToString(object obj)
        {
            if (obj is DateTime)
                // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
                // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
                // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
                // For example: 2009-06-15T13:45:30.0000000
                return ((DateTime)obj).ToString (Configuration.DateTimeFormat);
            else if (obj is DateTimeOffset)
                // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
                // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
                // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
                // For example: 2009-06-15T13:45:30.0000000
                return ((DateTimeOffset)obj).ToString (Configuration.DateTimeFormat);
            else if (obj is IList)
            {
                var flattenedString = new StringBuilder();
                foreach (var param in (IList)obj)
                {
                    if (flattenedString.Length > 0)
                        flattenedString.Append(",");
                    flattenedString.Append(param);
                }
                return flattenedString.ToString();
            }
            else
                return Convert.ToString (obj);
        }

        /// 
        /// Deserialize the JSON string into a proper object.
        /// 
        /// The HTTP response.
        /// Object type.
        /// Object representation of the JSON string.
        public object Deserialize(IRestResponse response, Type type)
        {
            {{^netStandard}}IList{{/netStandard}}{{#netStandard}}IHttpHeaders{{/netStandard}} headers = response.Headers;
            if (type == typeof(byte[])) // return byte array
            {
                return response.RawBytes;
            }

            // TODO: ? if (type.IsAssignableFrom(typeof(Stream)))
            if (type == typeof(Stream))
            {
                if (headers != null)
                {
                    var filePath = String.IsNullOrEmpty(Configuration.TempFolderPath)
                        ? Path.GetTempPath()
                        : Configuration.TempFolderPath;
                    var regex = new Regex(@"Content-Disposition=.*filename=['""]?([^'""\s]+)['""]?$");
                    foreach (var header in headers)
                    {
                        var match = regex.Match(header.ToString());
                        if (match.Success)
                        {
                            string fileName = filePath + SanitizeFilename(match.Groups[1].Value.Replace("\"", "").Replace("'", ""));
                            File.WriteAllBytes(fileName, response.RawBytes);
                            return new FileStream(fileName, FileMode.Open);
                        }
                    }
                }
                var stream = new MemoryStream(response.RawBytes);
                return stream;
            }

            if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object
            {
                return DateTime.Parse(response.Content,  null, System.Globalization.DateTimeStyles.RoundtripKind);
            }

            if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type
            {
                return ConvertType(response.Content, type);
            }

            // at this point, it must be a model (json)
            try
            {
                return JsonConvert.DeserializeObject(response.Content, type, serializerSettings);
            }
            catch (Exception e)
            {
                throw new ApiException(500, e.Message);
            }
        }

        /// 
        /// Serialize an input (model) into JSON string
        /// 
        /// Object.
        /// JSON string.
        public String Serialize(object obj)
        {
            try
            {
                return obj != null ? JsonConvert.SerializeObject(obj) : null;
            }
            catch (Exception e)
            {
                throw new ApiException(500, e.Message);
            }
        }

        /// 
        ///Check if the given MIME is a JSON MIME.
        ///JSON MIME examples:
        ///    application/json
        ///    application/json; charset=UTF8
        ///    APPLICATION/JSON
        ///    application/vnd.company+json
        /// 
        /// MIME
        /// Returns True if MIME type is json.
        public bool IsJsonMime(String mime)
        {
            var jsonRegex = new Regex("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$");
            return mime != null && (jsonRegex.IsMatch(mime) || mime.Equals("application/json-patch+json"));
        }

        /// 
        /// Select the Content-Type header's value from the given content-type array:
        /// if JSON type exists in the given array, use it;
        /// otherwise use the first one defined in 'consumes'
        /// 
        /// The Content-Type array to select from.
        /// The Content-Type header to use.
        public String SelectHeaderContentType(String[] contentTypes)
        {
            if (contentTypes.Length == 0)
                return "application/json";

            foreach (var contentType in contentTypes)
            {
                if (IsJsonMime(contentType.ToLower()))
                    return contentType;
            }

            return contentTypes[0]; // use the first content type specified in 'consumes'
        }

        /// 
        /// Select the Accept header's value from the given accepts array:
        /// if JSON exists in the given array, use it;
        /// otherwise use all of them (joining into a string)
        /// 
        /// The accepts array to select from.
        /// The Accept header to use.
        public String SelectHeaderAccept(String[] accepts)
        {
            if (accepts.Length == 0)
                return null;

            if (accepts.Contains("application/json", StringComparer.OrdinalIgnoreCase))
                return "application/json";

            return String.Join(",", accepts);
        }

        /// 
        /// Encode string in base64 format.
        /// 
        /// String to be encoded.
        /// Encoded string.
        public static string Base64Encode(string text)
        {
            return System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text));
        }

        /// 
        /// Dynamically cast the object into target type.
        /// 
        /// Object to be casted
        /// Target type
        /// Casted object
        {{#supportsAsync}}
        public static dynamic ConvertType(dynamic fromObject, Type toObject)
        {{/supportsAsync}}
        {{^supportsAsync}}
        public static object ConvertType(T fromObject, Type toObject) where T : class
        {{/supportsAsync}}
        {
            return Convert.ChangeType(fromObject, toObject);
        }

        /// 
        /// Convert stream to byte array
        /// 
        /// Input stream to be converted
        /// Byte array
        public static byte[] ReadAsBytes(Stream inputStream)
        {
            byte[] buf = new byte[16*1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int count;
                while ((count = inputStream.Read(buf, 0, buf.Length)) > 0)
                {
                    ms.Write(buf, 0, count);
                }
                return ms.ToArray();
            }
        }

        /// 
        /// URL encode a string
        /// Credit/Ref: https://github.com/restsharp/RestSharp/blob/master/RestSharp/Extensions/StringExtensions.cs#L50
        /// 
        /// String to be URL encoded
        /// Byte array
        public static string UrlEncode(string input)
        {
            const int maxLength = 32766;

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (input.Length <= maxLength)
            {
                return Uri.EscapeDataString(input);
            }

            StringBuilder sb = new StringBuilder(input.Length * 2);
            int index = 0;

            while (index < input.Length)
            {
                int length = Math.Min(input.Length - index, maxLength);
                string subString = input.Substring(index, length);

                sb.Append(Uri.EscapeDataString(subString));
                index += subString.Length;
            }

            return sb.ToString();
        }

        /// 
        /// Sanitize filename by removing the path
        /// 
        /// Filename
        /// Filename
        public static string SanitizeFilename(string filename)
        {
            Match match = Regex.Match(filename, @".*[/\\](.*)$");

            if (match.Success)
            {
                return match.Groups[1].Value;
            }
            else
            {
                return filename;
            }
        }
        {{^netStandard}}
        {{#supportsUWP}}
        /// 
        /// Convert stream to byte array
        /// 
        /// IO stream
        /// Byte array
        public static byte[] ToByteArray(Stream stream)
        {
            stream.Position = 0;
            byte[] buffer = new byte[stream.Length];
            for (int totalBytesCopied = 0; totalBytesCopied < stream.Length;)
                totalBytesCopied += stream.Read(buffer, totalBytesCopied, Convert.ToInt32(stream.Length) - totalBytesCopied);
            return buffer;
        }
        {{/supportsUWP}}
        {{/netStandard}}

        /// 
        /// Convert params to key/value pairs. 
        /// Use collectionFormat to properly format lists and collections.
        /// 
        /// Key name.
        /// Value object.
        /// A list of KeyValuePairs
        public IEnumerable> ParameterToKeyValuePairs(string collectionFormat, string name, object value)
        {
            var parameters = new List>();

            if (IsCollection(value) && collectionFormat == "multi")
            {
                var valueCollection = value as IEnumerable;
                parameters.AddRange(from object item in valueCollection select new KeyValuePair(name, ParameterToString(item)));
            }
            else
            {
                parameters.Add(new KeyValuePair(name, ParameterToString(value)));
            }

            return parameters;
        }

        /// 
        /// Check if generic object is a collection.
        /// 
        /// 
        /// True if object is a collection type
        private static bool IsCollection(object value)
        {
            return value is IList || value is ICollection;
        }
    }
}