public static Type GetClrType(this IEdmModel edmModel, IEdmEntitySetBase entitySet)
        {
            IEdmEntityType entityType = entitySet.EntityType();

            edmModel = OeEdmClrHelper.GetEdmModel(edmModel, entityType);
            return(edmModel.GetAnnotationValue <Type>(entityType));
        }
Exemple #2
0
        public virtual async Task ExecuteResultAsync(ActionContext context)
        {
            var settings = new ODataMessageWriterSettings()
            {
                BaseUri = _odataUri.ServiceRoot,
                EnableMessageStreamDisposal = false,
                ODataUri    = _odataUri,
                Validations = ValidationKinds.ThrowIfTypeConflictsWithMetadata | ValidationKinds.ThrowOnDuplicatePropertyNames,
                Version     = ODataVersion.V4
            };

            var requestHeaders = OeRequestHeaders.Parse(context.HttpContext.Request.Headers["Accept"], context.HttpContext.Request.Headers["Prefer"]);

            if (requestHeaders.MaxPageSize > 0 && PageSize == 0)
            {
                PageSize = requestHeaders.MaxPageSize;
            }

            IODataResponseMessage responseMessage = new Infrastructure.OeInMemoryMessage(context.HttpContext.Response.Body, context.HttpContext.Request.ContentType);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, _edmModel))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet);

                IEdmEntityType entityType = _resultEntitySet.EntityType();
                ODataWriter    writer     = messageWriter.CreateODataResourceSetWriter(_resultEntitySet, entityType);
                await SerializeAsync(writer, requestHeaders.MetadataLevel);
            }
        }
Exemple #3
0
        public static Type GetClrType(this IEdmModel edmModel, IEdmEntitySetBase entitySet)
        {
            IEdmEntityType           entityType        = entitySet.EntityType();
            OeValueAnnotation <Type> clrTypeAnnotation = edmModel.GetAnnotationValue <OeValueAnnotation <Type> >(entityType);

            return(clrTypeAnnotation.Value);
        }
Exemple #4
0
        public static Type GetClrType(this IEdmModel edmModel, IEdmEntitySetBase entitySet)
        {
            IEdmEntityType entityType = entitySet.EntityType();
            IEdmModel?     model      = OeEdmClrHelper.GetEdmModel(edmModel, entityType);

            if (model == null)
            {
                throw new InvalidOperationException("Add type annotation for " + entityType.FullTypeName());
            }
            return(model.GetAnnotationValue <Type>(entityType));
        }
Exemple #5
0
        private OeEntryFactory(IEdmEntitySetBase entitySet, OePropertyAccessor[] accessors)
        {
            Array.Sort(accessors, AccessorByNameComparer.Instance);
            EntitySet     = entitySet;
            _allAccessors = accessors;
            Accessors     = GetAccessorsWithoutSkiptoken(accessors);

            EntityType      = entitySet.EntityType();
            NavigationLinks = Array.Empty <OeEntryFactory>();
            _typeName       = EntityType.FullName();
        }
Exemple #6
0
        public static                          OePropertyAccessor[] CreateFromExpression(Expression source, ParameterExpression parameter, IEdmEntitySetBase entitySet)
        {
            var propertyAccessors = new List <OePropertyAccessor>();

            foreach (IEdmStructuralProperty edmProperty in entitySet.EntityType().StructuralProperties())
            {
                MemberExpression expression = Expression.Property(source, source.Type.GetProperty(edmProperty.Name));
                propertyAccessors.Add(CreatePropertyAccessor(edmProperty, expression, parameter));
            }
            return(propertyAccessors.ToArray());
        }
Exemple #7
0
        public static                          OePropertyAccessor[] CreateFromType(Type clrType, IEdmEntitySetBase entitySet)
        {
            ParameterExpression parameter = Expression.Parameter(typeof(Object));
            UnaryExpression     instance  = Expression.Convert(parameter, clrType);
            var propertyAccessors         = new List <OePropertyAccessor>();

            foreach (IEdmStructuralProperty edmProperty in entitySet.EntityType().StructuralProperties())
            {
                MemberExpression expression = Expression.Property(instance, clrType.GetProperty(edmProperty.Name));
                propertyAccessors.Add(CreatePropertyAccessor(edmProperty, expression, parameter, false));
            }
            return(propertyAccessors.ToArray());
        }
Exemple #8
0
        internal static OrderByClause GetUniqueOrderBy(IEdmEntitySetBase entitySet, OrderByClause orderByClause, ApplyClause applyClause)
        {
            if (orderByClause != null && applyClause == null && GetIsKey(entitySet.EntityType(), GetEdmProperies(orderByClause)))
            {
                return(orderByClause);
            }

            List <SingleValuePropertyAccessNode> orderByProperties = GetOrderByProperties(entitySet, orderByClause, applyClause);

            if (orderByProperties.Count == 0)
            {
                return(orderByClause ?? throw new InvalidOperationException("orderByClause must not null"));
            }

            OrderByClause uniqueOrderByClause = null;

            for (int i = orderByProperties.Count - 1; i >= 0; i--)
            {
                ResourceRangeVariableReferenceNode source;
                if (orderByProperties[i].Source is SingleNavigationNode navigationNode)
                {
                    source = (ResourceRangeVariableReferenceNode)navigationNode.Source;
                }
                else
                {
                    source = (ResourceRangeVariableReferenceNode)orderByProperties[i].Source;
                }
                uniqueOrderByClause = new OrderByClause(uniqueOrderByClause, orderByProperties[i], OrderByDirection.Ascending, source.RangeVariable);
            }

            if (orderByClause == null)
            {
                return(uniqueOrderByClause);
            }

            var orderByClauses = new Stack <OrderByClause>();

            do
            {
                orderByClauses.Push(orderByClause);
                orderByClause = orderByClause.ThenBy;
            }while (orderByClause != null);

            while (orderByClauses.Count > 0)
            {
                orderByClause       = orderByClauses.Pop();
                uniqueOrderByClause = new OrderByClause(uniqueOrderByClause, orderByClause.Expression, orderByClause.Direction, orderByClause.RangeVariable);
            }

            return(uniqueOrderByClause);
        }
