示例#1
0
        private Expression[] ProcessActionInvokePostBody(IODataRequestMessage message, IEdmOperation operation)
        {
            using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings()))
            {
                List <Expression> parameterValues = new List <Expression>();
                var parameterReader = messageReader.CreateODataParameterReader(operation);

                while (parameterReader.Read())
                {
                    switch (parameterReader.State)
                    {
                    case ODataParameterReaderState.Value:
                    {
                        object clrValue = ODataObjectModelConverter.ConvertPropertyValue(parameterReader.Value);
                        parameterValues.Add(Expression.Constant(clrValue));
                        break;
                    }

                    case ODataParameterReaderState.Collection:
                    {
                        ODataCollectionReader collectionReader = parameterReader.CreateCollectionReader();
                        object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadCollectionParameterValue(collectionReader));
                        parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType()));
                        break;
                    }

                    case ODataParameterReaderState.Resource:
                    {
                        var    entryReader = parameterReader.CreateResourceReader();
                        object clrValue    = ODataObjectModelConverter.ReadEntityOrEntityCollection(entryReader, false);
                        parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType()));
                        break;
                    }

                    case ODataParameterReaderState.ResourceSet:
                    {
                        var feedReader     = parameterReader.CreateResourceSetReader();
                        var collectionList = ODataObjectModelConverter.ReadEntityOrEntityCollection(feedReader, true);
                        parameterValues.Add(Expression.Constant(collectionList, collectionList.GetType()));
                        break;
                    }
                    }
                }

                return(parameterValues.ToArray());
            }
        }
示例#2
0
        /// <summary>
        /// Handle single entry, which from first level and $expand
        /// </summary>
        /// <param name="entry">Entry</param>
        /// <param name="entitySet">EntitySet</param>
        /// <param name="targetVersion">Target Version</param>
        /// <param name="selectExpandClause">Select and Expand Caluse</param>
        /// <param name="parentId">ParentId, string.Empty for first level</param>
        /// <param name="relationShip">Navigation property name, string.Empty for first level</param>
        private void GenerateDeltaItemFromEntry(object entry, IEdmNavigationSource entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause, string parentId, string relationShip)
        {
            var deltaEntry = ODataObjectModelConverter.ConvertToODataEntry(entry, entitySet, targetVersion).Resource;

            // Verify entry if need to be written
            DateTime lastestUpdated = ((ClrObject)entry).UpdatedTime;

            if (lastestUpdated > DeltaSnapshot.TimeStamp)
            {
                var lastSegmentOfDeltaEntry = new ODataUriParser(this.DataSource.Model, ServiceConstants.ServiceBaseUri, deltaEntry.Id).ParsePath().LastSegment as KeySegment;
                deltaEntry.SetSerializationInfo(new ODataResourceSerializationInfo
                {
                    NavigationSourceEntityTypeName = lastSegmentOfDeltaEntry.EdmType.ToString(),
                    NavigationSourceKind           = lastSegmentOfDeltaEntry.NavigationSource.NavigationSourceKind(),
                    NavigationSourceName           = lastSegmentOfDeltaEntry.NavigationSource.Name,
                });

                this.DeltaItems.Add(deltaEntry);
            }

            // Verify if need added link
            bool ifDeleted = DeltaSnapshot.Entries.Remove(DeltaSnapshot.Entries.FirstOrDefault(p => p.Id == deltaEntry.Id.AbsoluteUri && p.ParentId == parentId && p.RelationShip == relationShip));

            if ((!string.IsNullOrEmpty(parentId)) && ifDeleted == false)
            {
                var deltaLink = new ODataDeltaLink(new Uri(parentId), deltaEntry.Id, relationShip);
                var lastSegmentOfDeltaEntry = new ODataUriParser(this.DataSource.Model, ServiceConstants.ServiceBaseUri, deltaEntry.Id).ParsePath().LastSegment as KeySegment;
                deltaLink.SetSerializationInfo(new ODataDeltaSerializationInfo
                {
                    NavigationSourceName = lastSegmentOfDeltaEntry.NavigationSource.Name,
                });
                this.DeltaItems.Add(deltaLink);
            }

            // Handle $expand
            var expandedNavigationItems = selectExpandClause == null ? null : selectExpandClause.SelectedItems.OfType <ExpandedNavigationSelectItem>();

            GenerateDeltaItemsFromExpand(entry, entitySet, targetVersion, expandedNavigationItems, deltaEntry.Id.AbsoluteUri);
        }
