1
/* ****************************************************************************
3 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * This software is subject to the Microsoft Public License (Ms-PL).
6 * A copy of the license can be found in the license.htm file included
7 * in this distribution.
9 * You must not remove this notice, or any other, from this software.
11 * ***************************************************************************/
13 namespace System
.Web
.Mvc
{
15 using System
.Collections
;
16 using System
.Collections
.Generic
;
17 using System
.Globalization
;
20 using System
.Web
.Mvc
.Resources
;
21 using System
.Web
.Routing
;
23 public class DefaultControllerFactory
: IControllerFactory
{
25 private IBuildManager _buildManager
;
26 private ControllerBuilder _controllerBuilder
;
27 private ControllerTypeCache _instanceControllerTypeCache
;
28 private static ControllerTypeCache _staticControllerTypeCache
= new ControllerTypeCache();
30 internal IBuildManager BuildManager
{
32 if (_buildManager
== null) {
33 _buildManager
= new BuildManagerWrapper();
38 _buildManager
= value;
42 internal ControllerBuilder ControllerBuilder
{
44 return _controllerBuilder
?? ControllerBuilder
.Current
;
47 _controllerBuilder
= value;
51 internal ControllerTypeCache ControllerTypeCache
{
53 return _instanceControllerTypeCache
?? _staticControllerTypeCache
;
56 _instanceControllerTypeCache
= value;
60 public RequestContext RequestContext
{
65 public virtual IController
CreateController(RequestContext requestContext
, string controllerName
) {
66 if (requestContext
== null) {
67 throw new ArgumentNullException("requestContext");
69 if (String
.IsNullOrEmpty(controllerName
)) {
70 throw new ArgumentException(MvcResources
.Common_NullOrEmpty
, "controllerName");
72 RequestContext
= requestContext
;
73 Type controllerType
= GetControllerType(controllerName
);
74 IController controller
= GetControllerInstance(controllerType
);
78 protected internal virtual IController
GetControllerInstance(Type controllerType
) {
79 if (controllerType
== null) {
80 throw new HttpException(404,
82 CultureInfo
.CurrentUICulture
,
83 MvcResources
.DefaultControllerFactory_NoControllerFound
,
84 RequestContext
.HttpContext
.Request
.Path
));
86 if (!typeof(IController
).IsAssignableFrom(controllerType
)) {
87 throw new ArgumentException(
89 CultureInfo
.CurrentUICulture
,
90 MvcResources
.DefaultControllerFactory_TypeDoesNotSubclassControllerBase
,
95 return (IController
)Activator
.CreateInstance(controllerType
);
97 catch (Exception ex
) {
98 throw new InvalidOperationException(
100 CultureInfo
.CurrentUICulture
,
101 MvcResources
.DefaultControllerFactory_ErrorCreatingController
,
107 protected internal virtual Type
GetControllerType(string controllerName
) {
108 if (String
.IsNullOrEmpty(controllerName
)) {
109 throw new ArgumentException(MvcResources
.Common_NullOrEmpty
, "controllerName");
112 // first search in the current route's namespace collection
113 object routeNamespacesObj
;
115 if (RequestContext
!= null && RequestContext
.RouteData
.DataTokens
.TryGetValue("Namespaces", out routeNamespacesObj
)) {
116 IEnumerable
<string> routeNamespaces
= routeNamespacesObj
as IEnumerable
<string>;
117 if (routeNamespaces
!= null) {
118 HashSet
<string> nsHash
= new HashSet
<string>(routeNamespaces
, StringComparer
.OrdinalIgnoreCase
);
119 match
= GetControllerTypeWithinNamespaces(controllerName
, nsHash
);
126 // then search in the application's default namespace collection
127 HashSet
<string> nsDefaults
= new HashSet
<string>(ControllerBuilder
.DefaultNamespaces
, StringComparer
.OrdinalIgnoreCase
);
128 match
= GetControllerTypeWithinNamespaces(controllerName
, nsDefaults
);
133 // if all else fails, search every namespace
134 return GetControllerTypeWithinNamespaces(controllerName
, null /* namespaces */);
137 private Type
GetControllerTypeWithinNamespaces(string controllerName
, HashSet
<string> namespaces
) {
138 // Once the master list of controllers has been created we can quickly index into it
139 ControllerTypeCache
.EnsureInitialized(BuildManager
);
141 IList
<Type
> matchingTypes
= ControllerTypeCache
.GetControllerTypes(controllerName
, namespaces
);
142 switch (matchingTypes
.Count
) {
148 // single matching type
149 return matchingTypes
[0];
152 // multiple matching types
153 // we need to generate an exception containing all the controller types
154 StringBuilder sb
= new StringBuilder();
155 foreach (Type matchedType
in matchingTypes
) {
157 sb
.Append(matchedType
.FullName
);
159 throw new InvalidOperationException(
161 CultureInfo
.CurrentUICulture
,
162 MvcResources
.DefaultControllerFactory_ControllerNameAmbiguous
,
163 controllerName
, sb
));
167 public virtual void ReleaseController(IController controller
) {
168 IDisposable disposable
= controller
as IDisposable
;
169 if (disposable
!= null) {
170 disposable
.Dispose();