using System; using System.Collections.Generic; using System.Globalization; using System.Text.RegularExpressions; using System.IO; using System.Web; using System.Linq; using System.Net; using System.Text; using Newtonsoft.Json; using RestSharp; using RestSharp.Extensions; namespace {{packageName}}.Client { /// /// API client is mainly responible for making the HTTP call to the API backend. /// public class ApiClient { private readonly Dictionary _defaultHeaderMap = new Dictionary(); /// /// Initializes a new instance of the class. /// /// The base path. public ApiClient(String basePath="{{basePath}}") { BasePath = basePath; RestClient = new RestClient(BasePath); } /// /// Gets or sets the base path. /// /// The base path public string BasePath { get; set; } /// /// Gets or sets the RestClient. /// /// An instance of the RestClient public RestClient RestClient { get; set; } /// /// Gets the default header. /// public Dictionary DefaultHeader { get { return _defaultHeaderMap; } } /// /// Makes the HTTP request (Sync). /// /// URL path. /// HTTP method. /// Query parameters. /// HTTP body (POST request). /// Header parameters. /// Form parameters. /// File parameters. /// Authentication settings. /// Object public Object CallApi(String path, RestSharp.Method method, Dictionary queryParams, String postBody, Dictionary headerParams, Dictionary formParams, Dictionary fileParams, String[] authSettings) { var request = new RestRequest(path, method); UpdateParamsForAuth(queryParams, headerParams, authSettings); // add default header, if any foreach(var defaultHeader in _defaultHeaderMap) request.AddHeader(defaultHeader.Key, defaultHeader.Value); // 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.AddParameter(param.Key, param.Value, ParameterType.GetOrPost); // add form parameter, if any foreach(var param in formParams) request.AddParameter(param.Key, param.Value, ParameterType.GetOrPost); // add file parameter, if any foreach(var param in fileParams) request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType); if (postBody != null) // http body (model) parameter request.AddParameter("application/json", postBody, ParameterType.RequestBody); return (Object)RestClient.Execute(request); } /// /// Add default header. /// /// Header field name. /// Header field value. /// public void AddDefaultHeader(string key, string value) { _defaultHeaderMap.Add(key, value); } /// /// Escape string (url-encoded). /// /// String to be escaped. /// Escaped string. public string EscapeString(string str) { return RestSharp.Contrib.HttpUtility.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, stream.ReadAsBytes(), Path.GetFileName(((FileStream)stream).Name)); else return FileParameter.Create(name, stream.ReadAsBytes(), "no_file_name_provided"); } /// /// If parameter is DateTime, output in ISO8601 format. /// If parameter is a list of string, 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 ((DateTime)obj).ToString ("u"); else if (obj is List) return String.Join(",", (obj as List).ToArray()); else return Convert.ToString (obj); } /// /// Deserialize the JSON string into a proper object. /// /// HTTP body (e.g. string, JSON). /// Object type. /// Object representation of the JSON string. public object Deserialize(string content, Type type, IList headers=null) { if (type == typeof(Object)) // return an object { return content; } if (type == typeof(Stream)) { var filePath = String.IsNullOrEmpty(Configuration.TempFolderPath) ? Path.GetTempPath() : Configuration.TempFolderPath; var fileName = filePath + Guid.NewGuid(); if (headers != null) { var regex = new Regex(@"Content-Disposition:.*filename=['""]?([^'""\s]+)['""]?$"); var match = regex.Match(headers.ToString()); if (match.Success) fileName = filePath + match.Value.Replace("\"", "").Replace("'", ""); } File.WriteAllText(fileName, content); return new FileStream(fileName, FileMode.Open); } if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object { return DateTime.Parse(content, null, System.Globalization.DateTimeStyles.RoundtripKind); } if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type { return ConvertType(content, type); } // at this point, it must be a model (json) try { return JsonConvert.DeserializeObject(content, type); } catch (IOException e) { throw new ApiException(500, e.Message); } } /// /// Serialize an object 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); } } /// /// Get the API key with prefix. /// /// API key identifier (authentication scheme). /// API key with prefix. public string GetApiKeyWithPrefix (string apiKeyIdentifier) { var apiKeyValue = ""; Configuration.ApiKey.TryGetValue (apiKeyIdentifier, out apiKeyValue); var apiKeyPrefix = ""; if (Configuration.ApiKeyPrefix.TryGetValue (apiKeyIdentifier, out apiKeyPrefix)) return apiKeyPrefix + " " + apiKeyValue; else return apiKeyValue; } /// /// Update parameters based on authentication. /// /// Query parameters. /// Header parameters. /// Authentication settings. public void UpdateParamsForAuth(Dictionary queryParams, Dictionary headerParams, string[] authSettings) { if (authSettings == null || authSettings.Length == 0) return; foreach (string auth in authSettings) { // determine which one to use switch(auth) { {{#authMethods}} case "{{name}}": {{#isApiKey}}{{#isKeyInHeader}}headerParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInHeader}}{{#isKeyInQuery}}queryParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}headerParams["Authorization"] = "Basic " + Base64Encode(Configuration.Username + ":" + Configuration.Password);{{/isBasic}} {{#isOAuth}}//TODO support oauth{{/isOAuth}} break; {{/authMethods}} default: //TODO show warning about security definition not found break; } } } /// /// Encode string in base64 format. /// /// String to be encoded. /// Encoded string. public static string Base64Encode(string text) { var textByte = System.Text.Encoding.UTF8.GetBytes(text); return System.Convert.ToBase64String(textByte); } /// /// Dynamically cast the object into target type. /// Ref: http://stackoverflow.com/questions/4925718/c-dynamic-runtime-cast /// /// Object to be casted /// Target type /// Casted object public static Object ConvertType(Object source, Type dest) { return Convert.ChangeType(source, dest); } } }