示例#3
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            object result;

            if (this.HttpMethod == HttpMethod.GET)
            {
                // we cannot invoke same action request multiple times, so only Functions are allowed to do the server-driven paging
                this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext);

                result = this.ProcessFunction();

                if (this.PreferenceContext.MaxPageSize.HasValue)
                {
                    responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value));
                }
            }
            else
            {
                // TODO: currently ETag feature does not support action operation

                result = this.ProcessAction(requestMessage);
            }

            if (result == null)
            {
                // Protocol 9.1.4 Response Code 204 No Content
                // A request returns 204 No Content if the requested resource has the null value,
                // or if the service applies a return=minimal preference. In this case, the response body MUST be empty.
                ResponseWriter.WriteEmptyResponse(responseMessage);

                return;
            }

            using (var messageWriter = this.CreateMessageWriter(responseMessage))
            {
                if (this.QueryContext.Target.TypeKind == EdmTypeKind.None ||
                    this.QueryContext.Target.TypeKind == EdmTypeKind.EntityReference ||
                    this.QueryContext.Target.ElementTypeKind == EdmTypeKind.EntityReference)
                {
                    throw Utility.BuildException(HttpStatusCode.NotImplemented, "Unsupported return type in operation.", null);
                }
                else if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Entity ||
                         this.QueryContext.Target.TypeKind == EdmTypeKind.Complex || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Complex)
                {
                    ODataWriter resultWriter;

                    IEdmNavigationSource entitySource = this.QueryContext.OperationResultSource ?? this.QueryContext.Target.NavigationSource;

                    if (this.QueryContext.Target.TypeKind == EdmTypeKind.Collection)
                    {
                        IEdmEntitySetBase entitySet = (IEdmEntitySetBase)entitySource;

                        resultWriter = messageWriter.CreateODataResourceSetWriter(entitySet, (IEdmStructuredType)this.QueryContext.Target.ElementType);
                        ResponseWriter.WriteFeed(resultWriter, (IEdmStructuredType)this.QueryContext.Target.ElementType, result as IEnumerable, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, null, this.QueryContext.NextLink, this.RequestHeaders);
                    }
                    else
                    {
                        if (this.HttpMethod == HttpMethod.GET)
                        {
                            var currentETag = Utility.GetETagValue(result);
                            // if the current entity has ETag field
                            if (currentETag != null)
                            {
                                string requestETag;
                                if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag) && (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == currentETag))
                                {
                                    ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.NotModified);
                                    return;
                                }

                                responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag);
                            }
                        }

                        resultWriter = messageWriter.CreateODataResourceWriter(entitySource, (IEdmStructuredType)this.QueryContext.Target.Type);
                        ResponseWriter.WriteEntry(resultWriter, result, entitySource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders);
                    }
                }
                else
                {
                    ODataProperty property = new ODataProperty()
                    {
                        Name = "value", Value = ODataObjectModelConverter.CreateODataValue(result)
                    };
                    messageWriter.WriteProperty(property);
                }
            }
        }
