// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Concurrent; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Net.Http; using System.Net.Http.Formatting; using System.Web.Http.Dependencies; using System.Web.Http.Filters; using System.Web.Http.ModelBinding; using System.Web.Http.Services; namespace System.Web.Http { /// /// Configuration of instances. /// public class HttpConfiguration : IDisposable { private readonly HttpRouteCollection _routes; private readonly ConcurrentDictionary _properties = new ConcurrentDictionary(); private readonly MediaTypeFormatterCollection _formatters = DefaultFormatters(); private readonly Collection _messageHandlers = new Collection(); private readonly HttpFilterCollection _filters = new HttpFilterCollection(); private IDependencyResolver _dependencyResolver = EmptyResolver.Instance; private bool _disposed; /// /// Initializes a new instance of the class. /// [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The route collection is disposed as part of this class.")] public HttpConfiguration() : this(new HttpRouteCollection(String.Empty)) { } /// /// Initializes a new instance of the class. /// /// The to associate with this instance. public HttpConfiguration(HttpRouteCollection routes) { if (routes == null) { throw Error.ArgumentNull("routes"); } _routes = routes; Services = new DefaultServices(this); } /// /// Gets the list of filters that apply to all requests served using this HttpConfiguration instance. /// public HttpFilterCollection Filters { get { return _filters; } } /// /// Gets an ordered list of instances to be invoked as an /// travels up the stack and an travels down in /// stack in return. The handlers are invoked in a bottom-up fashion in the incoming path and top-down in the outgoing /// path. That is, the last entry is called first for an incoming request message but invoked last for an outgoing /// response message. /// /// /// The message handler collection. /// public Collection MessageHandlers { get { return _messageHandlers; } } /// /// Gets the associated with this instance. /// /// /// The . /// public HttpRouteCollection Routes { get { return _routes; } } /// /// Gets the properties associated with this instance. /// public ConcurrentDictionary Properties { get { return _properties; } } /// /// Gets the root virtual path. The property always returns /// "/" as the first character of the returned value. /// public string VirtualPathRoot { get { return _routes.VirtualPathRoot; } } /// /// Gets or sets the dependency resolver associated with this . /// public IDependencyResolver DependencyResolver { get { return _dependencyResolver; } set { if (value == null) { throw Error.PropertyNull(); } _dependencyResolver = value; } } /// /// Gets the container of default services associated with this . /// Only supports the list of service types documented on . For general /// purpose types, please use . /// public DefaultServices Services { get; internal set; } /// /// Gets or sets a value indicating whether error details should be included in error messages. /// public IncludeErrorDetailPolicy IncludeErrorDetailPolicy { get; set; } /// /// Gets the media type formatters. /// public MediaTypeFormatterCollection Formatters { get { return _formatters; } } private static MediaTypeFormatterCollection DefaultFormatters() { var formatters = new MediaTypeFormatterCollection(); // Basic FormUrlFormatter does not support binding to a T. // Use our JQuery formatter instead. formatters.Add(new JQueryMvcFormUrlEncodedFormatter()); return formatters; } internal bool ShouldIncludeErrorDetail(HttpRequestMessage request) { switch (IncludeErrorDetailPolicy) { case IncludeErrorDetailPolicy.LocalOnly: Uri requestUri = request.RequestUri; return requestUri.IsAbsoluteUri && requestUri.IsLoopback; case IncludeErrorDetailPolicy.Always: return true; case IncludeErrorDetailPolicy.Never: default: return false; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_disposed) { _disposed = true; if (disposing) { _routes.Dispose(); Services.Dispose(); DependencyResolver.Dispose(); } } } } }