예제 #1
0
        /// <summary>
        /// Finds matched route from the list with specified request
        /// </summary>
        public RouteMatch Find(IEnumerable <RouteLeaf> routes, HttpRequest request)
        {
            //split path to route parts
            string[] parts = request.Path.Split('/', StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length == 0)
            {
                parts = new[] { "" }
            }
            ;

            RouteLeaf route = null;

            foreach (RouteLeaf leaf in routes)
            {
                RouteLeaf found = FindRouteInLeaf(leaf, request.Method, parts, 0);
                if (found != null)
                {
                    route = found;
                    break;
                }
            }

            if (route == null)
            {
                return(null);
            }

            RouteMatch match = new RouteMatch();

            match.Values = new Dictionary <string, object>(StringComparer.InvariantCultureIgnoreCase);

            match.Route = route.Route;

            do
            {
                RoutePath path = route.Path;

                //if type is optional parameter we dont need to check if equals
                //we just need to read the part value and put it into value list (if doesn't exists put default value)
                if (path.Type == RouteType.OptionalParameter)
                {
                    match.Values.Add(path.Value,
                                     parts.Length <= route.Index
                                         ? null
                                         : parts[route.Index]);
                }

                //if type is parameter we dont need to check if equals
                //we just need to read the part value and put it into value list
                else if (path.Type == RouteType.Parameter)
                {
                    match.Values.Add(path.Value, parts[route.Index]);
                }

                route = route.Parent;
            } while (route != null);

            return(match);
        }
    }
예제 #2
0
        /// <summary>
        /// Creates all Route objects of the specified Controller type
        /// </summary>
        public IEnumerable <RouteLeaf> BuildRoutes(Type controllerType)
        {
            //find base path for the controller
            List <RouteLeaf> routes = CreateControllerRoutes(controllerType);
            List <RouteLeaf> edges  = new List <RouteLeaf>();

            foreach (RouteLeaf leaf in routes)
            {
                edges.AddRange(GetEdgeLeaves(leaf));
            }

            MethodInfo[] methods = controllerType.GetMethods();
            foreach (MethodInfo method in methods)
            {
                //find method route if exists
                List <RouteInfo> methodRoutes = FindActionRoute(method);
                if (methodRoutes.Count == 0)
                {
                    continue;
                }

                foreach (RouteLeaf cleaf in edges)
                {
                    foreach (RouteInfo info in methodRoutes)
                    {
                        //get route table from the fullpath
                        List <RoutePath> path = GetRoutePath(method, info.Pattern);

                        RouteLeaf leaf = cleaf;
                        for (int i = 0; i < path.Count; i++)
                        {
                            RoutePath rp    = path[i];
                            RouteLeaf child = new RouteLeaf(rp, leaf);
                            leaf.Children.Add(child);
                            leaf = child;

                            if (i == path.Count - 1)
                            {
                                leaf.Route = new Route
                                {
                                    ActionType     = method,
                                    ControllerType = controllerType,
                                    Method         = info.Method,
                                    Path           = path.ToArray(),
                                    Parameters     = BuildParameters(method),
                                    IsAsyncMethod  = (AsyncStateMachineAttribute)method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null
                                };
                            }
                        }

                        ApplyControllerAttributes(leaf.Route, controllerType);
                        ApplyActionAttributes(leaf.Route, method);
                    }
                }
            }

            return(routes);
        }
예제 #3
0
        /// <summary>
        /// Creates new leaf in specified path
        /// </summary>
        public RouteLeaf(RoutePath path, RouteLeaf parent)
        {
            Children = new List <RouteLeaf>();

            Path   = path;
            Parent = parent;

            if (parent != null && !string.IsNullOrEmpty(parent.Path.Value))
            {
                Index = parent.Index + 1;
            }
        }
