private bool CalculateRoute(RoutePath path, string httpMethod, RouteBuilder route, RouteNode node) { using (path.Pin()) using (var pin = route.Pin()) { if (node.Part.AcceptPath(path, httpMethod)) { route.Add(node.Part); if (node.Children.Any()) { foreach (var child in node.Children) { if (CalculateRoute(path, httpMethod, route, child)) { pin.Accept(); return true; } } } else if (!path.Any()) { pin.Accept(); return true; } } return false; } }
public void GenerateRoutesForController(RouteTree routeTree, Type controllerType) { var routeAttributes = controllerType.GetCustomAttributes(typeof(RouteAttribute), true); var routeAttribute = routeAttributes.Length > 0 ? (RouteAttribute)routeAttributes[0] : null; string route; if (routeAttribute == null) { route = GenerateDefaultRouteForController(controllerType); } else { route = routeAttribute.Value; } var routePath = new RoutePath(route); var currentNode = (IRouteNode)routeTree; var leafNodes = new List <RouteNode>(); do { RouteNode nextNode = null; if (routePath.Current != null) { var routePart = routePath.Consume(); var part = new RouteLiteral(routePart, true); nextNode = new RouteNode(part); AddNode(currentNode, nextNode); if (routePath.Current == null) { part.RouteData[RouteData.ControllerKey] = controllerType; leafNodes.Add(nextNode); } } // If defined as a default route, then we don't require the last path part if (routePath.Current == null) { var defaultAttributes = controllerType.GetCustomAttributes(typeof(DefaultAttribute), true); if (defaultAttributes.Length > 0) { var defaultNode = new RouteNode(new RouteDefault(RouteData.ControllerKey, controllerType)); AddNode(currentNode, defaultNode); leafNodes.Add(defaultNode); } } currentNode = nextNode; }while (routePath.Current != null); foreach (var method in controllerType.GetMethods().Where(x => x.IsPublic && !x.IsStatic && (typeof(ActionResult).IsAssignableFrom(x.ReturnType) || typeof(Task <ActionResult>).IsAssignableFrom(x.ReturnType)))) { GenerateRoutesForAction(routeTree, controllerType, leafNodes, method); } }
public void GenerateRoutesForController(RouteTree routeTree, Type controllerType) { var routeAttributes = controllerType.GetCustomAttributes(typeof(RouteAttribute), true); var routeAttribute = routeAttributes.Length > 0 ? (RouteAttribute)routeAttributes[0] : null; string route; if (routeAttribute == null) route = GenerateDefaultRouteForController(controllerType); else route = routeAttribute.Value; var routePath = new RoutePath(route); var currentNode = (IRouteNode)routeTree; var leafNodes = new List<RouteNode>(); do { RouteNode nextNode = null; if (routePath.Current != null) { var routePart = routePath.Consume(); var part = new RouteLiteral(routePart, true); nextNode = new RouteNode(part); AddNode(currentNode, nextNode); if (routePath.Current == null) { part.RouteData[RouteData.ControllerKey] = controllerType; leafNodes.Add(nextNode); } } // If defined as a default route, then we don't require the last path part if (routePath.Current == null) { var defaultAttributes = controllerType.GetCustomAttributes(typeof(DefaultAttribute), true); if (defaultAttributes.Length > 0) { var defaultNode = new RouteNode(new RouteDefault(RouteData.ControllerKey, controllerType)); AddNode(currentNode, defaultNode); leafNodes.Add(defaultNode); } } currentNode = nextNode; } while (routePath.Current != null); foreach (var method in controllerType.GetMethods().Where(x => x.IsPublic && !x.IsStatic && (typeof(ActionResult).IsAssignableFrom(x.ReturnType) || typeof(Task<ActionResult>).IsAssignableFrom(x.ReturnType)))) { GenerateRoutesForAction(routeTree, controllerType, leafNodes, method); } }
private RouteNode AddNode(IRouteNode parent, RouteNode child) { // var duplicate = child.FindDuplicate(parent); // if (duplicate != null) // { // child.FindDuplicate(parent); // throw new DuplicateRouteException(parent, child, duplicate); // } if (child.Part is RouteLiteral) { var routeLiteral = (RouteLiteral)child.Part; if (!routeLiteral.IsTerminal) { var commonChild = parent.Children.SingleOrDefault(x => x.Part is RouteLiteral && ((RouteLiteral)x.Part).Literal == routeLiteral.Literal && !((RouteLiteral)x.Part).IsTerminal); if (commonChild != null) { return(commonChild); } } } if (child.Part is RouteVariable) { var routeVariable = (RouteVariable)child.Part; if (!routeVariable.IsTerminal) { var commonChild = parent.Children.SingleOrDefault(x => x.Part is RouteVariable && !((RouteVariable)x.Part).IsTerminal); if (commonChild != null) { return(commonChild); } } } if (child.Part.RouteData.ContainsKey(Routes.RouteData.RequiredHttpMethodKey) || child.Part is RouteLiteral) { parent.Children.Insert(0, child); } else { parent.Children.Add(child); } return(child); }
private void GenerateRoutesForAction(RouteTree routeTree, Type controllerType, List <RouteNode> parentNodes, MethodInfo actionMethod) { var routeAttributes = actionMethod.GetCustomAttributes(typeof(RouteAttribute), true); var routeAttribute = routeAttributes.Length > 0 ? (RouteAttribute)routeAttributes[0] : null; string route; if (routeAttribute == null) { route = GenerateDefaultRouteForAction(actionMethod); } else { route = routeAttribute.Value; } string httpMethod = null; if (actionMethod.IsDefined(typeof(HttpPostAttribute), false)) { httpMethod = "POST"; } bool addToRoot = false; if (route.StartsWith("/")) { addToRoot = true; } var effectiveNodes = addToRoot ? new[] { (IRouteNode)routeTree } : parentNodes.ToArray(); foreach (var node in effectiveNodes) { var routePath = new RoutePath(route); var currentNode = node; do { RouteNode nextNode = null; if (routePath.Current != null) { var part = routePath.Consume(); if (part == "@") { part = GenerateDefaultRouteForAction(actionMethod); } RoutePart routePart; if (part == "*") { var parameter = actionMethod.GetParameters().Single(); routePart = new RouteWildcard(parameter); } else if (part.StartsWith("{") && part.EndsWith("}")) { var id = part.ChopStart("{").ChopEnd("}"); var parameter = actionMethod.GetParameters().Single(x => x.Name == id); routePart = new RouteVariable(routePath.Current == null, parameter); } else { routePart = new RouteLiteral(part, routePath.Current == null); } nextNode = new RouteNode(routePart); if (routePath.Current == null) { routePart.RouteData[RouteData.ActionKey] = actionMethod; routePart.RouteData[RouteData.ControllerKey] = controllerType; if (httpMethod != null) { routePart.RouteData[RouteData.RequiredHttpMethodKey] = httpMethod; } } nextNode = AddNode(currentNode, nextNode); } if (routePath.Current == null) { if (actionMethod.IsDefined(typeof(DefaultAttribute), false)) { AddNode(currentNode, new RouteNode(new RouteDefault(RouteData.ActionKey, actionMethod))); } } currentNode = nextNode; }while (routePath.Current != null); } }
private bool CalculateRoute(RoutePath path, string httpMethod, RouteBuilder route, RouteNode node) { using (path.Pin()) using (var pin = route.Pin()) { if (node.Part.AcceptPath(path, httpMethod)) { route.Add(node.Part); if (node.Children.Any()) { foreach (var child in node.Children) { if (CalculateRoute(path, httpMethod, route, child)) { pin.Accept(); return(true); } } } else if (!path.Any()) { pin.Accept(); return(true); } } return(false); } }
private void GenerateRoutesForAction(RouteTree routeTree, Type controllerType, List<RouteNode> parentNodes, MethodInfo actionMethod) { var routeAttributes = actionMethod.GetCustomAttributes(typeof(RouteAttribute), true); var routeAttribute = routeAttributes.Length > 0 ? (RouteAttribute)routeAttributes[0] : null; string route; if (routeAttribute == null) route = GenerateDefaultRouteForAction(actionMethod); else route = routeAttribute.Value; string httpMethod = null; if (actionMethod.IsDefined(typeof(HttpPostAttribute), false)) { httpMethod = "POST"; } bool addToRoot = false; if (route.StartsWith("/")) { addToRoot = true; } var effectiveNodes = addToRoot ? new[] { (IRouteNode)routeTree } : parentNodes.ToArray(); foreach (var node in effectiveNodes) { var routePath = new RoutePath(route); var currentNode = node; do { RouteNode nextNode = null; if (routePath.Current != null) { var part = routePath.Consume(); if (part == "@") { part = GenerateDefaultRouteForAction(actionMethod); } RoutePart routePart; if (part == "*") { var parameter = actionMethod.GetParameters().Single(); routePart = new RouteWildcard(parameter); } else if (part.StartsWith("{") && part.EndsWith("}")) { var pieces = part.ChopStart("{").ChopEnd("}").Split(':'); var id = pieces[0]; var parameter = actionMethod.GetParameters().Single(x => x.Name == id); var variable = new RouteVariable(routePath.Current == null, parameter); var constraints = pieces.Skip(1).ToArray(); foreach (var name in constraints) { var constraint = RouteConstraints.GetConstraint(name); variable.Constraints.Add(constraint); } routePart = variable; } else { routePart = new RouteLiteral(part, routePath.Current == null); } nextNode = new RouteNode(routePart); if (routePath.Current == null) { routePart.RouteData[RouteData.ActionKey] = actionMethod; routePart.RouteData[RouteData.ControllerKey] = controllerType; if (httpMethod != null) routePart.RouteData[RouteData.RequiredHttpMethodKey] = httpMethod; } nextNode = AddNode(currentNode, nextNode); } if (routePath.Current == null) { if (actionMethod.IsDefined(typeof(DefaultAttribute), false)) AddNode(currentNode, new RouteNode(new RouteDefault(RouteData.ActionKey, actionMethod))); } currentNode = nextNode; } while (routePath.Current != null); } }
private RouteNode AddNode(IRouteNode parent, RouteNode child) { // var duplicate = child.FindDuplicate(parent); // if (duplicate != null) // { // child.FindDuplicate(parent); // throw new DuplicateRouteException(parent, child, duplicate); // } if (child.Part is RouteLiteral) { var routeLiteral = (RouteLiteral)child.Part; if (!routeLiteral.IsTerminal) { var commonChild = parent.Children.SingleOrDefault(x => x.Part is RouteLiteral && ((RouteLiteral)x.Part).Literal == routeLiteral.Literal && !((RouteLiteral)x.Part).IsTerminal); if (commonChild != null) { return commonChild; } } } if (child.Part is RouteVariable) { var routeVariable = (RouteVariable)child.Part; if (!routeVariable.IsTerminal) { var commonChild = parent.Children.SingleOrDefault(x => x.Part is RouteVariable && !((RouteVariable)x.Part).IsTerminal); if (commonChild != null) { return commonChild; } } } if (child.Part.RouteData.ContainsKey(Routes.RouteData.RequiredHttpMethodKey) || child.Part is RouteLiteral) parent.Children.Insert(0, child); else parent.Children.Add(child); return child; }