예제 #1
0
        public void HasParameter_Returns_BooleanAsExpected()
        {
            // Arrange
            ActionModel action = _methodInfo.BuildActionModel();

            // Act & Assert
            Assert.False(action.HasParameter <int>("key"));
            Assert.True(action.HasParameter <int>("id"));
            Assert.False(action.HasParameter <string>("id"));
        }
예제 #2
0
        public void HasParameter_ThrowsArgumentNull_Action()
        {
            // Arrange & Act & Assert
            ActionModel action = null;

            ExceptionAssert.ThrowsArgumentNull(() => action.HasParameter <int>("key"), "action");
        }
예제 #3
0
        internal static bool ProcessNonNavigationProperty(string httpMethod, ODataControllerActionContext context,
                                                          ActionModel action,
                                                          IEdmNavigationSource navigationSource,
                                                          IEdmEntityType entityType, IEdmStructuredType castType)
        {
            // Action parameter should have a (string navigationProperty) parameter
            if (!action.HasParameter <string>("navigationProperty"))
            {
                return(false);
            }

            // Let's only handle single-key convention, for composite key, use attribute routing or non-generic navigation.
            bool hasRelatedKey = action.Parameters.Any(p => p.Name == "relatedKey"); // case sensitive?
            bool hasRelatedId  = action.Parameters.Any(p => p.Name == "relatedId");

            IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>();

            if (context.EntitySet != null)
            {
                segments.Add(new EntitySetSegmentTemplate(context.EntitySet));
                segments.Add(KeySegmentTemplate.CreateKeySegment(entityType, context.EntitySet));
            }
            else
            {
                segments.Add(new SingletonSegmentTemplate(context.Singleton));
            }

            if (entityType != castType)
            {
                segments.Add(new CastSegmentTemplate(castType, entityType, navigationSource));
            }

            if (hasRelatedKey)
            {
                segments.Add(new NavigationLinkTemplateSegmentTemplate(entityType, navigationSource)
                {
                    RelatedKey = "relatedKey"
                });
            }
            else if (hasRelatedId)
            {
                segments.Add(new NavigationLinkTemplateSegmentTemplate(entityType, navigationSource)
                {
                    RelatedKey = "relatedId"
                });
            }
            else
            {
                segments.Add(new NavigationLinkTemplateSegmentTemplate(entityType, navigationSource));
            }

            ODataPathTemplate template = new ODataPathTemplate(segments);

            action.AddSelector(httpMethod, context.Prefix, context.Model, template, context.Options?.RouteOptions);

            return(true);
        }
예제 #4
0
        /// <inheritdoc />
        public bool AppliesToAction(ODataControllerActionContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Debug.Assert(context.Action != null);

            ActionModel action           = context.Action;
            string      actionMethodName = action.ActionMethod.Name;

            // Need to refactor the following
            // for example:  CreateRef( with the navigation property parameter) should for all navigation properties
            // CreateRefToOrdersFromCustomer, CreateRefToOrders, CreateRef.
            string method = SplitRefActionName(actionMethodName, out string httpMethod, out string property, out string declaring);

            if (method == null)
            {
                return(false);
            }

            // Action parameter should have a (string navigationProperty) parameter
            if (!action.HasParameter <string>("navigationProperty"))
            {
                return(false);
            }

            IEdmNavigationSource navigationSource;
            IEdmEntityType       entityType;

            if (context.EntitySet != null)
            {
                entityType       = context.EntitySet.EntityType();
                navigationSource = context.EntitySet;
            }
            else
            {
                entityType       = context.Singleton.EntityType();
                navigationSource = context.Singleton;
            }

            // For entity set, we should have the key parameter
            // For Singleton, we should not have the key parameter
            bool hasODataKeyParameter = action.HasODataKeyParameter(entityType);

            if ((context.EntitySet != null && !hasODataKeyParameter) ||
                (context.Singleton != null && hasODataKeyParameter))
            {
                return(false);
            }

            // Find the navigation property declaring type
            IEdmStructuredType declaringType = entityType;

            if (declaring != null)
            {
                declaringType = entityType.FindTypeInInheritance(context.Model, declaring);
                if (declaringType == null)
                {
                    return(false);
                }
            }

            // Find the navigation property if have
            IEdmNavigationProperty navigationProperty = null;

            if (property != null)
            {
                navigationProperty = declaringType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == property);
                if (navigationProperty == null)
                {
                    return(false);
                }
            }

            IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>();

            if (context.EntitySet != null)
            {
                segments.Add(new EntitySetSegmentTemplate(context.EntitySet));
                segments.Add(new KeySegmentTemplate(entityType));
            }
            else
            {
                segments.Add(new SingletonSegmentTemplate(context.Singleton));
            }

            if (entityType != declaringType)
            {
                segments.Add(new CastSegmentTemplate(declaringType, entityType, navigationSource));
            }

            if (navigationProperty != null)
            {
                segments.Add(new NavigationSegmentTemplate(navigationProperty));
            }
            else
            {
                //TODO: Add the navigation template segment template,
                // Or add the template for all navigation properties?
                return(false);
            }

            IEdmEntityType navigationPropertyType            = navigationProperty.Type.GetElementTypeOrSelf().AsEntity().EntityDefinition();
            bool           hasNavigationPropertyKeyParameter = action.HasODataKeyParameter(navigationPropertyType, "relatedKey");

            if (hasNavigationPropertyKeyParameter)
            {
                segments.Add(new KeySegmentTemplate(navigationPropertyType, "relatedKey"));
            }

            IEdmNavigationSource targetNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, segments, out _);

            segments.Add(new RefSegmentTemplate(navigationProperty, targetNavigationSource));

            // TODO: support key as segment?
            ODataPathTemplate template = new ODataPathTemplate(segments);

            action.AddSelector(httpMethod, context.Prefix, context.Model, template);

            // processed
            return(true);
        }