/// <summary> /// Constructs a new route by appending a path to this instance /// </summary> /// <param name="path">The path to append.</param> /// <param name="caseinsensitive">If set to <c>true</c>, comapres are performed case insensitive.</param> /// <param name="target">The target method.</param> /// <returns>The combined route</returns> public RouteParser Append(string path, bool caseinsensitive, RouteEntry target) { return(Append(new RouteParser(path, caseinsensitive, target))); }
private static RouteParser BuildParse(IEnumerable <Controller> controllers, ControllerRouterConfig config) { var controller_routes = controllers.SelectMany(x => { string name; var nameattr = x.GetType().GetCustomAttributes(typeof(NameAttribute), false).Cast <NameAttribute>().FirstOrDefault(); // Extract controller name if (nameattr != null) { name = nameattr.Name; } else { name = x.GetType().Name; if (config.ControllerSuffixRemovals != null) { foreach (var rm in config.ControllerSuffixRemovals) { while (!string.IsNullOrWhiteSpace(rm) && name.EndsWith(rm, StringComparison.InvariantCultureIgnoreCase)) { name = name.Substring(0, name.Length - rm.Length); } } } if (config.LowerCaseNames) { name = name.ToLowerInvariant(); } } var routes = x.GetType().GetCustomAttributes(typeof(RouteAttribute), false).Cast <RouteAttribute>().Select(y => y.Route); // Add default route, if there are no route attributes if (routes.Count() == 0) { routes = new[] { string.Empty } } ; return(routes.Distinct().Select(y => new { Controller = x, ControllerRoute = y })); } ).ToArray(); var interface_expanded_routes = controller_routes.SelectMany(x => { var interfaces = x.Controller.GetType().GetParentInterfaces <IControllerPrefix>(); var interfacenames = interfaces .Select(y => x.Controller.GetType().GetParentInterfaceSequence(y).Reverse().Where(z => z != x.Controller.GetType() && z != typeof(IControllerPrefix))) .Select(y => string.Join("/", y.Select(z => z.GetItemName(config)))); if (interfacenames.Count() == 0) { interfacenames = new[] { string.Empty } } ; return(interfacenames.Distinct().Select(y => new { Controller = x.Controller, ControllerRoute = x.ControllerRoute, InterfacePath = (y ?? string.Empty) })); } ).ToArray(); var target_method_routes = interface_expanded_routes.SelectMany(x => { return (x.Controller.GetType() .GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(y => y.ReturnType == typeof(void) || typeof(IResult).IsAssignableFrom(y.ReturnType) || typeof(Task).IsAssignableFrom(y.ReturnType)) .Select(y => new { Controller = x.Controller, ControllerRoute = x.ControllerRoute, InterfacePath = x.InterfacePath, Method = y })); } ).ToArray(); var target_routes = target_method_routes.SelectMany(x => { var routes = x.Method.GetCustomAttributes(typeof(RouteAttribute), false).Cast <RouteAttribute>().Select(y => y.Route); // Add default route, if there are no route attributes if (routes.Count() == 0) { routes = new[] { string.Empty } } ; return(routes.Select(y => new { Controller = x.Controller, ControllerRoute = x.ControllerRoute, InterfacePath = x.InterfacePath, Method = x.Method, MethodRoute = y })); } ).ToArray(); // Now we have the cartesian product of all route/controller/action pairs, then build the target strings var tmp = new RouteParser(config.Template, !config.CaseSensitive, null); var defaultcontrollername = tmp.GetDefaultValue(config.ControllerGroupName); var defaultactionname = tmp.GetDefaultValue(config.ActionGroupName); var target_strings = target_routes.SelectMany(x => { var methodverbs = x.Method.GetCustomAttributes(typeof(HttpVerbFilterAttribute), false).Cast <HttpVerbFilterAttribute>().Select(b => b.Verb.ToUpperInvariant()); var entry = new RouteEntry(x.Controller, x.Method, methodverbs.ToArray(), null); var path = new RouteParser("/", !config.CaseSensitive, entry); if (!string.IsNullOrWhiteSpace(x.InterfacePath)) { if (x.InterfacePath.StartsWith("/", StringComparison.Ordinal)) { path = new RouteParser(x.InterfacePath, !config.CaseSensitive, entry); } else { path = path.Append(x.InterfacePath, !config.CaseSensitive, entry); } } var ct = string.IsNullOrWhiteSpace(x.ControllerRoute) ? config.Template : x.ControllerRoute; if (!string.IsNullOrWhiteSpace(ct)) { if (ct.StartsWith("/", StringComparison.Ordinal)) { path = new RouteParser(ct, !config.CaseSensitive, entry); } else { if (!path.Path.EndsWith("/", StringComparison.Ordinal)) { ct = "/" + ct; } path = path.Append(ct, !config.CaseSensitive, entry); } } var mt = x.MethodRoute; if (!string.IsNullOrWhiteSpace(mt)) { if (mt.StartsWith("/", StringComparison.Ordinal)) { path = new RouteParser(mt, !config.CaseSensitive, entry); } else { path = path.Bind(config.ActionGroupName, string.Empty, !config.CaseSensitive, true); if (!path.Path.EndsWith("/", StringComparison.Ordinal)) { mt = "/" + mt; } path = path.Append(mt, !config.CaseSensitive, entry); } } var controllername = x.Controller.GetType().GetItemName(config); var actionname = x.Method.GetItemName(config); var controllernames = new List <string>(); var actionnames = new List <string>(); if (!config.HideDefaultController || controllername != defaultcontrollername) { controllernames.Add(controllername); } if (!config.HideDefaultAction || actionname != defaultactionname) { actionnames.Add(actionname); } if (!string.IsNullOrEmpty(defaultcontrollername) && controllername == defaultcontrollername) { controllernames.Add(string.Empty); } if (!string.IsNullOrEmpty(defaultactionname) && actionname == defaultactionname) { actionnames.Add(string.Empty); } // Cartesian product with controller and action names bound return(controllernames .SelectMany(y => actionnames.Select( z => path .Bind(config.ControllerGroupName, y, !config.CaseSensitive, true) .Bind(config.ActionGroupName, z, !config.CaseSensitive, true) .PrunePath() .ReplaceTarget(x.Controller, x.Method, methodverbs.ToArray()) ) )); } ) .Distinct(x => x.ToString()) .ToArray(); var merged = RouteParser.Merge(target_strings); if (config.Debug) { Console.WriteLine("All target paths:"); foreach (var x in target_strings) { Console.WriteLine(x); } Console.WriteLine("Map structure:"); Console.WriteLine(merged.ToString()); } return(merged); }
/// <summary> /// Initializes a new instance of the <see cref="T:Ceen.Mvc.RouteParser2.Result"/> struct. /// </summary> /// <param name="entry">The entry to represent.</param> public Result(RouteEntry entry) { Route = entry; }
private static RouteParser BuildParse(IEnumerable <Controller> controllers, ControllerRouterConfig config) { var target_routes = ParseControllers(controllers, config) // Attach custom controller routes .Concat( controllers.OfType <ManualRoutingController>().SelectMany(x => x.Routes) ) .ToArray(); // Now we have the cartesian product of all route/controller/action pairs, then build the target strings var tmp = new RouteParser(config.Template, !config.CaseSensitive, null); var defaultcontrollername = tmp.GetDefaultValue(config.ControllerGroupName); var defaultactionname = tmp.GetDefaultValue(config.ActionGroupName); var target_strings = target_routes.SelectMany(x => { // Provide a hook point for the dynamic routing option if (x.Controller is IIDynamicConfiguredController idc) { x = idc.PatchRoute(x); } var entry = new RouteEntry(x.Controller, x.Method, x.Verbs, null); var path = new RouteParser("/", !config.CaseSensitive, entry); if (!string.IsNullOrWhiteSpace(x.InterfacePath)) { if (x.InterfacePath.StartsWith("/", StringComparison.Ordinal)) { path = new RouteParser(x.InterfacePath, !config.CaseSensitive, entry); } else { path = path.Append(x.InterfacePath, !config.CaseSensitive, entry); } } var ct = string.IsNullOrWhiteSpace(x.ControllerPath) ? config.Template : x.ControllerPath; if (!string.IsNullOrWhiteSpace(ct)) { if (ct.StartsWith("/", StringComparison.Ordinal)) { path = new RouteParser(ct, !config.CaseSensitive, entry); } else { if (!path.Path.EndsWith("/", StringComparison.Ordinal)) { ct = "/" + ct; } path = path.Append(ct, !config.CaseSensitive, entry); } } var mt = x.MethodPath; if (!string.IsNullOrWhiteSpace(mt)) { if (mt.StartsWith("/", StringComparison.Ordinal)) { path = new RouteParser(mt, !config.CaseSensitive, entry); } else { path = path.Bind(config.ActionGroupName, string.Empty, !config.CaseSensitive, true); if (!path.Path.EndsWith("/", StringComparison.Ordinal)) { mt = "/" + mt; } path = path.Append(mt, !config.CaseSensitive, entry); } } var controllername = x.Controller.GetType().GetItemName(config); var actionname = x.Method.GetItemName(config); var controllernames = new List <string>(); var actionnames = new List <string>(); if (!config.HideDefaultController || controllername != defaultcontrollername) { controllernames.Add(controllername); } if (!config.HideDefaultAction || actionname != defaultactionname) { actionnames.Add(actionname); } if (!string.IsNullOrEmpty(defaultcontrollername) && controllername == defaultcontrollername) { controllernames.Add(string.Empty); } if (!string.IsNullOrEmpty(defaultactionname) && actionname == defaultactionname) { actionnames.Add(string.Empty); } // Cartesian product with controller and action names bound return(controllernames .SelectMany(y => actionnames.Select( z => path .Bind(config.ControllerGroupName, y, !config.CaseSensitive, true) .Bind(config.ActionGroupName, z, !config.CaseSensitive, true) .PrunePath() .ReplaceTarget(x.Controller, x.Method, x.Verbs) ) )); } ) .Distinct(x => x.ToString()) .ToArray(); var merged = RouteParser.Merge(target_strings); if (config.Debug) { Console.WriteLine("All target paths:"); foreach (var x in target_strings) { Console.WriteLine(x); } Console.WriteLine("Map structure:"); Console.WriteLine(merged.ToString()); } return(merged); }