Exemple #9
0
        public OeEntryFactory(IEdmEntitySetBase entitySet, OePropertyAccessor[] accessors, OePropertyAccessor[] skipTokenAccessors)
        {
            Array.Sort(accessors, AccessorByNameComparer.Instance);
            EntitySet          = entitySet;
            _allAccessors      = accessors;
            Accessors          = GetAccessorsWithoutSkiptoken(accessors);
            SkipTokenAccessors = skipTokenAccessors;

            EdmEntityType   = entitySet.EntityType();
            NavigationLinks = Array.Empty <OeEntryFactory>();
            _typeName       = EdmEntityType.FullName();

            IsTuple = accessors.Length == 0 ? false : OeExpressionHelper.IsTupleType(accessors[0].PropertyExpression.Expression.Type);
        }
Exemple #10
0
        public static                                                                                  OePropertyAccessor[] CreateFromType(Type clrType, IEdmEntitySetBase entitySet)
        {
            ParameterExpression parameter = Expression.Parameter(typeof(Object));
            UnaryExpression     instance  = Expression.Convert(parameter, clrType);
            var propertyAccessors         = new List <OePropertyAccessor>();

            if (typeof(OeIndexerProperty).IsAssignableFrom(clrType))
            {
                InterfaceMapping interfaceMapping = clrType.GetInterfaceMap(typeof(OeIndexerProperty));
                foreach (IEdmStructuralProperty edmProperty in entitySet.EntityType().StructuralProperties())
                {
                    MethodCallExpression expression = Expression.Call(instance, interfaceMapping.TargetMethods[0], Expression.Constant(edmProperty.Name));
                    propertyAccessors.Add(CreatePropertyAccessor(edmProperty, expression, parameter, false));
                }
            }
            else
            {
                foreach (IEdmStructuralProperty edmProperty in entitySet.EntityType().StructuralProperties())
                {
                    PropertyInfo?propertyInfo = clrType.GetPropertyIgnoreCaseOrNull(edmProperty);
                    if (propertyInfo == null)
                    {
                        if (!(edmProperty is OeEdmStructuralShadowProperty))
                        {
                            throw new InvalidOperationException("Property " + edmProperty.Name + " not found in clr type " + clrType.Name);
                        }
                    }
                    else
                    {
                        MemberExpression expression = Expression.Property(instance, propertyInfo);
                        propertyAccessors.Add(CreatePropertyAccessor(edmProperty, expression, parameter, false));
                    }
                }
            }
            return(propertyAccessors.ToArray());
        }
        public static Uri ComputeId(Uri baseUri, IEdmEntitySetBase entitySet, ODataResource entry)
        {
            Uri uri     = AppendSegment(baseUri, entitySet.Name, true);
            var builder = new StringBuilder(uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.OriginalString);

            builder.Append('(');

            using (IEnumerator <IEdmStructuralProperty> enumerator = entitySet.EntityType().Key().GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    throw new InvalidOperationException("Key property not found for EntityType " + entitySet.EntityType().FullName());
                }

                IEdmStructuralProperty keyProperty = enumerator.Current;
                if (enumerator.MoveNext())
                {
                    int counter = 0;
                    do
                    {
                        ODataProperty property = GetProperty(entry, keyProperty.Name);
                        builder.Append(property.Name);
                        builder.Append('=');
                        builder.Append(ODataUriUtils.ConvertToUriLiteral(property.Value, ODataVersion.V4));

                        if (counter == 0 || enumerator.MoveNext())
                        {
                            keyProperty = enumerator.Current;
                            builder.Append(',');
                            counter = 1;
                        }
                        else
                        {
                            counter = 2;
                        }
                    }while (counter < 2);
                }
                else
                {
                    ODataProperty property = GetProperty(entry, keyProperty.Name);
                    builder.Append(ODataUriUtils.ConvertToUriLiteral(property.Value, ODataVersion.V4));
                }
            }

            builder.Append(')');
            return(new Uri(builder.ToString(), UriKind.Absolute));
        }
