PageRenderTime 5707ms CodeModel.GetById 26ms RepoModel.GetById 8ms app.codeStats 0ms

/ChargifyDotNET/Source/Chargify.NET/ChargifyException.cs

#
C# | 276 lines | 158 code | 20 blank | 98 comment | 11 complexity | f4e58665b2ac2ee0909ce760906dabab MD5 | raw file
  1. #region License, Terms and Conditions
  2. //
  3. // ChargifyException.cs
  4. //
  5. // Authors: Kori Francis <twitter.com/djbyter>, David Ball
  6. // Copyright (C) 2010 Clinical Support Systems, Inc. All rights reserved.
  7. //
  8. // THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining a
  11. // copy of this software and associated documentation files (the "Software"),
  12. // to deal in the Software without restriction, including without limitation
  13. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14. // and/or sell copies of the Software, and to permit persons to whom the
  15. // Software is furnished to do so, subject to the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be included in
  18. // all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26. // DEALINGS IN THE SOFTWARE.
  27. //
  28. #endregion
  29. namespace ChargifyNET
  30. {
  31. #region Imports
  32. using System;
  33. using System.Net;
  34. using System.Diagnostics;
  35. using System.Runtime.Serialization;
  36. using System.Security.Permissions;
  37. using System.Xml;
  38. using System.Collections.Generic;
  39. using System.IO;
  40. using ChargifyNET.Json;
  41. using System.Xml.Linq;
  42. using System.Linq;
  43. #endregion
  44. /// <summary>
  45. /// Error returned from Chargify after an unsuccessful operation
  46. /// </summary>
  47. [Serializable]
  48. public class ChargifyError
  49. {
  50. /// <summary>
  51. /// The message from Chargify
  52. /// </summary>
  53. public string Message { get; private set; }
  54. #region Constructors
  55. /// <summary>
  56. /// Constructor
  57. /// </summary>
  58. internal ChargifyError() { }
  59. /// <summary>
  60. /// Constructor
  61. /// </summary>
  62. /// <param name="message">The string error message to relay to the user</param>
  63. internal ChargifyError(string message)
  64. {
  65. this.Message = message;
  66. }
  67. /// <summary>
  68. /// Constructor
  69. /// </summary>
  70. /// <param name="errorNode">The XML node that contains the error message</param>
  71. internal ChargifyError(XmlNode errorNode)
  72. {
  73. this.Message = errorNode.Value;
  74. }
  75. /// <summary>
  76. /// Constructor
  77. /// </summary>
  78. /// <param name="errorStr">The JsonString obj that contains the error message</param>
  79. internal ChargifyError(JsonString errorStr)
  80. {
  81. this.Message = errorStr.Value;
  82. }
  83. #endregion
  84. /// <summary>
  85. /// Method to parse the errors returned from Chargify after an unsuccessful interaction
  86. /// </summary>
  87. /// <param name="response">The HttpWebResponse instance which contains the error response</param>
  88. /// <returns>The list of errors returned from Chargify</returns>
  89. internal static List<ChargifyError> ParseChargifyErrors(HttpWebResponse response)
  90. {
  91. if (response != null)
  92. {
  93. using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  94. {
  95. string errorResponse = reader.ReadToEnd();
  96. List<ChargifyError> errors = new List<ChargifyError>();
  97. // Response is frequently " " ...
  98. if (string.IsNullOrEmpty(errorResponse.Trim())) return errors;
  99. if (errorResponse.IsXml())
  100. {
  101. // New way - Linq-y
  102. XDocument xdoc = XDocument.Parse(errorResponse);
  103. var results = from e in xdoc.Descendants("errors")
  104. select new ChargifyError
  105. {
  106. Message = e.Value
  107. };
  108. errors = results.ToList();
  109. }
  110. else if (errorResponse.IsJSON())
  111. {
  112. // slightly different json response from the usual
  113. int position = 0;
  114. JsonObject obj = JsonObject.Parse(errorResponse, ref position);
  115. if (obj.ContainsKey("errors"))
  116. {
  117. JsonArray array = obj["errors"] as JsonArray;
  118. for (int i = 0; i <= array.Length - 1; i++)
  119. {
  120. if (((array.Items[i] as JsonString) != null)&&(!string.IsNullOrEmpty((array.Items[i] as JsonString).Value)))
  121. {
  122. JsonString errorStr = array.Items[i] as JsonString;
  123. ChargifyError anError = new ChargifyError(errorStr);
  124. if (!errors.Contains(anError))
  125. {
  126. errors.Add(anError);
  127. }
  128. }
  129. }
  130. }
  131. }
  132. return errors;
  133. }
  134. }
  135. else
  136. {
  137. throw new ChargifyNetException("Unknown Error");
  138. }
  139. }
  140. }
  141. /// <summary>
  142. /// Exception thrown by Chargify.NET library when things don't add up
  143. /// </summary>
  144. [Serializable]
  145. public class ChargifyNetException : Exception
  146. {
  147. /// <summary>
  148. /// Constructor
  149. /// </summary>
  150. /// <param name="message">The message of this exception</param>
  151. public ChargifyNetException(string message) : base(message)
  152. {
  153. }
  154. }
  155. /// <summary>
  156. /// Exception thrown by the chargify system when a request fails
  157. /// </summary>
  158. [DebuggerDisplay("Status Description: {StatusDescription}, Status Code: {StatusCode}, Error Messages: {ErrorMessages.Count}")]
  159. [Serializable]
  160. public class ChargifyException : Exception
  161. {
  162. /// <summary>
  163. /// Constructor
  164. /// </summary>
  165. /// <param name="errorResponse">The response that caused the exception</param>
  166. /// <param name="wex">The original web exception. This becomes the inner exception of ths exception</param>
  167. public ChargifyException(HttpWebResponse errorResponse, WebException wex) :
  168. base(string.Format("The server returned '{0}' with the status code {1} ({1:d}).", errorResponse.StatusDescription, errorResponse.StatusCode), wex)
  169. {
  170. _statusDescription = errorResponse.StatusDescription;
  171. _statusCode = errorResponse.StatusCode;
  172. // if there are any errors, parse them for user consumption
  173. _errors = ChargifyError.ParseChargifyErrors(errorResponse);
  174. }
  175. /// <summary>
  176. /// Constructor
  177. /// </summary>
  178. /// <param name="errorResponse">The response that caused the exception</param>
  179. /// <param name="wex">The original web exception. This becomes the inner exception of ths exception</param>
  180. /// <param name="postData">The data posted that could have potentially caused the exception.</param>
  181. public ChargifyException(HttpWebResponse errorResponse, WebException wex, string postData) :
  182. base(string.Format("The server returned '{0}' with the status code {1} ({1:d}) when posting '{2}'.", errorResponse.StatusDescription, errorResponse.StatusCode, postData), wex)
  183. {
  184. _statusDescription = errorResponse.StatusDescription;
  185. _statusCode = errorResponse.StatusCode;
  186. _postData = postData;
  187. // if there are any errors, parse them for user consumption
  188. _errors = ChargifyError.ParseChargifyErrors(errorResponse);
  189. }
  190. /// <summary>
  191. /// Get the status description
  192. /// </summary>
  193. public string StatusDescription
  194. {
  195. get
  196. {
  197. return _statusDescription;
  198. }
  199. }
  200. private string _statusDescription = "";
  201. /// <summary>
  202. /// Get the status code
  203. /// </summary>
  204. public HttpStatusCode StatusCode
  205. {
  206. get
  207. {
  208. return _statusCode;
  209. }
  210. }
  211. private HttpStatusCode _statusCode = HttpStatusCode.Accepted;
  212. /// <summary>
  213. /// Get the last data posted that potentially caused the exception
  214. /// </summary>
  215. public string LastDataPosted
  216. {
  217. get
  218. {
  219. return _postData;
  220. }
  221. }
  222. private string _postData = string.Empty;
  223. /// <summary>
  224. /// List of ChargifyErrors returned from Chargify.
  225. /// </summary>
  226. public List<ChargifyError> ErrorMessages
  227. {
  228. get
  229. {
  230. return _errors;
  231. }
  232. }
  233. private List<ChargifyError> _errors = null;
  234. /// <summary>
  235. /// Get object data
  236. /// </summary>
  237. [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
  238. public override void GetObjectData(SerializationInfo info, StreamingContext context)
  239. {
  240. base.GetObjectData(info, context);
  241. }
  242. /// <summary>
  243. /// Pretty output for this exception
  244. /// </summary>
  245. /// <returns>Request, response and errors</returns>
  246. public override string ToString()
  247. {
  248. // Used for the LogResponse Action
  249. string retVal = string.Empty;
  250. retVal += string.Format("Request: {0}\n", LastDataPosted);
  251. retVal += string.Format("Response: {0} {1}\n", StatusCode.ToString(), StatusDescription.ToString());
  252. retVal += string.Format("Errors: {0}\n", string.Join(", ", _errors.ToList().Select(e => e.Message).ToArray()));
  253. return retVal;
  254. }
  255. }
  256. }