Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

HelpPageConfigurationExtensions.cs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Diagnostics.CodeAnalysis;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Net.Http.Headers;
  8. using System.Web.Http;
  9. using System.Web.Http.Description;
  10. using WebAPiUtils_test.Areas.HelpPage.Models;
  11. namespace WebAPiUtils_test.Areas.HelpPage
  12. {
  13. public static class HelpPageConfigurationExtensions
  14. {
  15. private const string ApiModelPrefix = "MS_HelpPageApiModel_";
  16. /// <summary>
  17. /// Sets the documentation provider for help page.
  18. /// </summary>
  19. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  20. /// <param name="documentationProvider">The documentation provider.</param>
  21. public static void SetDocumentationProvider(this HttpConfiguration config, IDocumentationProvider documentationProvider)
  22. {
  23. config.Services.Replace(typeof(IDocumentationProvider), documentationProvider);
  24. }
  25. /// <summary>
  26. /// Sets the objects that will be used by the formatters to produce sample requests/responses.
  27. /// </summary>
  28. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  29. /// <param name="sampleObjects">The sample objects.</param>
  30. public static void SetSampleObjects(this HttpConfiguration config, IDictionary<Type, object> sampleObjects)
  31. {
  32. config.GetHelpPageSampleGenerator().SampleObjects = sampleObjects;
  33. }
  34. /// <summary>
  35. /// Sets the sample request directly for the specified media type and action.
  36. /// </summary>
  37. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  38. /// <param name="sample">The sample request.</param>
  39. /// <param name="mediaType">The media type.</param>
  40. /// <param name="controllerName">Name of the controller.</param>
  41. /// <param name="actionName">Name of the action.</param>
  42. public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
  43. {
  44. config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, new[] { "*" }), sample);
  45. }
  46. /// <summary>
  47. /// Sets the sample request directly for the specified media type and action with parameters.
  48. /// </summary>
  49. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  50. /// <param name="sample">The sample request.</param>
  51. /// <param name="mediaType">The media type.</param>
  52. /// <param name="controllerName">Name of the controller.</param>
  53. /// <param name="actionName">Name of the action.</param>
  54. /// <param name="parameterNames">The parameter names.</param>
  55. public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
  56. {
  57. config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, parameterNames), sample);
  58. }
  59. /// <summary>
  60. /// Sets the sample request directly for the specified media type of the action.
  61. /// </summary>
  62. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  63. /// <param name="sample">The sample response.</param>
  64. /// <param name="mediaType">The media type.</param>
  65. /// <param name="controllerName">Name of the controller.</param>
  66. /// <param name="actionName">Name of the action.</param>
  67. public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
  68. {
  69. config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, new[] { "*" }), sample);
  70. }
  71. /// <summary>
  72. /// Sets the sample response directly for the specified media type of the action with specific parameters.
  73. /// </summary>
  74. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  75. /// <param name="sample">The sample response.</param>
  76. /// <param name="mediaType">The media type.</param>
  77. /// <param name="controllerName">Name of the controller.</param>
  78. /// <param name="actionName">Name of the action.</param>
  79. /// <param name="parameterNames">The parameter names.</param>
  80. public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
  81. {
  82. config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, parameterNames), sample);
  83. }
  84. /// <summary>
  85. /// Sets the sample directly for all actions with the specified type and media type.
  86. /// </summary>
  87. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  88. /// <param name="sample">The sample.</param>
  89. /// <param name="mediaType">The media type.</param>
  90. /// <param name="type">The parameter type or return type of an action.</param>
  91. public static void SetSampleForType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, Type type)
  92. {
  93. config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, type), sample);
  94. }
  95. /// <summary>
  96. /// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
  97. /// The help page will use this information to produce more accurate request samples.
  98. /// </summary>
  99. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  100. /// <param name="type">The type.</param>
  101. /// <param name="controllerName">Name of the controller.</param>
  102. /// <param name="actionName">Name of the action.</param>
  103. public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName)
  104. {
  105. config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, new[] { "*" }), type);
  106. }
  107. /// <summary>
  108. /// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
  109. /// The help page will use this information to produce more accurate request samples.
  110. /// </summary>
  111. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  112. /// <param name="type">The type.</param>
  113. /// <param name="controllerName">Name of the controller.</param>
  114. /// <param name="actionName">Name of the action.</param>
  115. /// <param name="parameterNames">The parameter names.</param>
  116. public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
  117. {
  118. config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, parameterNames), type);
  119. }
  120. /// <summary>
  121. /// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> returned as part of the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
  122. /// The help page will use this information to produce more accurate response samples.
  123. /// </summary>
  124. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  125. /// <param name="type">The type.</param>
  126. /// <param name="controllerName">Name of the controller.</param>
  127. /// <param name="actionName">Name of the action.</param>
  128. public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName)
  129. {
  130. config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, new[] { "*" }), type);
  131. }
  132. /// <summary>
  133. /// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> returned as part of the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
  134. /// The help page will use this information to produce more accurate response samples.
  135. /// </summary>
  136. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  137. /// <param name="type">The type.</param>
  138. /// <param name="controllerName">Name of the controller.</param>
  139. /// <param name="actionName">Name of the action.</param>
  140. /// <param name="parameterNames">The parameter names.</param>
  141. public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
  142. {
  143. config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, parameterNames), type);
  144. }
  145. /// <summary>
  146. /// Gets the help page sample generator.
  147. /// </summary>
  148. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  149. /// <returns>The help page sample generator.</returns>
  150. public static HelpPageSampleGenerator GetHelpPageSampleGenerator(this HttpConfiguration config)
  151. {
  152. return (HelpPageSampleGenerator)config.Properties.GetOrAdd(
  153. typeof(HelpPageSampleGenerator),
  154. k => new HelpPageSampleGenerator());
  155. }
  156. /// <summary>
  157. /// Sets the help page sample generator.
  158. /// </summary>
  159. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  160. /// <param name="sampleGenerator">The help page sample generator.</param>
  161. public static void SetHelpPageSampleGenerator(this HttpConfiguration config, HelpPageSampleGenerator sampleGenerator)
  162. {
  163. config.Properties.AddOrUpdate(
  164. typeof(HelpPageSampleGenerator),
  165. k => sampleGenerator,
  166. (k, o) => sampleGenerator);
  167. }
  168. /// <summary>
  169. /// Gets the model that represents an API displayed on the help page. The model is initialized on the first call and cached for subsequent calls.
  170. /// </summary>
  171. /// <param name="config">The <see cref="HttpConfiguration"/>.</param>
  172. /// <param name="apiDescriptionId">The <see cref="ApiDescription"/> ID.</param>
  173. /// <returns>
  174. /// An <see cref="HelpPageApiModel"/>
  175. /// </returns>
  176. public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
  177. {
  178. object model;
  179. string modelId = ApiModelPrefix + apiDescriptionId;
  180. if (!config.Properties.TryGetValue(modelId, out model))
  181. {
  182. Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
  183. ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
  184. if (apiDescription != null)
  185. {
  186. HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
  187. model = GenerateApiModel(apiDescription, sampleGenerator);
  188. config.Properties.TryAdd(modelId, model);
  189. }
  190. }
  191. return (HelpPageApiModel)model;
  192. }
  193. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as ErrorMessages.")]
  194. private static HelpPageApiModel GenerateApiModel(ApiDescription apiDescription, HelpPageSampleGenerator sampleGenerator)
  195. {
  196. HelpPageApiModel apiModel = new HelpPageApiModel();
  197. apiModel.ApiDescription = apiDescription;
  198. try
  199. {
  200. foreach (var item in sampleGenerator.GetSampleRequests(apiDescription))
  201. {
  202. apiModel.SampleRequests.Add(item.Key, item.Value);
  203. LogInvalidSampleAsError(apiModel, item.Value);
  204. }
  205. foreach (var item in sampleGenerator.GetSampleResponses(apiDescription))
  206. {
  207. apiModel.SampleResponses.Add(item.Key, item.Value);
  208. LogInvalidSampleAsError(apiModel, item.Value);
  209. }
  210. }
  211. catch (Exception e)
  212. {
  213. apiModel.ErrorMessages.Add(String.Format(CultureInfo.CurrentCulture, "An exception has occurred while generating the sample. Exception Message: {0}", e.Message));
  214. }
  215. return apiModel;
  216. }
  217. private static void LogInvalidSampleAsError(HelpPageApiModel apiModel, object sample)
  218. {
  219. InvalidSample invalidSample = sample as InvalidSample;
  220. if (invalidSample != null)
  221. {
  222. apiModel.ErrorMessages.Add(invalidSample.ErrorMessage);
  223. }
  224. }
  225. }
  226. }