Exemple #12
0
        public static Uri ComputeId(Uri baseUri, IEdmEntitySetBase entitySet, ODataResource entry)
        {
            Uri uri     = AppendSegment(baseUri, entitySet.Name, true);
            var builder = new StringBuilder(uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.OriginalString);

            builder.Append('(');

            IEnumerable <IEdmStructuralProperty> keyProperties = entitySet.EntityType().Key();

            using (IEnumerator <IEdmStructuralProperty> enumerator = keyProperties.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    return(null);
                }

                IEdmStructuralProperty keyProperty = enumerator.Current;
                if (enumerator.MoveNext())
                {
                    int counter = 0;
                    while (keyProperty != null)
                    {
                        ODataProperty property = GetProperty(entry, keyProperty.Name);
                        builder.Append(property.Name);
                        builder.Append('=');
                        builder.Append(ODataUriUtils.ConvertToUriLiteral(property.Value, ODataVersion.V4));

                        keyProperty = counter == 0 || enumerator.MoveNext() ? enumerator.Current : null;
                        if (keyProperty != null)
                        {
                            builder.Append(',');
                        }

                        counter++;
                    }
                }
                else
                {
                    ODataProperty property = GetProperty(entry, keyProperty.Name);
                    builder.Append(ODataUriUtils.ConvertToUriLiteral(property.Value, ODataVersion.V4));
                }
            }

            builder.Append(')');
            return(new Uri(builder.ToString(), UriKind.Absolute));
        }
Exemple #13
0
        private static List <SingleValuePropertyAccessNode> GetOrderByProperties(IEdmEntitySetBase entitySet, OrderByClause?orderByClause, ApplyClause?applyClause)
        {
            var keys = new List <SingleValuePropertyAccessNode>();
            GroupByTransformationNode groupByNode;

            if (applyClause != null && (groupByNode = applyClause.Transformations.OfType <GroupByTransformationNode>().SingleOrDefault()) != null)
            {
                foreach (GroupByPropertyNode node in groupByNode.GroupingProperties)
                {
                    if (node.Expression == null)
                    {
                        keys.AddRange(node.ChildTransformations.Select(n => (SingleValuePropertyAccessNode)n.Expression));
                    }
                    else
                    {
                        keys.Add((SingleValuePropertyAccessNode)node.Expression);
                    }
                }
            }
            else
            {
                ResourceRangeVariableReferenceNode source = OeEdmClrHelper.CreateRangeVariableReferenceNode(entitySet);
                foreach (IEdmStructuralProperty key in entitySet.EntityType().Key())
                {
                    keys.Add(new SingleValuePropertyAccessNode(source, key));
                }
            }

            if (orderByClause == null)
            {
                return(keys);
            }

            for (; orderByClause != null; orderByClause = orderByClause.ThenBy)
            {
                if (orderByClause.Expression is SingleValuePropertyAccessNode propertyNode)
                {
                    int i = keys.FindIndex(p => p.Property == propertyNode.Property);
                    if (i >= 0)
                    {
                        keys.RemoveAt(i);
                    }
                }
            }
            return(keys);
        }
        private OeEntryFactory(IEdmEntitySetBase entitySet, OePropertyAccessor[] accessors)
        {
            _entitySet = entitySet;
            _accessors = accessors;

            _entityType      = entitySet.EntityType();
            _navigationLinks = Array.Empty <OeEntryFactory>();
            _typeName        = EntityType.FullName();

            _odataProperties = new ODataProperty[accessors.Length];
            for (int i = 0; i < accessors.Length; i++)
            {
                _odataProperties[i] = new ODataProperty()
                {
                    Name = accessors[i].Name
                }
            }
            ;
        }
Exemple #15
0
        public static Uri ComputeId(Uri baseUri, IEdmEntitySetBase entitySet, ODataResource entry)
        {
            Uri uri     = AppendSegment(baseUri, entitySet.Name, true);
            var builder = new StringBuilder(uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.OriginalString);

            builder.Append('(');
            bool flag = true;

            IEnumerable <IEdmStructuralProperty> keyProperties = entitySet.EntityType().Key();

            foreach (IEdmStructuralProperty keyProperty in keyProperties)
            {
                ODataProperty property = null;
                foreach (ODataProperty entryProperty in entry.Properties)
                {
                    if (entryProperty.Name == keyProperty.Name)
                    {
                        property = entryProperty;
                        break;
                    }
                }

                if (flag)
                {
                    flag = false;
                }
                else
                {
                    builder.Append(',');
                }
                if (keyProperties.Count() > 1)
                {
                    builder.Append(property.Name);
                    builder.Append('=');
                }

                builder.Append(ODataUriUtils.ConvertToUriLiteral(property.Value, ODataVersion.V4));
            }
            builder.Append(')');

            return(new Uri(builder.ToString(), UriKind.Absolute));
        }
        public OeEntryFactory(
            IEdmEntitySetBase entitySet,
            OePropertyAccessor[] accessors,
            OePropertyAccessor[]?skipTokenAccessors)
        {
            Array.Sort(accessors, AccessorByNameComparer.Instance);
            EntitySet          = entitySet;
            _allAccessors      = accessors;
            Accessors          = GetAccessorsWithoutSkiptoken(accessors);
            SkipTokenAccessors = skipTokenAccessors ?? Array.Empty <OePropertyAccessor>();

            EdmEntityType   = entitySet.EntityType();
            NavigationLinks = Array.Empty <OeNavigationEntryFactory>();
            _typeName       = EdmEntityType.FullName();

            if (accessors.Length != 0 && accessors[0].PropertyExpression is MemberExpression propertyExpression)
            {
                IsTuple = OeExpressionHelper.IsTupleType(propertyExpression.Expression !.Type);
            }
        }
        public BatchReferenceSegment(string contentId, IEdmType edmType, IEdmEntitySetBase entitySet)
        {
            ExceptionUtils.CheckArgumentNotNull(edmType, "resultingType");
            ExceptionUtils.CheckArgumentNotNull(contentId, "contentId");
            if (!ODataPathParser.ContentIdRegex.IsMatch(contentId))
            {
                throw new ODataException(ODataErrorStrings.BatchReferenceSegment_InvalidContentID(contentId));
            }

            this.edmType   = edmType;
            this.entitySet = entitySet;
            this.contentId = contentId;

            this.Identifier                = this.ContentId;
            this.TargetEdmType             = edmType;
            this.TargetEdmNavigationSource = this.EntitySet;
            this.SingleResult              = true;
            this.TargetKind                = RequestTargetKind.Resource;

            if (entitySet != null)
            {
                UriParserErrorHelper.ThrowIfTypesUnrelated(edmType, entitySet.EntityType(), "BatchReferenceSegments");
            }
        }