示例#4
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            if (this.TryDispatch(requestMessage, responseMessage))
            {
                return;
            }

            this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext);
            this.QueryContext.InitializeTrackingChanges(this.PreferenceContext);

            object queryResults = this.QueryContext.ResolveQuery(this.DataSource);

            if (queryResults == null)
            {
                // For individual property or $value
                if (this.QueryContext.Target.Property != null)
                {
                    // Protocol 9.1.4 Response Code 204 No Content
                    // A request returns 204 No Content if the requested resource has the null value,
                    // or if the service applies a return=minimal preference. In this case, the response body MUST be empty.
                    ResponseWriter.WriteEmptyResponse(responseMessage);

                    return;
                }
                else
                {
                    throw Utility.BuildException(HttpStatusCode.NotFound);
                }
            }

            // Handle the prefer of "odata.include-annotations", including it in response header
            if (!string.IsNullOrEmpty(this.PreferenceContext.IncludeAnnotations))
            {
                responseMessage.AddPreferenceApplied(string.Format("{0}={1}",
                                                                   ServiceConstants.Preference_IncludeAnnotations, this.PreferenceContext.IncludeAnnotations));
            }

            if (this.PreferenceContext.MaxPageSize.HasValue)
            {
                responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value));
            }

            if (this.PreferenceContext.TrackingChanges)
            {
                responseMessage.AddPreferenceApplied(ServiceConstants.Preference_TrackChanging);
            }

            responseMessage.SetStatusCode(HttpStatusCode.OK);

            using (var messageWriter = this.CreateMessageWriter(responseMessage))
            {
                IEdmNavigationSource navigationSource   = this.QueryContext.Target.NavigationSource;
                IEnumerable          iEnumerableResults = queryResults as IEnumerable;

                if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection)
                {
                    // Query a $ref collection
                    IList <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>();

                    foreach (var iEnumerableResult in iEnumerableResults)
                    {
                        var link = new ODataEntityReferenceLink
                        {
                            Url = Utility.BuildLocationUri(this.QueryContext, iEnumerableResult),
                        };
                        links.Add(link);
                    }

                    ODataEntityReferenceLinks linksCollection = new ODataEntityReferenceLinks()
                    {
                        Links = links, NextPageLink = this.QueryContext.NextLink
                    };
                    linksCollection.InstanceAnnotations.Add(new ODataInstanceAnnotation("Links.Annotation", new ODataPrimitiveValue(true)));
                    messageWriter.WriteEntityReferenceLinks(linksCollection);
                }
                else if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity)
                {
                    // Query a $ref
                    var link = new ODataEntityReferenceLink
                    {
                        Url = Utility.BuildLocationUri(this.QueryContext, queryResults),
                    };
                    link.InstanceAnnotations.Add(new ODataInstanceAnnotation("Link.Annotation", new ODataPrimitiveValue(true)));

                    messageWriter.WriteEntityReferenceLink(link);
                }
                else if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection)
                {
                    // Query a feed
                    IEdmEntitySetBase entitySet  = navigationSource as IEdmEntitySetBase;
                    IEdmEntityType    entityType = this.QueryContext.Target.ElementType as IEdmEntityType;

                    if (entitySet == null || entityType == null)
                    {
                        throw new InvalidOperationException("Invalid target when query feed.");
                    }

                    ODataWriter resultWriter = messageWriter.CreateODataFeedWriter(entitySet, entityType);

                    ResponseWriter.WriteFeed(resultWriter, iEnumerableResults, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, this.QueryContext.DeltaLink, this.QueryContext.NextLink, this.RequestHeaders);
                    resultWriter.Flush();
                }
                else if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity)
                {
                    var currentETag = Utility.GetETagValue(queryResults);
                    // if the current entity has ETag field
                    if (currentETag != null)
                    {
                        string requestETag;
                        if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag) && (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == currentETag))
                        {
                            ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.NotModified);
                            return;
                        }

                        responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag);
                    }

                    // Query a single entity
                    IEdmEntityType entityType = this.QueryContext.Target.Type as IEdmEntityType;

                    ODataWriter resultWriter = messageWriter.CreateODataEntryWriter(navigationSource, entityType);
                    ResponseWriter.WriteEntry(resultWriter, queryResults, navigationSource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders);
                    resultWriter.Flush();
                }
                else if (this.QueryContext.Target.Property != null && !this.QueryContext.Target.IsRawValue)
                {
                    // Query a individual property
                    ODataProperty property = ODataObjectModelConverter.CreateODataProperty(queryResults, this.QueryContext.Target.Property.Name);
                    messageWriter.WriteProperty(property);
                }
                else if (this.QueryContext.Target.IsRawValue)
                {
                    // Query a $value or $count
                    var propertyValue = ODataObjectModelConverter.CreateODataValue(queryResults);
                    messageWriter.WriteValue(propertyValue);
                }
                else
                {
                    throw Utility.BuildException(HttpStatusCode.NotImplemented);
                }
            }
        }
