PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/sipsorcery-core/SIPSorcery.CRM/ThirtySevenSignals/HighriseRequest.cs

https://github.com/thecc4re/sipsorcery-mono
C# | 190 lines | 120 code | 23 blank | 47 comment | 8 complexity | faf100f8955540b28108a9a4023335c1 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // ============================================================================
  2. // FileName: HighriseRequest.cs
  3. //
  4. // Description:
  5. // Base class to send requests to 37 Signals contact management system Highrise.
  6. //
  7. // Author(s):
  8. // Aaron Clauson
  9. //
  10. // History:
  11. // 13 Feb 2011 Aaron Clauson Created.
  12. //
  13. // License:
  14. // This software is licensed under the BSD License http://www.opensource.org/licenses/bsd-license.php
  15. //
  16. // Copyright (c) 2011 Aaron Clauson (aaron@sipsorcery.com), SIP Sorcery Pty Ltd
  17. // All rights reserved.
  18. //
  19. // Redistribution and use in source and binary forms, with or without modification, are permitted provided that
  20. // the following conditions are met:
  21. //
  22. // Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  23. // Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  24. // disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of SIP Sorcery Ltd.
  25. // nor the names of its contributors may be used to endorse or promote products derived from this software without specific
  26. // prior written permission.
  27. //
  28. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
  29. // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  30. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  31. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  32. // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  33. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. // POSSIBILITY OF SUCH DAMAGE.
  35. // ============================================================================
  36. using System;
  37. using System.Collections.Generic;
  38. using System.IO;
  39. using System.Linq;
  40. using System.Net;
  41. using System.Text;
  42. using System.Text.RegularExpressions;
  43. using System.Xml;
  44. using System.Xml.Serialization;
  45. using SIPSorcery.Sys;
  46. namespace SIPSorcery.CRM.ThirtySevenSignals
  47. {
  48. /// <summary>
  49. /// This class submits HTTP requests to the 37 Signals Highrise API.
  50. /// </summary>
  51. /// <typeparam name="S">The singular object type for retrieving single items, e.g. Person or Company.</typeparam>
  52. /// <typeparam name="T">The plural object type for retrieving lists of items, e.g. People or Companies.</typeparam>
  53. public class HighriseRequest<S, T>
  54. {
  55. private const int MAX_HTTP_REQUEST_TIMEOUT = 10;
  56. private string m_urlNoun;
  57. private string m_authToken;
  58. protected string BaseUrl { get; private set; }
  59. public HighriseRequest(string baseUrl, string urlNoun, string authToken)
  60. {
  61. BaseUrl = baseUrl;
  62. m_urlNoun = urlNoun;
  63. m_authToken = authToken;
  64. }
  65. public S GetByID(int id)
  66. {
  67. string requestURL = BaseUrl + "/" + m_urlNoun + "/" + id + ".xml";
  68. return GetItem(requestURL);
  69. }
  70. public T GetByPhoneNumber(string phoneNumber)
  71. {
  72. string requestURL = BaseUrl + "/" + m_urlNoun + "/search.xml?" + Uri.EscapeDataString("criteria[phone]=" + phoneNumber);
  73. return GetList(requestURL);
  74. }
  75. public T GetByName(string name)
  76. {
  77. string requestURL = BaseUrl + "/" + m_urlNoun + "/search.xml?" + Uri.EscapeDataString("term=" + name);
  78. return GetList(requestURL);
  79. }
  80. protected virtual S GetItem(string url)
  81. {
  82. string response = GetResponse(url);
  83. if (!response.IsNullOrBlank())
  84. {
  85. S item = default(S);
  86. using (TextReader xmlReader = new StringReader(response))
  87. {
  88. XmlSerializer serializer = new XmlSerializer(typeof(S));
  89. item = (S)serializer.Deserialize(xmlReader);
  90. }
  91. return item;
  92. }
  93. else
  94. {
  95. return default(S);
  96. }
  97. }
  98. protected virtual T GetList(string url)
  99. {
  100. string response = GetResponse(url);
  101. if (!response.IsNullOrBlank())
  102. {
  103. T list = default(T);
  104. using (TextReader xmlReader = new StringReader(response))
  105. {
  106. XmlSerializer serializer = new XmlSerializer(typeof(T));
  107. list = (T)serializer.Deserialize(xmlReader);
  108. }
  109. return list;
  110. }
  111. else
  112. {
  113. return default(T);
  114. }
  115. }
  116. private string GetResponse(string url)
  117. {
  118. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  119. request.AllowAutoRedirect = true;
  120. request.Timeout = MAX_HTTP_REQUEST_TIMEOUT * 1000;
  121. request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(m_authToken)));
  122. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  123. if (response.StatusCode != HttpStatusCode.OK)
  124. {
  125. response.Close();
  126. throw new ApplicationException("37 Signals Highrise request to " + url + " failed with response " + response.StatusCode + ".");
  127. }
  128. StreamReader reader = new StreamReader(response.GetResponseStream());
  129. string responseStr = reader.ReadToEnd();
  130. response.Close();
  131. if (responseStr != null)
  132. {
  133. return Regex.Replace(responseStr, "nil=\"true\"", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\"");
  134. }
  135. else
  136. {
  137. return null;
  138. }
  139. }
  140. /// <summary>
  141. /// Attempts to create a new Highrise item.
  142. /// </summary>
  143. /// <param name="createUrl">The URL to send the creation request to. The URL can determine where the object gets created.
  144. /// For example to create a new note on a person the URL would be /people/#{person-id}/notes.xml.</param>
  145. /// <param name="itemXML">The XML that contains the information to create the new Highrise item.</param>
  146. /// <returns>If sucessful the reponse HTTP Location header which indicates the URL for the newly created item.</returns>
  147. protected string CreateItem(string createUrl, string itemXML)
  148. {
  149. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(createUrl);
  150. request.Method = "POST";
  151. request.AllowAutoRedirect = true;
  152. request.Timeout = MAX_HTTP_REQUEST_TIMEOUT * 1000;
  153. request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(m_authToken)));
  154. request.ContentType = "application/xml";
  155. Stream requestStream = request.GetRequestStream();
  156. byte[] requestBytes = Encoding.UTF8.GetBytes(itemXML);
  157. requestStream.Write(requestBytes, 0, requestBytes.Length);
  158. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  159. if (response.StatusCode != HttpStatusCode.Created)
  160. {
  161. response.Close();
  162. throw new ApplicationException("37 Signals Highrise create request to " + createUrl + " failed with response " + response.StatusCode + ".");
  163. }
  164. return response.Headers["Location"];
  165. }
  166. }
  167. }