Exemple #18
0
        private static List <MemberExpression> GetKeyExpressions(IEdmEntitySetBase entitySet, OePropertyAccessor[] accessors)
        {
            var propertyExpressions = new List <MemberExpression>();

            foreach (IEdmStructuralProperty key in entitySet.EntityType().Key())
            {
                bool found = false;
                foreach (OePropertyAccessor accessor in accessors)
                {
                    if (String.CompareOrdinal(accessor.EdmProperty.Name, key.Name) == 0)
                    {
                        propertyExpressions.Add(accessor.PropertyExpression);
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    throw new InvalidOperationException("Key property " + key.Name + " not found in accessors");
                }
            }
            return(propertyExpressions);
        }
        public static                          OePropertyAccessor[] CreateFromType(Type clrType, IEdmEntitySetBase entitySet)
        {
            ParameterExpression parameter = Expression.Parameter(typeof(Object));
            UnaryExpression     instance  = Expression.Convert(parameter, clrType);
            var propertyAccessors         = new List <OePropertyAccessor>();

            foreach (IEdmStructuralProperty edmProperty in entitySet.EntityType().StructuralProperties())
            {
                PropertyInfo propertyInfo = clrType.GetProperty(edmProperty.Name);
                if (propertyInfo == null)
                {
                    if (!(edmProperty is OeEdmStructuralProperty))
                    {
                        throw new InvalidOperationException("Property " + edmProperty.Name + " not found in clr type " + clrType.Name);
                    }
                }
                else
                {
                    MemberExpression expression = Expression.Property(instance, propertyInfo);
                    propertyAccessors.Add(CreatePropertyAccessor(edmProperty, expression, parameter, false));
                }
            }
            return(propertyAccessors.ToArray());
        }
        /// <summary>
        /// Selects the action for OData requests.
        /// </summary>
        /// <param name="odataPath">The OData path.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionMap">The action map.</param>
        /// <returns>
        ///   <c>null</c> if the request isn't handled by this convention; otherwise, the name of the selected action
        /// </returns>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            if (odataPath.PathTemplate == "~/entityset")
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;
                HttpMethod        httpMethod       = controllerContext.Request.Method;

                if (httpMethod == HttpMethod.Get)
                {
                    // e.g. Try GetCustomers first, then fall back to Get action name
                    return(actionMap.FindMatchingAction(
                               "Get" + entitySet.Name,
                               "Get"));
                }
                else if (httpMethod == HttpMethod.Post)
                {
                    // e.g. Try PostCustomer first, then fall back to Post action name
                    return(actionMap.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name,
                               "Post"));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/$count" &&
                     controllerContext.Request.Method == HttpMethod.Get)
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                // e.g. Try GetCustomers first, then fall back to Get action name
                return(actionMap.FindMatchingAction(
                           "Get" + entitySet.Name,
                           "Get"));
            }
            else if (odataPath.PathTemplate == "~/entityset/cast")
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;
                HttpMethod         httpMethod       = controllerContext.Request.Method;

                if (httpMethod == HttpMethod.Get)
                {
                    // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                    return(actionMap.FindMatchingAction(
                               "Get" + entitySet.Name + "From" + entityType.Name,
                               "GetFrom" + entityType.Name));
                }
                else if (httpMethod == HttpMethod.Post)
                {
                    // e.g. Try PostCustomerFromSpecialCustomer first, then fall back to PostFromSpecialCustomer
                    return(actionMap.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name + "From" + entityType.Name,
                               "PostFrom" + entityType.Name));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/cast/$count" &&
                     controllerContext.Request.Method == HttpMethod.Get)
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.Segments[1].EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                return(actionMap.FindMatchingAction(
                           "Get" + entitySet.Name + "From" + entityType.Name,
                           "GetFrom" + entityType.Name));
            }

            return(null);
        }