示例#5
0
        private Expression[] ProcessActionInvokePostBody(IODataRequestMessage message, IEdmOperation operation)
        {
            using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings(), this.DataSource.Model))
            {
                List <Expression> parameterValues = new List <Expression>();
                var parameterReader = messageReader.CreateODataParameterReader(operation);

                while (parameterReader.Read())
                {
                    switch (parameterReader.State)
                    {
                    case ODataParameterReaderState.Value:
                    {
                        object clrValue = ODataObjectModelConverter.ConvertPropertyValue(parameterReader.Value);
                        parameterValues.Add(Expression.Constant(clrValue));
                        break;
                    }

                    case ODataParameterReaderState.Collection:
                    {
                        ODataCollectionReader collectionReader = parameterReader.CreateCollectionReader();
                        object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadCollectionParameterValue(collectionReader));
                        parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType()));
                        break;
                    }

                    case ODataParameterReaderState.Entry:
                    {
                        var    entryReader = parameterReader.CreateEntryReader();
                        object clrValue    = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadEntryParameterValue(entryReader));
                        parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType()));
                        break;
                    }

                    case ODataParameterReaderState.Feed:
                    {
                        IList collectionList = null;
                        var   feedReader     = parameterReader.CreateFeedReader();
                        while (feedReader.Read())
                        {
                            if (feedReader.State == ODataReaderState.EntryEnd)
                            {
                                object clrItem = ODataObjectModelConverter.ConvertPropertyValue(feedReader.Item);
                                if (collectionList == null)
                                {
                                    Type itemType = clrItem.GetType();
                                    Type listType = typeof(List <>).MakeGenericType(new[] { itemType });
                                    collectionList = (IList)Utility.QuickCreateInstance(listType);
                                }

                                collectionList.Add(clrItem);
                            }
                        }

                        parameterValues.Add(Expression.Constant(collectionList, collectionList.GetType()));
                        break;
                    }
                    }
                }

                return(parameterValues.ToArray());
            }
        }
        private static void UpdateCore(object target, string propertyName, object propertyValue)
        {
            var odataComplexValue    = propertyValue as ODataComplexValue;
            var odataCollectionValue = propertyValue as ODataCollectionValue;
            var odataEnumValue       = propertyValue as ODataEnumValue;
            var odataPrimitiveValue  = propertyValue as ODataPrimitiveValue;

            if (odataComplexValue != null)
            {
                var property = target.GetType().GetProperty(propertyName);
                if (property != null)
                {
                    var value = property.GetValue(target, null);
                    if (value == null)
                    {
                        var valueType    = EdmClrTypeUtils.GetInstanceType(odataComplexValue.TypeName);
                        var propertyType = property.PropertyType;
                        if (valueType.IsSubclassOf(propertyType) || valueType == propertyType)
                        {
                            value = Utility.QuickCreateInstance(valueType);
                        }
                        else
                        {
                            throw new InvalidOperationException(string.Format("{0} is not equal or derived from {1}", valueType, propertyType));
                        }

                        property.SetValue(target, value, null);
                    }

                    foreach (var p in odataComplexValue.Properties)
                    {
                        UpdateCore(value, p.Name, p.Value);
                    }

                    return;
                }
            }
            else if (odataCollectionValue != null)
            {
                var property = target.GetType().GetProperty(propertyName);
                if (property != null)
                {
                    var collection = Utility.QuickCreateInstance(property.PropertyType);

                    foreach (var item in odataCollectionValue.Items)
                    {
                        var itemType = property.PropertyType.GetGenericArguments().Single();
                        odataComplexValue    = item as ODataComplexValue;
                        odataCollectionValue = item as ODataCollectionValue;
                        object collectionItem = null;
                        if (odataComplexValue != null)
                        {
                            // TODO: call Create method to new instance instead
                            collectionItem = Utility.QuickCreateInstance(itemType);
                            foreach (var p in odataComplexValue.Properties)
                            {
                                UpdateCore(collectionItem, p.Name, p.Value);
                            }
                        }
                        else if (odataCollectionValue != null)
                        {
                            // TODO, check should support this type or not
                            throw new NotImplementedException();
                        }
                        else
                        {
                            collectionItem = ODataObjectModelConverter.ConvertPropertyValue(item, itemType);
                        }

                        property.PropertyType.GetMethod("Add").Invoke(collection, new object[] { collectionItem });
                    }

                    property.SetValue(target, collection, null);

                    return;
                }
            }
            else
            {
                var property = target.GetType().GetProperty(propertyName);
                if (property != null)
                {
                    property.SetValue(target, ODataObjectModelConverter.ConvertPropertyValue(propertyValue, property.PropertyType), null);
                    return;
                }
            }

            var openClrObject = target as OpenClrObject;

            if (openClrObject != null)
            {
                var structuredType = (IEdmStructuredType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, openClrObject);

                //check if the edmType is an open type
                if (structuredType.IsOpen)
                {
                    if (odataCollectionValue != null)
                    {
                        // Collection of Edm.String
                        if (odataCollectionValue.TypeName == "Collection(Edm.String)")
                        {
                            var collection = new Collection <string>();
                            foreach (var it in odataCollectionValue.Items)
                            {
                                collection.Add(it as string);
                            }
                            openClrObject.OpenProperties[propertyName] = collection;
                        }
                        else
                        {
                            // TODO: handle other types.
                            throw new NotImplementedException();
                        }
                    }
                    else if (odataComplexValue != null)
                    {
                        var type  = EdmClrTypeUtils.GetInstanceType(odataComplexValue.TypeName);
                        var value = Utility.QuickCreateInstance(type);
                        foreach (var property in odataComplexValue.Properties)
                        {
                            UpdateCore(value, property.Name, property.Value);
                        }
                        openClrObject.OpenProperties[propertyName] = value;
                    }
                    else if (odataEnumValue != null)
                    {
                        var type = EdmClrTypeUtils.GetInstanceType(odataEnumValue.TypeName);
                        openClrObject.OpenProperties[propertyName] = ODataObjectModelConverter.ConvertPropertyValue(propertyValue, type);
                    }
                    else if (odataPrimitiveValue != null)
                    {
                        openClrObject.OpenProperties[propertyName] = odataPrimitiveValue.Value;
                    }
                    else
                    {
                        openClrObject.OpenProperties[propertyName] = propertyValue;
                    }
                }
            }
        }