private static EntityReferenceCollection GetEntityReferences(
            ODataNavigationLinkWithItems navigationLinkWrapper,
            ODataDeserializerContext readContext)
        {
            var referenceCollection = new EntityReferenceCollection();

            foreach (var childItem in navigationLinkWrapper.NestedItems.OfType <ODataEntityReferenceLinkBase>())
            {
                var uriParser = readContext.Request.GetODataUriParser(childItem.EntityReferenceLink.Url);
                referenceCollection.Add(uriParser.ParsePath());
            }
            return(referenceCollection);
        }
        public override void ApplyNavigationProperty(
            object entityResource,
            ODataNavigationLinkWithItems navigationLinkWrapper,
            IEdmEntityTypeReference entityType,
            ODataDeserializerContext readContext)
        {
            base.ApplyNavigationProperty(entityResource, navigationLinkWrapper, entityType, readContext);

            var referenceCollection = GetEntityReferences(navigationLinkWrapper, readContext);

            if (referenceCollection.Any())
            {
                if (!entityResource.As <EdmStructuredObject>().TrySetPropertyValue(navigationLinkWrapper.NavigationLink.Name, referenceCollection))
                {
                    throw new InvalidOperationException("Unable to set entity reference links as navigation property value.");
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Десериализует navigation property.
        /// Также выполняет необходимые действия, чтобы обработка @odata.bind выполнялась по стандарту OData.
        /// </summary>
        /// <param name="entityResource">Объект, в который navigation property будет прочитано.</param>
        /// <param name="navigationLinkWrapper">navigation линк.</param>
        /// <param name="entityType">Тип сущности.</param>
        /// <param name="readContext">Состояние и установки, используемые при чтении.</param>
        public override void ApplyNavigationProperty(
            object entityResource,
            ODataNavigationLinkWithItems navigationLinkWrapper,
            IEdmEntityTypeReference entityType,
            ODataDeserializerContext readContext)
        {
            base.ApplyNavigationProperty(entityResource, navigationLinkWrapper, entityType, readContext);
            EdmEntityObject    edmEntity = (EdmEntityObject)entityResource;
            DataObjectEdmModel model     = readContext.Model as DataObjectEdmModel;

            foreach (var childItem in navigationLinkWrapper.NestedItems)
            {
                if (!readContext.Request.Properties.ContainsKey(Dictionary))
                {
                    readContext.Request.Properties.Add(Dictionary, new Dictionary <string, object>());
                }

                var dictionary             = (Dictionary <string, object>)readContext.Request.Properties[Dictionary];
                var navigationPropertyName = navigationLinkWrapper.NavigationLink.Name;
                var entityReferenceLink    = childItem as ODataEntityReferenceLinkBase;

                if (entityReferenceLink != null)
                {
                    Uri referencedEntityUrl = entityReferenceLink.EntityReferenceLink.Url;
                    if (referencedEntityUrl.IsAbsoluteUri)
                    {
                        referencedEntityUrl = referencedEntityUrl.MakeRelativeUri(readContext.Request.RequestUri);
                    }

                    var segments = referencedEntityUrl.OriginalString.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
                    if (segments.Length != 2)
                    {
                        throw new ApplicationException($"Invalid @odata.bind: {referencedEntityUrl.OriginalString}");
                    }

                    var type = model.GetDataObjectType(segments[0]);
                    if (type == null)
                    {
                        throw new ApplicationException($"Invalid entity set: {segments[0]}");
                    }

                    Guid guid;
                    try
                    {
                        guid = new Guid(segments[1]);
                    }
                    catch (Exception)
                    {
                        throw new ApplicationException($"Invalid guid: {segments[1]}");
                    }

                    var linkedEdmEntity = new EdmEntityObject(model.GetEdmEntityType(type));
                    linkedEdmEntity.TrySetPropertyValue("__PrimaryKey", guid);
                    edmEntity.TrySetPropertyValue(navigationPropertyName, linkedEdmEntity);
                    if (!dictionary.ContainsKey(navigationPropertyName))
                    {
                        dictionary.Add(navigationPropertyName, navigationPropertyName);
                    }
                }

                var feed = childItem as ODataFeedWithEntries;
                if (childItem == null || (feed != null && feed.Entries.Count == 0))
                {
                    edmEntity.TrySetPropertyValue(navigationPropertyName, null);
                    if (!dictionary.ContainsKey(navigationPropertyName))
                    {
                        dictionary.Add(navigationPropertyName, null);
                    }
                }
            }
        }