Exemple #21
0
        private object ProcessPostBody(IODataRequestMessage message, IEdmEntitySetBase entitySet, object queryResults)
        {
            object lastNewInstance = null;

            using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings(), this.DataSource.Model))
            {
                var odataItemStack = new Stack<ODataItem>();
                var entryReader = messageReader.CreateODataEntryReader(entitySet, entitySet.EntityType());
                var currentTargetEntitySet = entitySet;

                while (entryReader.Read())
                {
                    switch (entryReader.State)
                    {
                        case ODataReaderState.EntryStart:
                            odataItemStack.Push(entryReader.Item);
                            break;

                        case ODataReaderState.EntryEnd:
                            {
                                var entry = (ODataEntry)entryReader.Item;

                                // TODO: the code here will be changed to handle following scenarios
                                //       1: non-contained navigation, e.g. People(1)/Friends
                                //       2. general entity set, e.g. People
                                //       3. contained navigation, e.g. People(1)/Trips
                                //       4. upsert, e.g. People(1)/Friends(2)
                                var newInstance = this.DataSource.UpdateProvider.Create(entry.TypeName, queryResults);

                                foreach (var property in entry.Properties)
                                {
                                    if (Utility.IsETagProperty(newInstance, property.Name)) continue;
                                    this.DataSource.UpdateProvider.Update(newInstance, property.Name, property.Value);
                                }

                                var boundNavPropAnnotation = odataItemStack.Pop().GetAnnotation<BoundNavigationPropertyAnnotation>();
                                if (boundNavPropAnnotation != null)
                                {
                                    foreach (var boundProperty in boundNavPropAnnotation.BoundProperties)
                                    {
                                        var isCollection = boundProperty.Item1.IsCollection == true;
                                        var propertyValue = isCollection ? boundProperty.Item2 : ((IEnumerable<object>)boundProperty.Item2).Single();
                                        this.DataSource.UpdateProvider.Update(newInstance, boundProperty.Item1.Name, propertyValue);
                                    }
                                }

                                var parentItem = odataItemStack.Count > 0 ? odataItemStack.Peek() : null;
                                if (parentItem != null)
                                {
                                    // This new entry belongs to a navigation property and/or feed -
                                    // propagate it up the tree for further processing.
                                    AddChildInstanceAnnotation(parentItem, newInstance);
                                }

                                lastNewInstance = newInstance;
                            }

                            break;

                        case ODataReaderState.FeedStart:
                            odataItemStack.Push(entryReader.Item);
                            break;

                        case ODataReaderState.FeedEnd:
                            {
                                var childAnnotation = odataItemStack.Pop().GetAnnotation<ChildInstanceAnnotation>();

                                var parentNavLink = odataItemStack.Count > 0 ? odataItemStack.Peek() as ODataNavigationLink : null;
                                if (parentNavLink != null)
                                {
                                    // This feed belongs to a navigation property -
                                    // propagate it up the tree for further processing.
                                    AddChildInstanceAnnotation(parentNavLink, childAnnotation.ChildInstances ?? new object[0]);
                                }
                            }

                            break;

                        case ODataReaderState.NavigationLinkStart:
                            {
                                odataItemStack.Push(entryReader.Item);
                                var navigationLink = (ODataNavigationLink)entryReader.Item;
                                var navigationProperty = (IEdmNavigationProperty)currentTargetEntitySet.EntityType().FindProperty(navigationLink.Name);

                                // Current model implementation doesn't expose associations otherwise this would be much cleaner.
                                currentTargetEntitySet = this.DataSource.Model.EntityContainer.EntitySets().Single(s => s.EntityType() == navigationProperty.Type.Definition);
                            }

                            break;

                        case ODataReaderState.NavigationLinkEnd:
                            {
                                var navigationLink = (ODataNavigationLink)entryReader.Item;
                                var childAnnotation = odataItemStack.Pop().GetAnnotation<ChildInstanceAnnotation>();
                                if (childAnnotation != null)
                                {
                                    // Propagate the bound entries to the parent entry.
                                    AddBoundNavigationPropertyAnnotation(odataItemStack.Peek(), navigationLink, childAnnotation.ChildInstances);
                                }
                            }

                            break;
                    }
                }
            }

            return lastNewInstance;
        }
