예제 #1
0
        /// <summary>
        /// Get the possible route datas that could have selected a given container or content item via a route
        /// </summary>
        /// <param name="route">The route</param>
        /// <param name="o">The container or content item</param>
        /// <returns>The route datas that could have accessed the object via the route</returns>
        public List<RouteData> GetRouteDatas(Route route, Address address)
        {
            // Start list of urls which could map to this item.  Note, catchall items (starting *) are treated as normal ones
            List<RouteValueDictionary> rvds = new List<RouteValueDictionary>();

            var keyOutputs = route.KeyOutputs();

            Type type = address.Type;

            ICollator collator = Collator.Instance.Registered(type);
            var rvd = new RouteValueDictionary(address);

            // Action & controller

            if (!(keyOutputs.ContainsKey("controller") && keyOutputs.ContainsKey("action")))
                throw new Exception("Route " + route.Url + " fails to define controller and action");

            if (keyOutputs["controller"].StartsWith("?"))
                throw new Exception("Route " + route.Url + " is a data route which lacks but must have a specified controller");

            if (!ContentTypeHierarchy.ControllerActions.ContainsKey(keyOutputs["controller"]))
                return new List<RouteData>();  // Controller doesn't exist therefore no rvds

            rvd.Add("controller", keyOutputs["controller"]);

            rvds.Add(rvd);

            // copy list so we can change 'actions'
            var actions = ContentTypeHierarchy.ControllerActions[keyOutputs["controller"]].ToList();
            if (keyOutputs["action"].StartsWith("?"))
            {
                if (keyOutputs["action"].Length > 1 && actions.Contains(keyOutputs["action"].Substring(1).ToLower()))
                    actions.Add("??");
                rvds = PermuteAdd(rvds, "action", actions);
            }
            else if (!actions.Contains(keyOutputs["action"]))
                return new List<RouteData>(); // Fixed action doesn't exist therefore no urls
            else
                rvd.Add("action", keyOutputs["action"]);

            // Route vars addressing the content item

            foreach (var kvp in keyOutputs)
            {
                if (kvp.Key == "controller" || kvp.Key == "action") // already dealt with
                    continue;

                if (kvp.Value == "??" && address.ContainsKey(kvp.Key)) // optional variable
                {
                    address.SetMatched(kvp.Key);
                }
                else if (kvp.Value.StartsWith("?")) // variable takes any value
                {
                    // matches a path element
                    address.SetMatched(kvp.Key);   // this address element is matched
                }
                else // fixed value, has to be matched by item
                {
                    bool matched = false;
                    if (address.ContainsKey(kvp.Key))
                    {
                        if (address.GetAsString(kvp.Key) == kvp.Value)
                        {
                            matched = true;
                            address.SetMatched(kvp.Key);
                        }
                    }
                    if (!matched)
                        return new List<RouteData>();
                }
            }

            if (!address.FullyMatched) // Fails because one or more address elements could not have come from this route
                return new List<RouteData>();

            return rvds
                .Select(r =>
                    {
                        var rd = new RouteData();
                        r.Do(kvp => rd.Values.Add(kvp.Key, kvp.Value));
                        rd.Route = route;
                        rd.RouteHandler = route.RouteHandler;
                        return rd;
                    })
                .ToList();
        }
