public HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            Throw.IfArgumentNull(request, "request");

            // reset version for each request
            this.Version = null;

            // set a default version if not already set
            //if (string.IsNullOrEmpty(this.DefaultVersion))
            //{
            //    // extract 'area' route value if requested
            //    string area = string.Empty;
            //    var routeData = request.GetRouteData();
            //    if (routeData != null && routeData.Values.ContainsKey("area") && routeData.Values["area"] != null)
            //        area = routeData.Values["area"].ToString();
            //    this.DefaultVersion = this.GetVersions(area).Count() > 0 ? this.GetVersions(area).First() : null;
            //}

            ControllerIdentification controllerName = this.GetControllerIdentificationFromRequest(request);

            if (String.IsNullOrEmpty(controllerName.Name))
            {
                Throw.HttpResponse(request.CreateErrorResponse(HttpStatusCode.NotFound,
                                                               string.Format(ExceptionStrings.ResourceNotFound, request.RequestUri),
                                                               string.Format(ExceptionStrings.ControllerNameNotFound, request.RequestUri)));
            }

            HttpControllerDescriptor controllerDescriptor;

            if (this._controllerInfoCache.Value.TryGetValue(controllerName, out controllerDescriptor))
            {
                return(controllerDescriptor);
            }

            ICollection <Type> matchingTypes = this._controllerTypeCache.GetControllerTypes(controllerName);

            // ControllerInfoCache is already initialized.
            Contract.Assert(matchingTypes.Count != 1);

            if (matchingTypes.Count == 0)
            {
                // no matching types
                Throw.HttpResponse(request.CreateErrorResponse(HttpStatusCode.NotFound,
                                                               string.Format(ExceptionStrings.ResourceNotFound, request.RequestUri),
                                                               string.Format(ExceptionStrings.DefaultControllerFactory_ControllerNameNotFound,
                                                                             controllerName.Name)));
            }
            else
            {
                // multiple matching types
                Throw.Generic(CreateAmbiguousControllerException(request.GetRouteData().Route, controllerName.Name, matchingTypes));
            }

            // Throw.HttpResponse does not return a value so we have to return null here
            return(null);
        }
        /// <summary>
        /// Gets all controller types within the system matching the specified controller identification.
        /// </summary>
        /// <param name="controllerName">Name of the controller.</param>
        /// <returns>
        /// Returns an <see cref="T:System.Collections.Generic.ICollection`1" /> of controller types.
        /// </returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// controllername
        /// or
        /// <see cref="P:Geocrest.Web.Mvc.Controllers.ControllerIdentification.Name"/> is null or empty
        /// </exception>
        public ICollection <Type> GetControllerTypes(ControllerIdentification controllerName)
        {
            Throw.IfArgumentNull(controllerName, "controllerName");
            Throw.IfArgumentNullOrEmpty(controllerName.Name, "controllerName");

            var matchingTypes = new HashSet <Type>();

            ILookup <string, Type> namespaceLookup;

            if (this._cache.Value.TryGetValue(controllerName, out namespaceLookup))
            {
                foreach (var namespaceGroup in namespaceLookup)
                {
                    matchingTypes.UnionWith(namespaceGroup);
                }
            }

            return(matchingTypes);
        }
        private ConcurrentDictionary <ControllerIdentification, HttpControllerDescriptor> InitializeControllerInfoCache()
        {
            // lock dependend properties
            _VersionPrefix.Lock();

            // let's find and cache the found controllers
            var result = new ConcurrentDictionary <ControllerIdentification, HttpControllerDescriptor>(ControllerIdentification.Comparer);
            var duplicateControllers = new HashSet <ControllerIdentification>();
            Dictionary <ControllerIdentification, ILookup <string, Type> > controllerTypeGroups = this._controllerTypeCache.Cache;

            foreach (KeyValuePair <ControllerIdentification, ILookup <string, Type> > controllerTypeGroup in controllerTypeGroups)
            {
                ControllerIdentification controllerName = controllerTypeGroup.Key;
                foreach (IGrouping <string, Type> controllerTypesGroupedByNs in controllerTypeGroup.Value)
                {
                    foreach (Type controllerType in controllerTypesGroupedByNs)
                    {
                        if (result.Keys.Contains(controllerName))
                        {
                            duplicateControllers.Add(controllerName);
                            break;
                        }
                        else
                        {
                            result.TryAdd(controllerName, new HttpControllerDescriptor(this._configuration,
                                                                                       controllerName.Name, controllerType));
                        }
                    }
                }
            }
            foreach (ControllerIdentification duplicateController in duplicateControllers)
            {
                HttpControllerDescriptor descriptor;
                result.TryRemove(duplicateController, out descriptor);
            }
            return(result);
        }