PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/SystemWebMvc/Mvc/DefaultControllerFactory.cs

https://bitbucket.org/markhneedham/aspnet-mvc
C# | 164 lines | 139 code | 17 blank | 8 comment | 21 complexity | 1699f2d73a1ffedf5aa184154a916e38 MD5 | raw file
  1. namespace System.Web.Mvc {
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using System.Text;
  7. using System.Web;
  8. using System.Web.Mvc.Resources;
  9. using System.Web.Routing;
  10. [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  11. [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  12. public class DefaultControllerFactory : IControllerFactory {
  13. private IBuildManager _buildManager;
  14. private ControllerBuilder _controllerBuilder;
  15. private ControllerTypeCache _instanceControllerTypeCache;
  16. private static ControllerTypeCache _staticControllerTypeCache = new ControllerTypeCache();
  17. internal IBuildManager BuildManager {
  18. get {
  19. if (_buildManager == null) {
  20. _buildManager = new BuildManagerWrapper();
  21. }
  22. return _buildManager;
  23. }
  24. set {
  25. _buildManager = value;
  26. }
  27. }
  28. internal ControllerBuilder ControllerBuilder {
  29. get {
  30. return _controllerBuilder ?? ControllerBuilder.Current;
  31. }
  32. set {
  33. _controllerBuilder = value;
  34. }
  35. }
  36. internal ControllerTypeCache ControllerTypeCache {
  37. get {
  38. return _instanceControllerTypeCache ?? _staticControllerTypeCache;
  39. }
  40. set {
  41. _instanceControllerTypeCache = value;
  42. }
  43. }
  44. public RequestContext RequestContext {
  45. get;
  46. set;
  47. }
  48. public virtual IController CreateController(RequestContext requestContext, string controllerName) {
  49. if (requestContext == null) {
  50. throw new ArgumentNullException("requestContext");
  51. }
  52. if (String.IsNullOrEmpty(controllerName)) {
  53. throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
  54. }
  55. RequestContext = requestContext;
  56. Type controllerType = GetControllerType(controllerName);
  57. IController controller = GetControllerInstance(controllerType);
  58. return controller;
  59. }
  60. protected internal virtual IController GetControllerInstance(Type controllerType) {
  61. if (controllerType == null) {
  62. throw new HttpException(404,
  63. String.Format(
  64. CultureInfo.CurrentUICulture,
  65. MvcResources.DefaultControllerFactory_NoControllerFound,
  66. RequestContext.HttpContext.Request.Path));
  67. }
  68. if (!typeof(IController).IsAssignableFrom(controllerType)) {
  69. throw new ArgumentException(
  70. String.Format(
  71. CultureInfo.CurrentUICulture,
  72. MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,
  73. controllerType),
  74. "controllerType");
  75. }
  76. try {
  77. return (IController)Activator.CreateInstance(controllerType);
  78. }
  79. catch (Exception ex) {
  80. throw new InvalidOperationException(
  81. String.Format(
  82. CultureInfo.CurrentUICulture,
  83. MvcResources.DefaultControllerFactory_ErrorCreatingController,
  84. controllerType),
  85. ex);
  86. }
  87. }
  88. protected internal virtual Type GetControllerType(string controllerName) {
  89. if (String.IsNullOrEmpty(controllerName)) {
  90. throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
  91. }
  92. // first search in the current route's namespace collection
  93. object routeNamespacesObj;
  94. Type match;
  95. if (RequestContext != null && RequestContext.RouteData.DataTokens.TryGetValue("Namespaces", out routeNamespacesObj)) {
  96. IEnumerable<string> routeNamespaces = routeNamespacesObj as IEnumerable<string>;
  97. if (routeNamespaces != null) {
  98. HashSet<string> nsHash = new HashSet<string>(routeNamespaces, StringComparer.OrdinalIgnoreCase);
  99. match = GetControllerTypeWithinNamespaces(controllerName, nsHash);
  100. if (match != null) {
  101. return match;
  102. }
  103. }
  104. }
  105. // then search in the application's default namespace collection
  106. HashSet<string> nsDefaults = new HashSet<string>(ControllerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase);
  107. match = GetControllerTypeWithinNamespaces(controllerName, nsDefaults);
  108. if (match != null) {
  109. return match;
  110. }
  111. // if all else fails, search every namespace
  112. return GetControllerTypeWithinNamespaces(controllerName, null /* namespaces */);
  113. }
  114. private Type GetControllerTypeWithinNamespaces(string controllerName, HashSet<string> namespaces) {
  115. // Once the master list of controllers has been created we can quickly index into it
  116. ControllerTypeCache.EnsureInitialized(BuildManager);
  117. IList<Type> matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces);
  118. switch (matchingTypes.Count) {
  119. case 0:
  120. // no matching types
  121. return null;
  122. case 1:
  123. // single matching type
  124. return matchingTypes[0];
  125. default:
  126. // multiple matching types
  127. // we need to generate an exception containing all the controller types
  128. StringBuilder sb = new StringBuilder();
  129. foreach (Type matchedType in matchingTypes) {
  130. sb.AppendLine();
  131. sb.Append(matchedType.FullName);
  132. }
  133. throw new InvalidOperationException(
  134. String.Format(
  135. CultureInfo.CurrentUICulture,
  136. MvcResources.DefaultControllerFactory_ControllerNameAmbiguous,
  137. controllerName, sb));
  138. }
  139. }
  140. public virtual void ReleaseController(IController controller) {
  141. IDisposable disposable = controller as IDisposable;
  142. if (disposable != null) {
  143. disposable.Dispose();
  144. }
  145. }
  146. }
  147. }