public static JasperRoute Build(Type handlerType, MethodInfo method) { var route = Rules.FirstValue(x => x.DetermineRoute(handlerType, method)); if (route == null) { throw new InvalidOperationException( $"Jasper does not know how to make an Http route from the method {handlerType.NameInCode()}.{method.Name}()"); } route.InputType = DetermineInputType(method); route.HandlerType = handlerType; route.Method = method; var hasPrimitives = method.GetParameters().Any(x => x.ParameterType == typeof(string) || RouteArgument.CanParse(x.ParameterType)); if (hasPrimitives) { for (var i = 0; i < route.Segments.Count; i++) { var current = route.Segments[i].SegmentPath; var isParameter = current.StartsWith("{") && current.EndsWith("}"); var parameterName = current.TrimStart('{').TrimEnd('}'); var parameter = method.GetParameters().FirstOrDefault(x => x.Name == parameterName); if (parameter != null) { var argument = new RouteArgument(parameter, i); route.Segments[i] = argument; } if (isParameter && parameter == null) { throw new InvalidOperationException( $"Required parameter '{current}' could not be resoved in method {handlerType.FullNameInCode()}.{method.Name}()"); } } } var spreads = method.GetParameters().Where(x => x.IsSpread()).ToArray(); if (spreads.Length > 1) { throw new InvalidOperationException( $"An HTTP action method can only take in either '{JasperRoute.PathSegments}' or '{JasperRoute.RelativePath}', but not both. Error with action {handlerType.FullName}.{method.Name}()"); } if (spreads.Length == 1) { var spread = new Spread(route.Segments.Count, spreads.Single()); route.Segments.Add(spread); } method.ForAttribute <RouteNameAttribute>(att => route.Name = att.Name); return(route); }
public static Route Build(string pattern, Type handlerType, MethodInfo method) { pattern = pattern.Replace("___", "-").Replace("__", "_@"); var parts = pattern.Split('_') .Select(x => x.Replace("@", "_")).ToArray(); var verb = HttpVerbs.All.FirstOrDefault(x => x.EqualsIgnoreCase(parts[0])); if (verb.IsNotEmpty()) { parts = parts.Skip(1).ToArray(); } else { verb = HttpVerbs.GET; } var segments = parts .Select((x, position) => new Segment(x.ToLowerInvariant(), position)) .OfType <ISegment>() .ToArray(); if (SpecialClassNames.Contains(handlerType.Name) && SpecialMethodNames.ContainsKey(method.Name)) { pattern = "/"; verb = SpecialMethodNames[method.Name]; segments = new ISegment[0]; } Type inputType = DetermineInputType(method); var hasPrimitives = method.GetParameters().Any(x => x.ParameterType == typeof(string) || RoutingFrames.CanParse(x.ParameterType)); if (hasPrimitives) { for (var i = 0; i < segments.Length; i++) { var current = parts[i]; var parameter = method.GetParameters().FirstOrDefault(x => x.Name == current); if (parameter != null) { var argument = new RouteArgument(parameter, i); segments[i] = argument; } } } else if (inputType != null) { var members = inputType.GetProperties().OfType <MemberInfo>().Concat(inputType.GetFields()).ToArray(); for (var i = 0; i < segments.Length; i++) { var current = parts[i]; var member = members.FirstOrDefault(x => x.Name == current); if (member != null) { var argument = new RouteArgument(member, i); segments[i] = argument; } } } var spreads = method.GetParameters().Where(x => x.IsSpread()).ToArray(); if (spreads.Length > 1) { throw new InvalidOperationException($"An HTTP action method can only take in either '{Route.PathSegments}' or '{Route.RelativePath}', but not both. Error with action {handlerType.FullName}.{method.Name}()"); } if (spreads.Length == 1) { segments = segments.Concat(new ISegment[] { new Spread(segments.Length) }).ToArray(); } var route = new Route(segments, verb) { HandlerType = handlerType, Method = method, InputType = inputType }; method.ForAttribute <RouteNameAttribute>(att => route.Name = att.Name); return(route); }
public static Route Build(string pattern, Type handlerType, MethodInfo method) { pattern = pattern.Replace("___", "-").Replace("__", "_@"); var parts = pattern.Split('_') .Select(x => x.Replace("@", "_")).ToArray(); var verb = HttpVerbs.All.FirstOrDefault(x => x.EqualsIgnoreCase(parts[0])); if (verb.IsNotEmpty()) { parts = parts.Skip(1).ToArray(); } else { verb = HttpVerbs.GET; } var segments = parts .Select((x, position) => new Segment(x.ToLowerInvariant(), position)) .OfType <ISegment>() .ToArray(); if (SpecialClassNames.Contains(handlerType.Name) && SpecialMethodNames.ContainsKey(method.Name)) { pattern = "/"; verb = SpecialMethodNames[method.Name]; segments = new ISegment[0]; } // TODO -- eliminate the old Fubu input model routing? Type inputType = DetermineInputType(method); var hasPrimitives = method.GetParameters().Any(x => x.ParameterType == typeof(string) || RoutingFrames.CanParse(x.ParameterType)); if (hasPrimitives) { for (var i = 0; i < segments.Length; i++) { var current = parts[i]; var parameter = method.GetParameters().FirstOrDefault(x => x.Name == current); if (parameter != null) { var argument = new RouteArgument(parameter, i); segments[i] = argument; } } } else if (inputType != null) { var members = inputType.GetProperties().OfType <MemberInfo>().Concat(inputType.GetFields()).ToArray(); for (var i = 0; i < segments.Length; i++) { var current = parts[i]; var member = members.FirstOrDefault(x => x.Name == current); if (member != null) { var argument = new RouteArgument(member, i); segments[i] = argument; } } } var route = new Route(segments, verb) { HandlerType = handlerType, Method = method, InputType = inputType }; method.ForAttribute <RouteNameAttribute>(att => route.Name = att.Name); return(route); }
public static Route Build(RoutePattern pattern, Type handlerType, MethodInfo method) { var inputType = DetermineInputType(method); var hasPrimitives = method.GetParameters().Any(x => x.ParameterType == typeof(string) || RoutingFrames.CanParse(x.ParameterType)); if (hasPrimitives) { for (var i = 0; i < pattern.Segments.Length; i++) { var current = pattern.Segments[i].SegmentPath; var isParameter = current.StartsWith("{") && current.EndsWith("}"); var parameterName = current.TrimStart('{').TrimEnd('}'); var parameter = method.GetParameters().FirstOrDefault(x => x.Name == parameterName); if (parameter != null) { var argument = new RouteArgument(parameter, i); pattern.Segments[i] = argument; } if (isParameter && parameter == null) { throw new InvalidOperationException($"Required parameter '{current}' could not be resoved in method {handlerType.FullNameInCode()}.{method.Name}()"); } } } else if (inputType != null) { var members = inputType.GetProperties().OfType <MemberInfo>().Concat(inputType.GetFields()).ToArray(); for (var i = 0; i < pattern.Segments.Length; i++) { var current = pattern.Segments[i].SegmentPath; var member = members.FirstOrDefault(x => x.Name == current); if (member != null) { var argument = new RouteArgument(member, i); pattern.Segments[i] = argument; } } } var spreads = method.GetParameters().Where(x => x.IsSpread()).ToArray(); if (spreads.Length > 1) { throw new InvalidOperationException( $"An HTTP action method can only take in either '{Route.PathSegments}' or '{Route.RelativePath}', but not both. Error with action {handlerType.FullName}.{method.Name}()"); } var segments = pattern.Segments; if (spreads.Length == 1) { segments = segments.Concat(new ISegment[] { new Spread(segments.Length) }).ToArray(); } var route = new Route(segments, pattern.Method) { HandlerType = handlerType, Method = method, InputType = inputType }; method.ForAttribute <RouteNameAttribute>(att => route.Name = att.Name); return(route); }