Exemple #22
0
        private object ProcessPostBody(IODataRequestMessage message, IEdmEntitySetBase entitySet, object queryResults)
        {
            object lastNewInstance = null;

            using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings(), this.DataSource.Model))
            {
                var odataItemStack         = new Stack <ODataItem>();
                var entryReader            = messageReader.CreateODataEntryReader(entitySet, entitySet.EntityType());
                var currentTargetEntitySet = entitySet;

                while (entryReader.Read())
                {
                    switch (entryReader.State)
                    {
                    case ODataReaderState.EntryStart:
                        odataItemStack.Push(entryReader.Item);
                        break;

                    case ODataReaderState.EntryEnd:
                    {
                        var entry = (ODataEntry)entryReader.Item;

                        // TODO: the code here will be changed to handle following scenarios
                        //       1: non-contained navigation, e.g. People(1)/Friends
                        //       2. general entity set, e.g. People
                        //       3. contained navigation, e.g. People(1)/Trips
                        //       4. upsert, e.g. People(1)/Friends(2)
                        var newInstance = this.DataSource.UpdateProvider.Create(entry.TypeName, queryResults);

                        foreach (var property in entry.Properties)
                        {
                            if (Utility.IsETagProperty(newInstance, property.Name))
                            {
                                continue;
                            }
                            this.DataSource.UpdateProvider.Update(newInstance, property.Name, property.Value);
                        }

                        var boundNavPropAnnotation = odataItemStack.Pop().GetAnnotation <BoundNavigationPropertyAnnotation>();
                        if (boundNavPropAnnotation != null)
                        {
                            foreach (var boundProperty in boundNavPropAnnotation.BoundProperties)
                            {
                                var isCollection  = boundProperty.Item1.IsCollection == true;
                                var propertyValue = isCollection ? boundProperty.Item2 : ((IEnumerable <object>)boundProperty.Item2).Single();
                                this.DataSource.UpdateProvider.Update(newInstance, boundProperty.Item1.Name, propertyValue);
                            }
                        }

                        var parentItem = odataItemStack.Count > 0 ? odataItemStack.Peek() : null;
                        if (parentItem != null)
                        {
                            // This new entry belongs to a navigation property and/or feed -
                            // propagate it up the tree for further processing.
                            AddChildInstanceAnnotation(parentItem, newInstance);
                        }

                        lastNewInstance = newInstance;
                    }

                    break;

                    case ODataReaderState.FeedStart:
                        odataItemStack.Push(entryReader.Item);
                        break;

                    case ODataReaderState.FeedEnd:
                    {
                        var childAnnotation = odataItemStack.Pop().GetAnnotation <ChildInstanceAnnotation>();

                        var parentNavLink = odataItemStack.Count > 0 ? odataItemStack.Peek() as ODataNavigationLink : null;
                        if (parentNavLink != null)
                        {
                            // This feed belongs to a navigation property -
                            // propagate it up the tree for further processing.
                            AddChildInstanceAnnotation(parentNavLink, childAnnotation.ChildInstances ?? new object[0]);
                        }
                    }

                    break;

                    case ODataReaderState.NavigationLinkStart:
                    {
                        odataItemStack.Push(entryReader.Item);
                        var navigationLink     = (ODataNavigationLink)entryReader.Item;
                        var navigationProperty = (IEdmNavigationProperty)currentTargetEntitySet.EntityType().FindProperty(navigationLink.Name);

                        // Current model implementation doesn't expose associations otherwise this would be much cleaner.
                        currentTargetEntitySet = this.DataSource.Model.EntityContainer.EntitySets().Single(s => s.EntityType() == navigationProperty.Type.Definition);
                    }

                    break;

                    case ODataReaderState.NavigationLinkEnd:
                    {
                        var navigationLink  = (ODataNavigationLink)entryReader.Item;
                        var childAnnotation = odataItemStack.Pop().GetAnnotation <ChildInstanceAnnotation>();
                        if (childAnnotation != null)
                        {
                            // Propagate the bound entries to the parent entry.
                            AddBoundNavigationPropertyAnnotation(odataItemStack.Peek(), navigationLink, childAnnotation.ChildInstances);
                        }
                    }

                    break;
                    }
                }
            }

            return(lastNewInstance);
        }
        /// <inheritdoc/>
        public override ActionDescriptor SelectAction(RouteContext routeContext, IEnumerable <ControllerActionDescriptor> actionDescriptors)
        {
            if (routeContext == null)
            {
                throw Error.ArgumentNull("routeContext");
            }

            ODataPath   odataPath  = routeContext.HttpContext.Request.ODataFeature().Path;
            HttpRequest request    = routeContext.HttpContext.Request;
            string      httpMethod = request.Method.ToUpperInvariant();

            if (odataPath.PathTemplate == "~/entityset")
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                if (httpMethod == ODataRouteConstants.HttpGet)
                {
                    // e.g. Try GetCustomers first, then fall back to Get action name
                    return(actionDescriptors.FindMatchingAction(
                               "Get" + entitySet.Name,
                               "Get"));
                }
                else if (httpMethod == ODataRouteConstants.HttpPost)
                {
                    // e.g. Try PostCustomer first, then fall back to Post action name
                    return(actionDescriptors.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name,
                               "Post"));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/$count" &&
                     httpMethod == ODataRouteConstants.HttpGet)
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                // e.g. Try GetCustomers first, then fall back to Get action name
                return(actionDescriptors.FindMatchingAction(
                           "Get" + entitySet.Name,
                           "Get"));
            }
            else if (odataPath.PathTemplate == "~/entityset/cast")
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                if (httpMethod == ODataRouteConstants.HttpGet)
                {
                    // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                    return(actionDescriptors.FindMatchingAction(
                               "Get" + entitySet.Name + "From" + entityType.Name,
                               "GetFrom" + entityType.Name));
                }
                else if (httpMethod == ODataRouteConstants.HttpPost)
                {
                    // e.g. Try PostCustomerFromSpecialCustomer first, then fall back to PostFromSpecialCustomer
                    return(actionDescriptors.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name + "From" + entityType.Name,
                               "PostFrom" + entityType.Name));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/cast/$count" &&
                     httpMethod == ODataRouteConstants.HttpGet)
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.Segments[1].EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                return(actionDescriptors.FindMatchingAction(
                           "Get" + entitySet.Name + "From" + entityType.Name,
                           "GetFrom" + entityType.Name));
            }

            return(null);
        }
        private string SelectActionImpl(RouteContext routeContext, SelectControllerResult controllerResult, IEnumerable <ControllerActionDescriptor> actionDescriptors)
        {
            Microsoft.AspNet.OData.Routing.ODataPath odataPath = routeContext.HttpContext.ODataFeature().Path;
            HttpRequest request = routeContext.HttpContext.Request;

            if (odataPath.PathTemplate == "~/entityset")
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                if (HttpMethods.IsGet(request.Method))
                {
                    // e.g. Try GetCustomers first, then fall back to Get action name
                    return(actionDescriptors.FindMatchingAction(
                               "Get" + entitySet.Name,
                               "Get"));
                }
                else if (HttpMethods.IsPost(request.Method))
                {
                    // e.g. Try PostCustomer first, then fall back to Post action name
                    return(actionDescriptors.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name,
                               "Post"));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/key" ||
                     odataPath.PathTemplate == "~/entityset/key/cast")
            {
                string httpMethodName;

                if (HttpMethods.IsGet(request.Method))
                {
                    httpMethodName = "Get";
                }
                else if (HttpMethods.IsPut(request.Method))
                {
                    httpMethodName = "Put";
                }
                else if (HttpMethods.IsPatch(request.Method))
                {
                    httpMethodName = "Patch";
                }
                else if (HttpMethods.IsDelete(request.Method))
                {
                    httpMethodName = "Delete";
                }
                else
                {
                    return(null);
                }

                Contract.Assert(httpMethodName != null);

                IEdmEntityType entityType = (IEdmEntityType)odataPath.EdmType;

                // e.g. Try GetCustomer first, then fallback on Get action name
                string actionName = actionDescriptors.FindMatchingAction(
                    httpMethodName + entityType.Name,
                    httpMethodName);

                if (actionName != null)
                {
                    KeySegment keySegment = (KeySegment)odataPath.Segments[1];
                    // TODO: Add key/value to RouteData
                    return(actionName);
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/$count" &&
                     HttpMethods.IsGet(request.Method))
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                // e.g. Try GetCustomers first, then fall back to Get action name
                return(actionDescriptors.FindMatchingAction(
                           "Get" + entitySet.Name,
                           "Get"));
            }
            else if (odataPath.PathTemplate == "~/entityset/cast")
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                if (HttpMethods.IsGet(request.Method))
                {
                    // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                    return(actionDescriptors.FindMatchingAction(
                               "Get" + entitySet.Name + "From" + entityType.Name,
                               "GetFrom" + entityType.Name));
                }
                else if (HttpMethods.IsPost(request.Method))
                {
                    // e.g. Try PostCustomerFromSpecialCustomer first, then fall back to PostFromSpecialCustomer
                    return(actionDescriptors.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name + "From" + entityType.Name,
                               "PostFrom" + entityType.Name));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/cast/$count" &&
                     HttpMethods.IsGet(request.Method))
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.Segments[1].EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                return(actionDescriptors.FindMatchingAction(
                           "Get" + entitySet.Name + "From" + entityType.Name,
                           "GetFrom" + entityType.Name));
            }

            return(null);
        }
        /// <summary>
        /// Selects the action for OData requests.
        /// </summary>
        /// <param name="odataPath">The OData path.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionMap">The action map.</param>
        /// <returns>
        ///   <c>null</c> if the request isn't handled by this convention; otherwise, the name of the selected action
        /// </returns>
        internal static string SelectActionImpl(ODataPath odataPath, IWebApiControllerContext controllerContext, IWebApiActionMap actionMap)
        {
            if (odataPath.PathTemplate == "~/entityset")
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                if (ODataRequestMethod.Get == controllerContext.Request.GetRequestMethodOrPreflightMethod())
                {
                    // e.g. Try GetCustomers first, then fall back to Get action name
                    return(actionMap.FindMatchingAction(
                               "Get" + entitySet.Name,
                               "Get"));
                }
                else if (ODataRequestMethod.Post == controllerContext.Request.GetRequestMethodOrPreflightMethod())
                {
                    // e.g. Try PostCustomer first, then fall back to Post action name
                    return(actionMap.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name,
                               "Post"));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/$count" &&
                     ODataRequestMethod.Get == controllerContext.Request.GetRequestMethodOrPreflightMethod())
            {
                EntitySetSegment  entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase entitySet        = entitySetSegment.EntitySet;

                // e.g. Try GetCustomers first, then fall back to Get action name
                return(actionMap.FindMatchingAction(
                           "Get" + entitySet.Name,
                           "Get"));
            }
            else if (odataPath.PathTemplate == "~/entityset/cast")
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                if (ODataRequestMethod.Get == controllerContext.Request.GetRequestMethodOrPreflightMethod())
                {
                    // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                    return(actionMap.FindMatchingAction(
                               "Get" + entitySet.Name + "From" + entityType.Name,
                               "GetFrom" + entityType.Name));
                }
                else if (ODataRequestMethod.Post == controllerContext.Request.GetRequestMethodOrPreflightMethod())
                {
                    // e.g. Try PostCustomerFromSpecialCustomer first, then fall back to PostFromSpecialCustomer
                    return(actionMap.FindMatchingAction(
                               "Post" + entitySet.EntityType().Name + "From" + entityType.Name,
                               "PostFrom" + entityType.Name));
                }
            }
            else if (odataPath.PathTemplate == "~/entityset/cast/$count" &&
                     ODataRequestMethod.Get == controllerContext.Request.GetRequestMethodOrPreflightMethod())
            {
                EntitySetSegment   entitySetSegment = (EntitySetSegment)odataPath.Segments[0];
                IEdmEntitySetBase  entitySet        = entitySetSegment.EntitySet;
                IEdmCollectionType collectionType   = (IEdmCollectionType)odataPath.Segments[1].EdmType;
                IEdmEntityType     entityType       = (IEdmEntityType)collectionType.ElementType.Definition;

                // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer
                return(actionMap.FindMatchingAction(
                           "Get" + entitySet.Name + "From" + entityType.Name,
                           "GetFrom" + entityType.Name));
            }

            return(null);
        }
