PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/WCFWebApi/src/Microsoft.ApplicationServer.Http/Microsoft/ApplicationServer/Http/HttpMemoryConfiguration.cs

#
C# | 310 lines | 204 code | 34 blank | 72 comment | 20 complexity | acaeb9888f6dfc8acc95dc83b4185ffd MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. // <copyright>
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // </copyright>
  4. namespace Microsoft.ApplicationServer.Http
  5. {
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.ComponentModel;
  10. using System.Diagnostics.CodeAnalysis;
  11. using System.Linq;
  12. using System.Net.Http;
  13. using System.Net.Http.Formatting;
  14. using System.ServiceModel;
  15. using System.ServiceModel.Description;
  16. using Microsoft.ApplicationServer.Http.Channels;
  17. using Microsoft.ApplicationServer.Http.Configuration;
  18. using Microsoft.ApplicationServer.Http.Description;
  19. using Microsoft.ApplicationServer.Http.Dispatcher;
  20. using Microsoft.Server.Common;
  21. /// <summary>
  22. /// The configuration class for Http Services with an <see cref="HttpMemoryEndpoint"/> for
  23. /// in-memory communication.
  24. /// </summary>
  25. public class HttpMemoryConfiguration
  26. {
  27. // TODO: CSDMain 238509: Introduce abstract HttpConfigurationBase class which is the union of HttpConfiguration and HttpMemoryConfiguration
  28. private static readonly Type httpMemoryConfigurationType = typeof(HttpMemoryConfiguration);
  29. private static readonly Type httpServiceHostType = typeof(HttpServiceHost);
  30. private bool isReadOnly;
  31. private HttpConfigurationInstanceProvider instanceProvider;
  32. private HttpConfigurationOperationHandlerFactory operationHandlerFactory;
  33. private HttpMessageHandlerFactory messageHandlerFactory;
  34. private Action<Collection<HttpErrorHandler>, ServiceEndpoint, IEnumerable<HttpOperationDescription>> errorHandlerAction;
  35. private TrailingSlashMode trailingSlashMode;
  36. private Func<IEnumerable<DelegatingHandler>> messageHandlerDelegate;
  37. private Collection<Type> messageHandlerTypes;
  38. /// <summary>
  39. /// Initializes a new instance of the <see cref="HttpMemoryConfiguration"/> class.
  40. /// </summary>
  41. public HttpMemoryConfiguration()
  42. {
  43. this.instanceProvider = new HttpConfigurationInstanceProvider();
  44. }
  45. /// <summary>
  46. /// Gets the media type formatters.
  47. /// </summary>
  48. public MediaTypeFormatterCollection Formatters
  49. {
  50. get
  51. {
  52. if (this.OperationHandlerFactory.Formatters == null)
  53. {
  54. this.OperationHandlerFactory.Formatters = new MediaTypeFormatterCollection();
  55. }
  56. return this.OperationHandlerFactory.Formatters;
  57. }
  58. }
  59. /// <summary>
  60. /// Gets or sets the trailing slash mode.
  61. /// </summary>
  62. /// <value>
  63. /// The trailing slash mode.
  64. /// </value>
  65. [DefaultValue(TrailingSlashMode.AutoRedirect)]
  66. public TrailingSlashMode TrailingSlashMode
  67. {
  68. get
  69. {
  70. return this.trailingSlashMode;
  71. }
  72. set
  73. {
  74. this.CheckReadOnly();
  75. TrailingSlashModeHelper.Validate(value, "value");
  76. this.trailingSlashMode = value;
  77. }
  78. }
  79. /// <summary>
  80. /// Gets or sets an action to configure request handlers.
  81. /// </summary>
  82. /// <value>
  83. /// The request handlers action.
  84. /// </value>
  85. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is required in order to provide a plug in model instead of having to define a new factory.")]
  86. public Action<Collection<HttpOperationHandler>, ServiceEndpoint, HttpOperationDescription> RequestHandlers
  87. {
  88. get
  89. {
  90. return this.OperationHandlerFactory.RequestHandlerDelegate;
  91. }
  92. set
  93. {
  94. this.CheckReadOnly();
  95. this.OperationHandlerFactory.RequestHandlerDelegate = value;
  96. }
  97. }
  98. /// <summary>
  99. /// Gets or sets an action to configure response handlers.
  100. /// </summary>
  101. /// <value>
  102. /// The response handlers action.
  103. /// </value>
  104. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is required in order to provide a plug in model instead of having to define a new factory.")]
  105. public Action<Collection<HttpOperationHandler>, ServiceEndpoint, HttpOperationDescription> ResponseHandlers
  106. {
  107. get
  108. {
  109. return this.OperationHandlerFactory.ResponseHandlerDelegate;
  110. }
  111. set
  112. {
  113. this.CheckReadOnly();
  114. this.OperationHandlerFactory.ResponseHandlerDelegate = value;
  115. }
  116. }
  117. /// <summary>
  118. /// Gets or sets a delegate to create service instance
  119. /// </summary>
  120. /// <value>
  121. /// The create service instance delegate.
  122. /// </value>
  123. public Func<Type, InstanceContext, HttpRequestMessage, object> CreateInstance
  124. {
  125. get
  126. {
  127. return this.instanceProvider.CreateInstanceDelegate;
  128. }
  129. set
  130. {
  131. this.CheckReadOnly();
  132. this.instanceProvider.CreateInstanceDelegate = value;
  133. }
  134. }
  135. /// <summary>
  136. /// Gets or sets a delegate to release service instance
  137. /// </summary>
  138. /// <value>
  139. /// The release service instance delegate.
  140. /// </value>
  141. public Action<InstanceContext, object> ReleaseInstance
  142. {
  143. get
  144. {
  145. return this.instanceProvider.ReleaseInstanceDelegate;
  146. }
  147. set
  148. {
  149. this.CheckReadOnly();
  150. this.instanceProvider.ReleaseInstanceDelegate = value;
  151. }
  152. }
  153. /// <summary>
  154. /// Gets or sets the delegate to create message handlers.
  155. /// </summary>
  156. /// <value>
  157. /// The message handler delegate.
  158. /// </value>
  159. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is required in order to provide a plug in model instead of having to define a new factory.")]
  160. public Func<IEnumerable<DelegatingHandler>> MessageHandlerFactory
  161. {
  162. get
  163. {
  164. return this.messageHandlerDelegate;
  165. }
  166. set
  167. {
  168. this.CheckReadOnly();
  169. this.messageHandlerDelegate = value;
  170. }
  171. }
  172. /// <summary>
  173. /// Gets the types of message handlers to be created.
  174. /// </summary>
  175. /// <value>
  176. /// The message handler types.
  177. /// </value>
  178. public Collection<Type> MessageHandlers
  179. {
  180. get
  181. {
  182. if (this.messageHandlerTypes == null)
  183. {
  184. this.messageHandlerTypes = new Collection<Type>();
  185. }
  186. return this.messageHandlerTypes;
  187. }
  188. }
  189. /// <summary>
  190. /// Gets or sets an action to configure http error handlers.
  191. /// </summary>
  192. /// <value>
  193. /// The error handlers action.
  194. /// </value>
  195. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is required in order to provide a plug in model instead of having to define a new factory.")]
  196. public Action<Collection<HttpErrorHandler>, ServiceEndpoint, IEnumerable<HttpOperationDescription>> ErrorHandlers
  197. {
  198. get
  199. {
  200. return this.errorHandlerAction;
  201. }
  202. set
  203. {
  204. this.CheckReadOnly();
  205. this.errorHandlerAction = value;
  206. }
  207. }
  208. private HttpConfigurationOperationHandlerFactory OperationHandlerFactory
  209. {
  210. get
  211. {
  212. if (this.operationHandlerFactory == null)
  213. {
  214. this.operationHandlerFactory = new HttpConfigurationOperationHandlerFactory();
  215. }
  216. return this.operationHandlerFactory;
  217. }
  218. }
  219. /// <summary>
  220. /// Internal method called to configure endpoint settings.
  221. /// </summary>
  222. /// <param name="endpoint">Http endpoint.</param>
  223. internal void ConfigureEndpoint(HttpMemoryEndpoint endpoint)
  224. {
  225. this.isReadOnly = true;
  226. this.OnConfigureEndpoint(endpoint);
  227. }
  228. /// <summary>
  229. /// Called to apply the configuration on the endpoint level.
  230. /// </summary>
  231. /// <param name="endpoint">Http endpoint.</param>
  232. protected virtual void OnConfigureEndpoint(HttpMemoryEndpoint endpoint)
  233. {
  234. if (endpoint == null)
  235. {
  236. throw Fx.Exception.ArgumentNull("endpoint");
  237. }
  238. if (this.ReleaseInstance != null && this.CreateInstance == null)
  239. {
  240. throw Fx.Exception.AsError(new InvalidOperationException(SR.CannotSetOnlyOneProperty("ReleaseInstance", "CreateInstance", httpMemoryConfigurationType.Name)));
  241. }
  242. // At this point the endpoint has the default HttpBehavior so we can get it in order to configure it.
  243. HttpBehavior httpBehavior = endpoint.HttpBehavior;
  244. // Configure the HttpBehavior
  245. httpBehavior.OperationHandlerFactory = this.operationHandlerFactory;
  246. httpBehavior.ErrorHandlerDelegate = this.errorHandlerAction;
  247. httpBehavior.InstanceProvider = this.instanceProvider.CreateInstanceDelegate != null ? this.instanceProvider : null;
  248. httpBehavior.TrailingSlashMode = this.TrailingSlashMode;
  249. if (this.MessageHandlerFactory != null && this.MessageHandlers.Count > 0)
  250. {
  251. throw Fx.Exception.AsError(new InvalidOperationException(SR.CannotSetBothProperties("MessageHandlerFactory", "MessageHandlers", httpMemoryConfigurationType.Name)));
  252. }
  253. if (this.MessageHandlerFactory != null)
  254. {
  255. this.messageHandlerFactory = new HttpMessageHandlerFactory(this.MessageHandlerFactory);
  256. }
  257. if (this.MessageHandlers.Count > 0)
  258. {
  259. this.messageHandlerFactory = new HttpMessageHandlerFactory(this.MessageHandlers.ToArray());
  260. }
  261. HttpMemoryBinding httpBinding = endpoint.HttpMemoryBinding;
  262. httpBinding.MessageHandlerFactory = this.messageHandlerFactory;
  263. }
  264. private void CheckReadOnly()
  265. {
  266. if (this.isReadOnly)
  267. {
  268. throw Fx.Exception.AsError(
  269. new InvalidOperationException(
  270. Microsoft.ApplicationServer.Http.SR.HttpConfigurationIsReadOnly(
  271. httpMemoryConfigurationType.Name,
  272. httpServiceHostType.Name)));
  273. }
  274. }
  275. }
  276. }