1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Diagnostics.CodeAnalysis;
\r
16 using System.Web.Routing;
\r
18 public static class RouteCollectionExtensions {
\r
20 // This method returns a new RouteCollection containing only routes that matched a particular area.
\r
21 // The Boolean out parameter is just a flag specifying whether any registered routes were area-aware.
\r
22 private static RouteCollection FilterRouteCollectionByArea(RouteCollection routes, string areaName, out bool usingAreas) {
\r
23 if (areaName == null) {
\r
24 areaName = String.Empty;
\r
28 RouteCollection filteredRoutes = new RouteCollection();
\r
30 using (routes.GetReadLock()) {
\r
31 foreach (RouteBase route in routes) {
\r
32 string thisAreaName = AreaHelpers.GetAreaName(route) ?? String.Empty;
\r
33 usingAreas |= (thisAreaName.Length > 0);
\r
34 if (String.Equals(thisAreaName, areaName, StringComparison.OrdinalIgnoreCase)) {
\r
35 filteredRoutes.Add(route);
\r
40 // if areas are not in use, the filtered route collection might be incorrect
\r
41 return (usingAreas) ? filteredRoutes : routes;
\r
44 public static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, RouteValueDictionary values) {
\r
45 return GetVirtualPathForArea(routes, requestContext, null /* name */, values);
\r
48 public static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values) {
\r
49 bool usingAreas; // don't care about this value
\r
50 return GetVirtualPathForArea(routes, requestContext, name, values, out usingAreas);
\r
53 internal static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values, out bool usingAreas) {
\r
54 if (routes == null) {
\r
55 throw new ArgumentNullException("routes");
\r
58 if (!String.IsNullOrEmpty(name)) {
\r
59 // the route name is a stronger qualifier than the area name, so just pipe it through
\r
61 return routes.GetVirtualPath(requestContext, name, values);
\r
64 string targetArea = null;
\r
65 if (values != null) {
\r
66 object targetAreaRawValue;
\r
67 if (values.TryGetValue("area", out targetAreaRawValue)) {
\r
68 targetArea = targetAreaRawValue as string;
\r
71 // set target area to current area
\r
72 if (requestContext != null) {
\r
73 targetArea = AreaHelpers.GetAreaName(requestContext.RouteData);
\r
78 // need to apply a correction to the RVD if areas are in use
\r
79 RouteValueDictionary correctedValues = values;
\r
80 RouteCollection filteredRoutes = FilterRouteCollectionByArea(routes, targetArea, out usingAreas);
\r
82 correctedValues = new RouteValueDictionary(values);
\r
83 correctedValues.Remove("area");
\r
86 VirtualPathData vpd = filteredRoutes.GetVirtualPath(requestContext, correctedValues);
\r
90 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#",
\r
91 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
92 public static void IgnoreRoute(this RouteCollection routes, string url) {
\r
93 IgnoreRoute(routes, url, null /* constraints */);
\r
96 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#",
\r
97 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
98 public static void IgnoreRoute(this RouteCollection routes, string url, object constraints) {
\r
99 if (routes == null) {
\r
100 throw new ArgumentNullException("routes");
\r
103 throw new ArgumentNullException("url");
\r
106 IgnoreRouteInternal route = new IgnoreRouteInternal(url) {
\r
107 Constraints = new RouteValueDictionary(constraints)
\r
113 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
\r
114 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
115 public static Route MapRoute(this RouteCollection routes, string name, string url) {
\r
116 return MapRoute(routes, name, url, null /* defaults */, (object)null /* constraints */);
\r
119 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
\r
120 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
121 public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults) {
\r
122 return MapRoute(routes, name, url, defaults, (object)null /* constraints */);
\r
125 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
\r
126 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
127 public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints) {
\r
128 return MapRoute(routes, name, url, defaults, constraints, null /* namespaces */);
\r
131 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
\r
132 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
133 public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces) {
\r
134 return MapRoute(routes, name, url, null /* defaults */, null /* constraints */, namespaces);
\r
137 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
\r
138 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
139 public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces) {
\r
140 return MapRoute(routes, name, url, defaults, null /* constraints */, namespaces);
\r
143 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
\r
144 Justification = "This is not a regular URL as it may contain special routing characters.")]
\r
145 public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
\r
146 if (routes == null) {
\r
147 throw new ArgumentNullException("routes");
\r
150 throw new ArgumentNullException("url");
\r
153 Route route = new Route(url, new MvcRouteHandler()) {
\r
154 Defaults = new RouteValueDictionary(defaults),
\r
155 Constraints = new RouteValueDictionary(constraints),
\r
156 DataTokens = new RouteValueDictionary()
\r
159 if ((namespaces != null) && (namespaces.Length > 0)) {
\r
160 route.DataTokens["Namespaces"] = namespaces;
\r
163 routes.Add(name, route);
\r
168 private sealed class IgnoreRouteInternal : Route {
\r
169 public IgnoreRouteInternal(string url)
\r
170 : base(url, new StopRoutingHandler()) {
\r
173 public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues) {
\r
174 // Never match during route generation. This avoids the scenario where an IgnoreRoute with
\r
175 // fairly relaxed constraints ends up eagerly matching all generated URLs.
\r