예제 #4
0
        /// <summary>
        /// Finds route value for the controller type
        /// </summary>
        private static List <RouteLeaf> CreateControllerRoutes(Type controllerType)
        {
            List <RouteLeaf>             routes     = new List <RouteLeaf>();
            IEnumerable <RouteAttribute> attributes = controllerType.GetCustomAttributes <RouteAttribute>(true);

            foreach (RouteAttribute attr in attributes)
            {
                string value = attr.Pattern;
                if (value == null)
                {
                    routes.Add(new RouteLeaf(new RoutePath(RouteType.Text, FindControllerRouteName(controllerType)), null));
                    continue;
                }

                if (value == "")
                {
                    routes.Add(new RouteLeaf(new RoutePath(RouteType.Text, ""), null));
                    continue;
                }

                string[]  pathLeaves = value.Split('/', StringSplitOptions.RemoveEmptyEntries);
                RouteLeaf parent     = null;
                foreach (string p in pathLeaves)
                {
                    string v = p;
                    if (p.Equals("[controller]", StringComparison.InvariantCultureIgnoreCase))
                    {
                        v = FindControllerRouteName(controllerType);
                    }

                    RouteLeaf leaf = new RouteLeaf(new RoutePath(RouteType.Text, v), parent);
                    if (parent == null)
                    {
                        routes.Add(leaf);
                    }
                    else
                    {
                        parent.Children.Add(leaf);
                    }

                    parent = leaf;
                }
            }

            //if there is no route definition, the route value is the name of the controller
            if (routes.Count == 0)
            {
                routes.Add(new RouteLeaf(new RoutePath(RouteType.Text, FindControllerRouteName(controllerType)), null));
            }

            return(routes);
        }
예제 #5
0
        /// <summary>
        /// Sorts all route leaves recursively
        /// </summary>
        internal void SortChildren(RouteLeaf leaf)
        {
            if (leaf.Children.Count == 0)
            {
                return;
            }

            SortRoutes(leaf.Children);

            foreach (RouteLeaf child in leaf.Children)
            {
                SortChildren(child);
            }
        }
예제 #6
0
        private IEnumerable <RouteLeaf> GetEdgeLeaves(RouteLeaf root)
        {
            if (root.Children.Count == 0)
            {
                yield return(root);

                yield break;
            }

            foreach (RouteLeaf leaf in root.Children)
            {
                IEnumerable <RouteLeaf> leaves = GetEdgeLeaves(leaf);
                foreach (RouteLeaf child in leaves)
                {
                    yield return(child);
                }
            }
        }
예제 #7
0
        private RouteLeaf FindRouteInLeaf(RouteLeaf leaf, string method, string[] parts, int index)
        {
            //for text parts, it should match
            if (leaf.Path.Type == RouteType.Text)
            {
                bool matched = leaf.Path.Value.Equals(parts[index], StringComparison.InvariantCultureIgnoreCase);
                if (!matched)
                {
                    return(null);
                }
            }

            //if leaf is last of path check method and return if equals
            if (leaf.Route != null)
            {
                if (parts.Length == index + 1 && leaf.Route.Method.Equals(method, StringComparison.InvariantCultureIgnoreCase))
                {
                    return(leaf);
                }

                return(null);
            }

            if (leaf.Children.Count == 0)
            {
                return(null);
            }

            //parts are done but route may keep going to optional parameters
            if (parts.Length == index + 1)
            {
                RouteLeaf x = leaf;
                while (x.Children.Count == 1)
                {
                    RouteLeaf y = x.Children[0];

                    if (y.Path.Type == RouteType.Text && string.IsNullOrEmpty(y.Path.Value))
                    {
                        if (y.Route.Method.Equals(method, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(y);
                        }

                        return(null);
                    }

                    if (y.Path.Type != RouteType.OptionalParameter)
                    {
                        break;
                    }

                    if (y.Route != null)
                    {
                        if (y.Route.Method.Equals(method, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(y);
                        }

                        break;
                    }

                    x = y;
                }
            }

            if (parts.Length < index + 2)
            {
                return(null);
            }

            int next = index + 1;

            foreach (RouteLeaf child in leaf.Children)
            {
                RouteLeaf found = FindRouteInLeaf(child, method, parts, next);
                if (found != null)
                {
                    return(found);
                }
            }

            return(null);
        }