Esempio n. 1
0
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches the pattern specified via attributes.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="action">The delegate executed when the endpoint is matched.</param>
        /// <returns>An <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static MapActionEndpointConventionBuilder MapAction(
            this IEndpointRouteBuilder endpoints,
            Delegate action)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var requestDelegate = MapActionExpressionTreeBuilder.BuildRequestDelegate(action);

            var routeAttributes    = action.Method.GetCustomAttributes().OfType <IRoutePatternMetadata>();
            var conventionBuilders = new List <IEndpointConventionBuilder>();

            const int defaultOrder = 0;

            foreach (var routeAttribute in routeAttributes)
            {
                if (routeAttribute.RoutePattern is not string pattern)
                {
                    continue;
                }

                var routeName  = (routeAttribute as IRouteNameMetadata)?.RouteName;
                var routeOrder = (routeAttribute as IRouteOrderMetadata)?.RouteOrder;

                var conventionBuilder = endpoints.Map(pattern, requestDelegate);

                conventionBuilder.Add(endpointBuilder =>
                {
                    foreach (var attribute in action.Method.GetCustomAttributes())
                    {
                        endpointBuilder.Metadata.Add(attribute);
                    }

                    endpointBuilder.DisplayName = routeName ?? pattern;

                    ((RouteEndpointBuilder)endpointBuilder).Order = routeOrder ?? defaultOrder;
                });

                conventionBuilders.Add(conventionBuilder);
            }

            if (conventionBuilders.Count == 0)
            {
                throw new InvalidOperationException("Action must have a pattern. Is it missing a Route attribute?");
            }

            return(new MapActionEndpointConventionBuilder(conventionBuilders));
        }
Esempio n. 2
0
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="action">The delegate executed when the endpoint is matched.</param>
        /// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static MapActionEndpointConventionBuilder Map(
            this IEndpointRouteBuilder endpoints,
            RoutePattern pattern,
            Delegate action)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (pattern is null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            const int defaultOrder = 0;

            var builder = new RouteEndpointBuilder(
                MapActionExpressionTreeBuilder.BuildRequestDelegate(action),
                pattern,
                defaultOrder)
            {
                DisplayName = pattern.RawText ?? pattern.DebuggerToString(),
            };

            // Add delegate attributes as metadata
            var attributes = action.Method.GetCustomAttributes();

            // This can be null if the delegate is a dynamic method or compiled from an expression tree
            if (attributes is not null)
            {
                foreach (var attribute in attributes)
                {
                    builder.Metadata.Add(attribute);
                }
            }

            var dataSource = endpoints.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new ModelEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }

            return(new MapActionEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)));
        }
Esempio n. 3
0
        private static MapActionEndpointConventionBuilder Map(
            this IEndpointRouteBuilder endpoints,
            RoutePattern pattern,
            Delegate action,
            string?displayName)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (pattern is null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            const int defaultOrder = 0;

            var builder = new RouteEndpointBuilder(
                MapActionExpressionTreeBuilder.BuildRequestDelegate(action),
                pattern,
                defaultOrder)
            {
                DisplayName = pattern.RawText ?? pattern.DebuggerToString(),
            };

            // Add delegate attributes as metadata
            var    attributes = action.Method.GetCustomAttributes();
            string?routeName  = null;
            int?   routeOrder = null;

            // This can be null if the delegate is a dynamic method or compiled from an expression tree
            if (attributes is not null)
            {
                foreach (var attribute in attributes)
                {
                    if (attribute is IRoutePatternMetadata patternMetadata && patternMetadata.RoutePattern is not null)
                    {
                        throw new InvalidOperationException($"'{attribute.GetType()}' implements {nameof(IRoutePatternMetadata)} which is not supported by this method.");
                    }
                    if (attribute is IHttpMethodMetadata methodMetadata && methodMetadata.HttpMethods.Any())
                    {
                        throw new InvalidOperationException($"'{attribute.GetType()}' implements {nameof(IHttpMethodMetadata)} which is not supported by this method.");
                    }

                    if (attribute is IRouteNameMetadata nameMetadata && nameMetadata.RouteName is string name)
                    {
                        routeName = name;
                    }
                    if (attribute is IRouteOrderMetadata orderMetadata && orderMetadata.RouteOrder is int order)
                    {
                        routeOrder = order;
                    }

                    builder.Metadata.Add(attribute);
                }
            }

            builder.DisplayName = routeName ?? displayName ?? builder.DisplayName;
            builder.Order       = routeOrder ?? defaultOrder;

            var dataSource = endpoints.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new ModelEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }

            return(new MapActionEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)));
        }