PageRenderTime 31ms CodeModel.GetById 14ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 1ms

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