예제 #2
0
        /// <summary>
        /// Get the possible urls that could have selected a given container or content item via a given route
        /// </summary>
        /// <param name="route">The route</param>
        /// <param name="address">The content address</param>
        /// <returns>The urls that could have accessed the object via the route</returns>
        public List<string> GetUrls(Route route, Address address)
        {
            // Start list of urls which could map to this item.  Note, catchall items (starting *) are treated as normal ones
            List<string> urls = new List<string> { route.Url.Replace("{*", "{") };

            var keyOutputs = route.KeyOutputs();

            List<string> replaceWiths = null;

            // Action & controller

            if (!(keyOutputs.ContainsKey("controller") && keyOutputs.ContainsKey("action")))
                throw new Exception("Route " + route.Url + " fails to define controller and action");

            if (keyOutputs["controller"].StartsWith("?"))
                throw new Exception("Route " + route.Url + " is a data route which lacks but must have a specified controller");

            if (!ContentTypeHierarchy.ControllerActions.ContainsKey(keyOutputs["controller"]))
                return new List<string>();  // Controller doesn't exist therefore no urls

            // copy list so we can change 'actions'
            var actions = ContentTypeHierarchy.ControllerActions[keyOutputs["controller"]].ToList();
            if (keyOutputs["action"].StartsWith("?"))
            {
                if (keyOutputs["action"].Length > 1 && actions.Contains(keyOutputs["action"].Substring(1).ToLower()))
                    actions.Add("??");
                UrlX.PermuteReplace(urls, "{action}", actions);
            }
            else if (!actions.Contains(keyOutputs["action"]))
                return new List<string>(); // Fixed action doesn't exist therefore no urls

            // Route vars addressing the content item

            foreach (var kvp in keyOutputs)
            {
                if (kvp.Key == "controller" || kvp.Key == "action") // already dealt with
                    continue;

                if (kvp.Value.StartsWith("?") && kvp.Value != "??") // variable takes any value
                {
                    if (address.ContainsKey(kvp.Key)) // its part of the content item address
                    {
                        // path element is the default value, so this url element is optional
                        replaceWiths = new List<string> { address.GetAsString(kvp.Key) };
                        if (kvp.Value.Length > 1 && address.GetAsString(kvp.Key) == kvp.Value.Substring(1))
                            replaceWiths.Add("??");
                        // matches a path element
                        address.SetMatched(kvp.Key);   // this address element is matched
                    }
                    else
                    {
                        replaceWiths = new List<string> { "?" };// no match, so many urls mapped to this item
                        int nUrls = urls.Count;
                        if (kvp.Value.Length > 1) // there's a default value so the element is optional
                            replaceWiths.Add("??");
                    }
                    UrlX.PermuteReplace(urls, "{" + kvp.Key + "}", replaceWiths);
                }
                else if (kvp.Value == "??")
                {
                    UrlX.PermuteReplace(urls, "{" + kvp.Key + "}", new List<string> { "??" });   // optional variable
                }
                else // fixed value, has to be matched by item
                {
                    bool matched = false;
                    if (address.ContainsKey(kvp.Key))
                    {
                        if (address.GetAsString(kvp.Key) == kvp.Value)
                        {
                            matched = true;
                            address.SetMatched(kvp.Key);
                        }
                    }
                    if (!matched)
                        return new List<string>();
                }
            }

            if (!address.FullyMatched) // Fails because one or more address elements could not have come from this route
                return new List<string>();

            // Deal with possible url variations with omitted path elements

            for (int i = 0; i < urls.Count; i++)
            {
                while (urls[i].EndsWith("/??"))
                    urls[i] = urls[i].Substring(0, urls[i].Length - 3);
                if (urls[i].Contains("??"))
                    urls[i] = null;
            }

            return urls.Where(u => u != null).OrderBy(u => u.Split('/').Length).Select(u => "/" + u).ToList();
        }
예제 #3
0
        public List<string> GetUrls(Route route, object item)
        {
            string url = route.Url;
            var keyOutputs = route.KeyOutputs();
            foreach (var kvp in keyOutputs)
            {
                if (kvp.Key == "@id") // We're looking at the id variable, the only one matchable by our item
                {
                    PropertyInfo keyProp = item.GetType().GetProperties().FirstOrDefault(p => p.CustomAttributes.Any(cad => cad.AttributeType == typeof(KeyAttribute)));
                    if (keyProp != null)
                    {
                        string id = keyProp.GetValue(item).ToString();
                        url.Replace("{@id}", id);
                    }
                    else
                        url.Replace("{@id}", "?");
                }
                else if (kvp.Value == "?" || kvp.Value == "??")
                    url.Replace("{" + kvp.Key + "}", kvp.Value);
                else if (kvp.Value.StartsWith("?"))
                {

                    url.Replace("{" + kvp.Key + "}", "?");
                }
            }
            while (url.EndsWith("/??"))
                url = url.UpToLast("/??");
            return new List<string> { url };
        }