Exemple #26
0
        private object ProcessPostBody(IODataRequestMessage message, IEdmEntitySetBase entitySet, object queryResults)
        {
            object lastNewInstance = null;

            using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings()))
            {
                var odataItemStack         = new Stack <ODataItem>();
                var entityStack            = new Stack <IEdmEntitySetBase>();
                var entryReader            = messageReader.CreateODataResourceReader(entitySet, entitySet.EntityType());
                var currentTargetEntitySet = entitySet;

                while (entryReader.Read())
                {
                    switch (entryReader.State)
                    {
                    case ODataReaderState.ResourceStart:
                    {
                        var entry = (ODataResource)entryReader.Item;
                        if (entry == null)
                        {
                            break;
                        }

                        odataItemStack.Push(entryReader.Item);
                        entityStack.Push(currentTargetEntitySet);
                        break;
                    }

                    case ODataReaderState.ResourceEnd:
                    {
                        var entry = (ODataResource)entryReader.Item;
                        if (entry == null)
                        {
                            break;
                        }

                        // TODO: the code here will be changed to handle following scenarios
                        //       1: non-contained navigation, e.g. People(1)/Friends
                        //       2. general entity set, e.g. People
                        //       3. contained navigation, e.g. People(1)/Trips
                        //       4. complex property, e.g. Airports('KSFO')/Location
                        //       5. upsert, e.g. People(1)/Friends(2)
                        object newInstance;
                        currentTargetEntitySet = entityStack.Pop();
                        if (currentTargetEntitySet == null)
                        {
                            // For entry
                            var valueType = EdmClrTypeUtils.GetInstanceType(entry.TypeName);
                            newInstance = Utility.QuickCreateInstance(valueType);
                        }
                        else
                        {
                            // For complex property
                            newInstance = this.DataSource.UpdateProvider.Create(entry.TypeName, queryResults);
                        }

                        foreach (var property in entry.Properties)
                        {
                            if (Utility.IsETagProperty(newInstance, property.Name))
                            {
                                continue;
                            }
                            this.DataSource.UpdateProvider.Update(newInstance, property.Name, property.Value);
                        }

                        var boundNavPropAnnotation = odataItemStack.Pop().GetAnnotation <BoundNavigationPropertyAnnotation>();
                        if (boundNavPropAnnotation != null)
                        {
                            foreach (var boundProperty in boundNavPropAnnotation.BoundProperties)
                            {
                                var isCollection  = boundProperty.Item1.IsCollection == true;
                                var propertyValue = isCollection ? boundProperty.Item2 : ((IEnumerable <object>)boundProperty.Item2).Single();
                                this.DataSource.UpdateProvider.Update(newInstance, boundProperty.Item1.Name, propertyValue);
                            }
                        }

                        var parentItem = odataItemStack.Count > 0 ? odataItemStack.Peek() : null;
                        if (parentItem != null)
                        {
                            // This new resource belongs to a navigation property and/or complex/complex collection property and/or feed -
                            // propagate it up the tree for further processing.
                            AddChildInstanceAnnotation(parentItem, newInstance);
                        }

                        lastNewInstance = newInstance;
                    }

                    break;

                    case ODataReaderState.ResourceSetStart:
                        odataItemStack.Push(entryReader.Item);
                        break;

                    case ODataReaderState.ResourceSetEnd:
                    {
                        var childAnnotation = odataItemStack.Pop().GetAnnotation <ChildInstanceAnnotation>();
                        var parentNavLink   = odataItemStack.Count > 0 ? odataItemStack.Peek() as ODataNestedResourceInfo : null;
                        if (parentNavLink != null)
                        {
                            // This feed belongs to a navigation property -
                            // propagate it up the tree for further processing.
                            AddChildInstanceAnnotations(parentNavLink, childAnnotation == null ? new object[0] : (childAnnotation.ChildInstances ?? new object[0]));
                        }
                    }

                    break;

                    case ODataReaderState.NestedResourceInfoStart:
                    {
                        odataItemStack.Push(entryReader.Item);
                        var nestedResourceInfo = (ODataNestedResourceInfo)entryReader.Item;
                        IEdmNavigationProperty navigationProperty = currentTargetEntitySet == null ? null : currentTargetEntitySet.EntityType().FindProperty(nestedResourceInfo.Name) as IEdmNavigationProperty;

                        // Current model implementation doesn't expose associations otherwise this would be much cleaner.
                        if (navigationProperty != null)
                        {
                            currentTargetEntitySet = this.DataSource.Model.EntityContainer.EntitySets().Single(s => s.EntityType() == navigationProperty.Type.Definition);
                        }
                        else
                        {
                            currentTargetEntitySet = null;
                        }

                        entityStack.Push(currentTargetEntitySet);
                    }

                    break;

                    case ODataReaderState.NestedResourceInfoEnd:
                    {
                        var navigationLink  = (ODataNestedResourceInfo)entryReader.Item;
                        var childAnnotation = odataItemStack.Pop().GetAnnotation <ChildInstanceAnnotation>();
                        if (childAnnotation != null)
                        {
                            // Propagate the bound entries to the parent entry.
                            AddBoundNavigationPropertyAnnotation(odataItemStack.Peek(), navigationLink, childAnnotation == null ? new object[0] : childAnnotation.ChildInstances);
                        }

                        entityStack.Pop();
                        currentTargetEntitySet = entityStack.Peek();
                    }

                    break;
                    }
                }
            }

            return(lastNewInstance);
        }