// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Web.Routing; namespace System.Web.Mvc.Routing { internal static class DirectRouteExtensions { /// /// Gets the precedence or this route. /// public static decimal GetPrecedence(this RouteData routeData) { return GetRouteDataTokenValue(routeData, RouteDataTokenKeys.Precedence); } /// /// Gets the precedence or this route. /// public static decimal GetPrecedence(this Route route) { return GetRouteDataTokenValue(route, RouteDataTokenKeys.Precedence); } /// /// Sets the precedence of this Route. /// public static void SetPrecedence(this Route route, decimal precedence) { SetRouteDataTokenValue(route, RouteDataTokenKeys.Precedence, precedence); } /// /// Gets the order or this route. /// public static int GetOrder(this RouteData routeData) { return GetRouteDataTokenValue(routeData, RouteDataTokenKeys.Order); } /// /// Gets the order or this route. /// public static int GetOrder(this Route route) { return GetRouteDataTokenValue(route, RouteDataTokenKeys.Order); } /// /// Sets the order of this Route. /// public static void SetOrder(this Route route, int order) { SetRouteDataTokenValue(route, RouteDataTokenKeys.Order, order); } /// /// Gets a value indicating whether or not the route is a direct route to an action. /// public static bool GetTargetIsAction(this RouteData routeData) { return GetRouteDataTokenValue(routeData, RouteDataTokenKeys.TargetIsAction); } /// /// Gets a value indicating whether or not the route is a direct route to an action. /// public static bool GetTargetIsAction(this Route route) { return GetRouteDataTokenValue(route, RouteDataTokenKeys.TargetIsAction); } /// /// Sets a value indicating whether or not the route is a direct route to an action. /// public static void SetTargetIsAction(this Route route, bool targetIsAction) { SetRouteDataTokenValue(route, RouteDataTokenKeys.TargetIsAction, targetIsAction); } /// /// Gets the ControllerDescriptor that matches this Route. /// public static ControllerDescriptor GetTargetControllerDescriptor(this Route route) { var actions = GetTargetActionDescriptors(route); ControllerDescriptor controller = null; foreach (var action in actions) { if (controller == null) { controller = action.ControllerDescriptor; } else if (controller != action.ControllerDescriptor) { // Don't provide a single controller descriptor if multiple controllers match. return null; } } return controller; } /// /// Gets the ControllerDescriptor that matches this Route. /// public static ControllerDescriptor GetTargetControllerDescriptor(this RouteData routeData) { var actions = GetTargetActionDescriptors(routeData); ControllerDescriptor controller = null; foreach (var action in actions) { if (controller == null) { controller = action.ControllerDescriptor; } else if (controller != action.ControllerDescriptor) { // Don't provide a single controller descriptor if multiple controllers match. return null; } } return controller; } public static Type GetTargetControllerType(this RouteData routeData) { ControllerDescriptor controllerDescriptor = routeData.GetTargetControllerDescriptor(); return controllerDescriptor == null ? null : controllerDescriptor.ControllerType; } /// /// Gets the target actions that can be matched if this route is matched. /// public static ActionDescriptor[] GetTargetActionDescriptors(this RouteData routeData) { return GetRouteDataTokenValue(routeData, RouteDataTokenKeys.Actions); } /// /// Gets the target actions that can be matched if this route is matched. /// public static ActionDescriptor[] GetTargetActionDescriptors(this Route route) { return GetRouteDataTokenValue(route, RouteDataTokenKeys.Actions); } /// /// Sets the target actions that can be matched if this route is matched. /// public static void SetTargetActionDescriptors(this Route route, ActionDescriptor[] actionDescriptors) { if (actionDescriptors == null || actionDescriptors.Length == 0) { throw Error.ParameterCannotBeNullOrEmpty("actionDescriptors"); } SetRouteDataTokenValue(route, RouteDataTokenKeys.Actions, actionDescriptors); } public static bool HasDirectRouteMatch(this RouteData routeData) { if (routeData == null) { throw Error.ArgumentNull("routeData"); } return routeData.Values.ContainsKey(RouteDataTokenKeys.DirectRouteMatches); } public static IEnumerable GetDirectRouteMatches(this RouteData routeData) { return GetRouteDataValue>(routeData, RouteDataTokenKeys.DirectRouteMatches) ?? Enumerable.Empty(); } public static void SetDirectRouteMatches(this RouteData routeData, IEnumerable matches) { if (matches == null || !matches.Any()) { throw Error.ParameterCannotBeNullOrEmpty("matches"); } SetRouteDataValue(routeData, RouteDataTokenKeys.DirectRouteMatches, matches); } public static bool IsDirectRoute(this RouteBase routeBase) { Route route = routeBase as Route; if (route == null) { return false; } else { // All direct routes need to have actions associated. return route.GetTargetActionDescriptors() != null; } } private static T GetRouteDataTokenValue(this Route route, string key) { if (route == null) { throw Error.ArgumentNull("route"); } if (key == null) { throw Error.ArgumentNull("key"); } T value; if (route.DataTokens != null && route.DataTokens.TryGetValue(key, out value)) { return value; } else { return default(T); } } private static T GetRouteDataTokenValue(this RouteData routeData, string key) { if (routeData == null) { throw Error.ArgumentNull("route"); } if (key == null) { throw Error.ArgumentNull("key"); } return GetRouteDataTokenValue(routeData.Route as Route, key); } private static void SetRouteDataTokenValue(this Route route, string key, T value) { if (route == null) { throw Error.ArgumentNull("route"); } if (key == null) { throw Error.ArgumentNull("key"); } if (route.DataTokens == null) { route.DataTokens = new RouteValueDictionary(); } route.DataTokens[key] = value; } private static T GetRouteDataValue(this RouteData routeData, string key) { if (routeData == null) { throw Error.ArgumentNull("routeData"); } if (key == null) { throw Error.ArgumentNull("key"); } T value; if (routeData.Values.TryGetValue(key, out value)) { return value; } else { return default(T); } } private static void SetRouteDataValue(this RouteData routeData, string key, T value) { if (routeData == null) { throw Error.ArgumentNull("routeData"); } if (key == null) { throw Error.ArgumentNull("key"); } routeData.Values[key] = value; } } }