Пример #1
0
        /// <summary>
        /// Creates the metadata builder for the given entry. If such a builder is set, asking for payload
        /// metadata properties (like EditLink) of the entry may return a value computed by convention,
        /// depending on the metadata level and whether the user manually set an edit link or not.
        /// </summary>
        /// <param name="entry">The entry to create the metadata builder for.</param>
        /// <param name="typeContext">The context object to answer basic questions regarding the type of the entry or feed.</param>
        /// <param name="serializationInfo">The serialization info for the entry.</param>
        /// <param name="actualEntityType">The entity type of the entry.</param>
        /// <param name="selectedProperties">The selected properties of this scope.</param>
        /// <param name="isResponse">true if the entity metadata builder to create should be for a response payload; false for a request.</param>
        /// <param name="keyAsSegment">true if keys should go in seperate segments in auto-generated URIs, false if they should go in parentheses.
        /// A null value means the user hasn't specified a preference and we should look for an annotation in the entity container, if available.</param>
        /// <param name="odataUri">The OData Uri.</param>
        /// <returns>The created metadata builder.</returns>
        internal override ODataEntityMetadataBuilder CreateEntityMetadataBuilder(
            ODataEntry entry,
            IODataFeedAndEntryTypeContext typeContext,
            ODataFeedAndEntrySerializationInfo serializationInfo,
            IEdmEntityType actualEntityType,
            SelectedPropertiesNode selectedProperties,
            bool isResponse,
            bool?keyAsSegment,
            ODataUri odataUri)
        {
            Debug.Assert(entry != null, "entry != null");
            Debug.Assert(typeContext != null, "typeContext != null");
            Debug.Assert(selectedProperties != null, "selectedProperties != null");

            IODataMetadataContext metadataContext = new ODataMetadataContext(
                isResponse,
                this.model,
                this.NonNullMetadataDocumentUri,
                odataUri);

            UrlConvention urlConvention            = UrlConvention.ForUserSettingAndTypeContext(keyAsSegment, typeContext);
            ODataConventionalUriBuilder uriBuilder = new ODataConventionalUriBuilder(metadataContext.ServiceBaseUri, urlConvention);

            IODataEntryMetadataContext entryMetadataContext = ODataEntryMetadataContext.Create(entry, typeContext, serializationInfo, actualEntityType, metadataContext, selectedProperties);

            return(new ODataConventionalEntityMetadataBuilder(entryMetadataContext, metadataContext, uriBuilder));
        }
            /// <summary>
            /// Constructs an instance of <see cref="ODataFeedAndEntryTypeContext"/>.
            /// </summary>
            /// <param name="navigationSource">The navigation source of the feed or entry.</param>
            /// <param name="navigationSourceEntityType">The entity type of the navigation source.</param>
            /// <param name="expectedEntityType">The expected entity type of the feed or entry.</param>
            /// <param name="model">The Edm model instance to use.</param>
            internal ODataFeedAndEntryTypeContextWithModel(IEdmNavigationSource navigationSource, IEdmEntityType navigationSourceEntityType, IEdmEntityType expectedEntityType, IEdmModel model)
                : base(/*throwIfMissingTypeInfo*/ false)
            {
                Debug.Assert(model != null, "model != null");
                Debug.Assert(navigationSource != null, "navigationSource != null");
                Debug.Assert(navigationSourceEntityType != null, "navigationSourceEntityType != null");
                Debug.Assert(expectedEntityType != null, "expectedEntityType != null");

                this.navigationSource           = navigationSource;
                this.navigationSourceEntityType = navigationSourceEntityType;
                this.expectedEntityType         = expectedEntityType;
                this.model = model;

                IEdmContainedEntitySet containedEntitySet = navigationSource as IEdmContainedEntitySet;

                if (containedEntitySet != null)
                {
                    if (containedEntitySet.NavigationProperty.Type.TypeKind() == EdmTypeKind.Collection)
                    {
                        this.isFromCollection = true;
                    }
                }

                this.navigationSourceName = this.navigationSource.Name;
                this.isMediaLinkEntry     = this.expectedEntityType.HasStream;
                this.lazyUrlConvention    = new SimpleLazy <UrlConvention>(() => UrlConvention.ForModel(this.model));
            }
        /// <summary>
        /// Populates the annotation cache based on the current configuration of the service.
        /// 1) Adds any annotatedModels specific to the current URL convention.
        /// 2) Invokes the user-provided 'AnnotationsBuilder' delegate.
        /// </summary>
        /// <param name="configuration">The service configuration.</param>
        internal void PopulateFromConfiguration(DataServiceConfiguration configuration)
        {
            Debug.Assert(configuration != null, "configuration != null");

            // Add any annotations for the current URL convention.
            this.AddAnnotations(UrlConvention.BuildMetadataAnnotations(configuration.DataServiceBehavior, this.primaryModel));

            IEnumerable <IEdmModel> annotatedModels = null;
            Func <IEdmModel, IEnumerable <IEdmModel> > annotationsBuilder = configuration.AnnotationsBuilder;

            if (annotationsBuilder != null)
            {
                annotatedModels = annotationsBuilder(this.primaryModel);
            }

            // if the delegate was not provided or returned null, stop now.
            if (annotatedModels == null)
            {
                return;
            }

            // add the annotations form each of the models to the vocab cache
            foreach (IEdmModel annotationModel in annotatedModels)
            {
                if (annotationModel == null)
                {
                    throw new InvalidOperationException(Strings.DataServiceProviderWrapper_AnnotationsBuilderCannotReturnNullModels);
                }

                // to avoid issues with the closure, create a local variable to store the model.
                IEdmModel localReferenceToModel = annotationModel;
                this.AddAnnotations(localReferenceToModel.VocabularyAnnotations);
            }
        }
Пример #4
0
        /// <summary>
        /// Gets an entity metadata builder for the given entry.
        /// </summary>
        /// <param name="entryState">Entry state to use as reference for information needed by the builder.</param>
        /// <returns>An entity metadata builder.</returns>
        public ODataEntityMetadataBuilder GetEntityMetadataBuilderForReader(IODataJsonLightReaderEntryState entryState)
        {
            Debug.Assert(entryState != null, "entry != null");

            // Only apply the conventional template builder on response. On a request we would only report what's on the wire.
            if (entryState.MetadataBuilder == null)
            {
                ODataEntry entry = entryState.Entry;
                if (this.isResponse)
                {
                    ODataTypeAnnotation typeAnnotation = entry.GetAnnotation <ODataTypeAnnotation>();

                    Debug.Assert(typeAnnotation != null, "The JSON light reader should have already set the ODataTypeAnnotation.");
                    IEdmNavigationSource navigationSource = typeAnnotation.NavigationSource;

                    IEdmEntityType navigationSourceElementType         = this.edmTypeResolver.GetElementType(navigationSource);
                    IODataFeedAndEntryTypeContext typeContext          = ODataFeedAndEntryTypeContext.Create(/*serializationInfo*/ null, navigationSource, navigationSourceElementType, entryState.EntityType, this.model, /*throwIfMissingTypeInfo*/ true);
                    IODataEntryMetadataContext    entryMetadataContext = ODataEntryMetadataContext.Create(entry, typeContext, /*serializationInfo*/ null, (IEdmEntityType)entry.GetEdmType().Definition, this, entryState.SelectedProperties);

                    UrlConvention urlConvention            = UrlConvention.ForUserSettingAndTypeContext(/*keyAsSegment*/ null, typeContext);
                    ODataConventionalUriBuilder uriBuilder = new ODataConventionalUriBuilder(this.ServiceBaseUri, urlConvention);

                    entryState.MetadataBuilder = new ODataConventionalEntityMetadataBuilder(entryMetadataContext, this, uriBuilder);
                }
                else
                {
                    entryState.MetadataBuilder = new NoOpEntityMetadataBuilder(entry);
                }
            }

            return(entryState.MetadataBuilder);
        }
Пример #5
0
        public void UrlConventionFromSettingAndTypeContextShouldReturnKeyAsSegmentIfSettingIsNullAndTypeContextReturnsKeyAsSegment()
        {
            var typeContext = new TestFeedAndEntryTypeContext()
            {
                UrlConvention = UrlConvention.CreateWithExplicitValue(/*generateKeyAsSegment*/ true)
            };

            UrlConvention.ForUserSettingAndTypeContext(null, typeContext).GenerateKeyAsSegment.Should().BeTrue();
        }
Пример #6
0
        public void UrlConventionFromAnnotationShouldReturnKeyAsSegmentIfAnnotationFound()
        {
            var container = new EdmEntityContainer("Fake", "Container");
            var model     = new EdmModel();

            model.AddElement(container);
            model.AddVocabularyAnnotation(new EdmAnnotation(container, UrlConventionsConstants.ConventionTerm, UrlConventionsConstants.KeyAsSegmentAnnotationValue));
            UrlConvention.ForModel(model).GenerateKeyAsSegment.Should().BeTrue();
        }
Пример #7
0
        public void UrlConventionFromAnnotationShouldReturnDefaultIfAnnotationMissing()
        {
            var container = new EdmEntityContainer("Fake", "Container");
            var model     = new EdmModel();

            model.AddElement(container);
            model.AddVocabularyAnnotation(new EdmAnnotation(container, new EdmTerm("Fake", "Fake", EdmPrimitiveTypeKind.Stream), EdmNullExpression.Instance));
            UrlConvention.ForModel(model).GenerateKeyAsSegment.Should().BeFalse();
        }
Пример #8
0
        public void UrlConventionFromAnnotationShouldReturnDefaultIfAnnotationHasWrongValue()
        {
            var container = new EdmEntityContainer("Fake", "Container");
            var model     = new EdmModel();

            model.AddElement(container);
            model.AddVocabularyAnnotation(new EdmAnnotation(container, UrlConventionsConstants.ConventionTerm, new EdmStringConstant("fake")));
            UrlConvention.ForModel(model).GenerateKeyAsSegment.Should().BeFalse();
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="serviceBaseUri">The base URI of the service. This will be used as the base URI for all entity containers.</param>
        /// <param name="urlConvention">The specific url convention to use.</param>
        internal ODataConventionalUriBuilder(Uri serviceBaseUri, UrlConvention urlConvention)
        {
            Debug.Assert(serviceBaseUri != null && serviceBaseUri.IsAbsoluteUri, "serviceBaseUri != null && serviceBaseUri.IsAbsoluteUri");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            this.serviceBaseUri = serviceBaseUri;
            this.urlConvention  = urlConvention;
            this.keySerializer  = KeySerializer.Create(this.urlConvention);
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="serviceBaseUri">The base URI of the service. This will be used as the base URI for all entity containers.</param>
        /// <param name="urlConvention">The specific url convention to use.</param>
        internal ODataConventionalUriBuilder(Uri serviceBaseUri, UrlConvention urlConvention)
        {
            Debug.Assert(serviceBaseUri != null && serviceBaseUri.IsAbsoluteUri, "serviceBaseUri != null && serviceBaseUri.IsAbsoluteUri");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            this.serviceBaseUri = serviceBaseUri;
            this.urlConvention = urlConvention;
            this.keySerializer = KeySerializer.Create(this.urlConvention);
        }
Пример #11
0
        public void Init()
        {
            this.keyProperty1 = new ResourceProperty("Key1", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)));
            this.keyProperty2 = new ResourceProperty("Key2", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)));

            this.defaultSerializer = KeySerializer.Create(UrlConvention.CreateWithExplicitValue(false));
            this.segmentSerializer = KeySerializer.Create(UrlConvention.CreateWithExplicitValue(true));

            this.singleKeyProperty = new[] { this.keyProperty1 };
            this.compositeKey      = new[] { this.keyProperty1, this.keyProperty2 };
        }
Пример #12
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="urlConvention">The current url convention for the server.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, IPathSegment previous, UrlConvention urlConvention, out IPathSegment keySegment)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            keySegment = null;

            // If the current convention is not keys-as-segments, then this does not apply.
            if (!urlConvention.GenerateKeyAsSegment)
            {
                return false;
            }

            // If the current identifier was preceeded by a '$' segment, then do not treat it as a key.
            if (previous.IsEscapeMarker)
            {
                return false;
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return false;
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return false;
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;
            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return false;
            }

            // If the resource type has more than 1 key property, then do not treat the segment as a key.
            var keyProperties = targetEntityType.Key().ToList();
            if (keyProperties.Count > 1)
            {
                return false;
            }

            // At this point it must be treated as a key, so fail if it is malformed.
            Debug.Assert(keyProperties.Count == 1, "keyProperties.Count == 1");
            keySegment = CreateKeySegment(previous, KeyInstance.FromSegment(segmentText));

            return true;
        }
Пример #13
0
 public void FullMetadataLevelShouldReturnODataConventionalEntityMetadataBuilder()
 {
     testSubject.CreateEntityMetadataBuilder(
         new ODataEntry(),
         new TestFeedAndEntryTypeContext {
         UrlConvention = UrlConvention.CreateWithExplicitValue(generateKeyAsSegment: false)
     }, new ODataFeedAndEntrySerializationInfo(), /*actualEntityType*/ null,
         SelectedPropertiesNode.EntireSubtree,
         /*isResponse*/ true,
         /*keyAsSegment*/ false,
         /*requestUri*/ null).Should().BeAssignableTo <ODataConventionalEntityMetadataBuilder>();
 }
Пример #14
0
        /// <summary>
        /// Creates a new key serializer.
        /// </summary>
        /// <param name="urlConvention">The url convention to use.</param>
        /// <returns>
        /// A new key serializer.
        /// </returns>
        internal static KeySerializer Create(UrlConvention urlConvention)
        {
#if ODATALIB
#endif
            Debug.Assert(urlConvention != null, "UrlConvention != null");

            if (urlConvention.GenerateKeyAsSegment)
            {
                return(SegmentInstance);
            }

            return(DefaultInstance);
        }
Пример #15
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="urlConvention">The current url convention for the server.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, ODataPathSegment previous, KeySegment previousKeySegment, UrlConvention urlConvention, out KeySegment keySegment, bool enableUriTemplateParsing = false, ODataUriResolver resolver = null)
        {
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            keySegment = null;

            // If the current convention is not keys-as-segments, then this does not apply.
            if (!urlConvention.GenerateKeyAsSegment)
            {
                return false;
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return false;
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return false;
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;
            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return false;
            }

            // Previously KeyAsSegment only allows single key, but we can also leverage related key finder to auto fill
            // missed key value from referential constraint information, which would be done in CreateKeySegment.
            // CreateKeySegment method will check whether key properties are missing after taking in related key values.
            keySegment = CreateKeySegment(previous, previousKeySegment, SegmentArgumentParser.FromSegment(segmentText, enableUriTemplateParsing), resolver);

            return true;
        }
Пример #16
0
        private static EntityToSerialize CreateEntityToSerialize(bool shouldIncludeTypeSegment)
        {
            ResourceType baseType = new ResourceType(typeof(MyType), ResourceTypeKind.EntityType, null, "TestNamespace", "BaseType", /*isAbstract*/ false);

            baseType.AddProperty(new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, new ResourceType(typeof(int), ResourceTypeKind.Primitive, null, "int")));

            baseType.SetReadOnly();

            Uri serviceUri = new Uri("http://dummy");

            KeySerializer keySerializer = KeySerializer.Create(UrlConvention.CreateWithExplicitValue(false));

            Func <ResourceProperty, object> getPropertyValue = p => "fakePropertyValue";

            return(EntityToSerialize.Create(new MyType {
                ID = 42
            }, baseType, "MySet", shouldIncludeTypeSegment, getPropertyValue, keySerializer, serviceUri));
        }
Пример #17
0
            /// <summary>
            /// Constructs an instance of <see cref="ODataFeedAndEntryTypeContext"/>.
            /// </summary>
            /// <param name="entitySet">The entity set of the feed or entry.</param>
            /// <param name="entitySetElementType">The element type of the entity set.</param>
            /// <param name="expectedEntityType">The expected entity type of the feed or entry.</param>
            /// <param name="model">The Edm model instance to use.</param>
            internal ODataFeedAndEntryTypeContextWithModel(IEdmEntitySet entitySet, IEdmEntityType entitySetElementType, IEdmEntityType expectedEntityType, IEdmModel model)
                : base(/*throwIfMissingTypeInfo*/ false)
            {
                DebugUtils.CheckNoExternalCallers();
                Debug.Assert(model != null, "model != null");
                Debug.Assert(entitySet != null, "entitySet != null");
                Debug.Assert(entitySetElementType != null, "entitySetElementType != null");
                Debug.Assert(expectedEntityType != null, "expectedEntityType != null");

                this.entitySet            = entitySet;
                this.entitySetElementType = entitySetElementType;
                this.expectedEntityType   = expectedEntityType;
                this.model = model;

                this.lazyEntitySetName    = new SimpleLazy <string>(() => this.model.IsDefaultEntityContainer(this.entitySet.Container) ? this.entitySet.Name : this.entitySet.Container.FullName() + "." + this.entitySet.Name);
                this.lazyIsMediaLinkEntry = new SimpleLazy <bool>(() => this.model.HasDefaultStream(this.expectedEntityType));
                this.lazyUrlConvention    = new SimpleLazy <UrlConvention>(() => UrlConvention.ForEntityContainer(this.model, this.entitySet.Container));
            }
Пример #18
0
        /// <summary>
        /// Creates a new instance of <see cref="EntityToSerialize"/>.
        /// </summary>
        /// <param name="entity">The entity itself.</param>
        /// <param name="resourceType">The type of the entity.</param>
        /// <param name="resourceSetWrapper">The resource set the entity belongs to.</param>
        /// <param name="provider">The wrapper for the current service provider.</param>
        /// <param name="absoluteServiceUri">The absolute service URI.</param>
        /// <returns>The new instance of <see cref="EntityToSerialize"/></returns>
        internal static EntityToSerialize Create(object entity, ResourceType resourceType, ResourceSetWrapper resourceSetWrapper, DataServiceProviderWrapper provider, Uri absoluteServiceUri)
        {
            Debug.Assert(provider != null, "provider != null");
            Debug.Assert(provider.DataService != null, "provider.DataService != null");
            Debug.Assert(provider.DataService.Configuration != null, "provider.DataService.Configuration != null");

            KeySerializer keySerializer = KeySerializer.Create(UrlConvention.Create(provider.DataService));
            Func <ResourceProperty, object> getPropertyValue = p =>
            {
                object keyValue = WebUtil.GetPropertyValue(provider, entity, resourceType, p, null);
                if (keyValue == null)
                {
                    throw new InvalidOperationException(Service.Strings.Serializer_NullKeysAreNotSupported(p.Name));
                }

                return(keyValue);
            };

            bool includeTypeSegment = resourceSetWrapper.ResourceType != resourceType;

            return(Create(entity, resourceType, resourceSetWrapper.Name, includeTypeSegment, getPropertyValue, keySerializer, absoluteServiceUri));
        }
Пример #19
0
        private static void RunPinningTest(StringBuilder builder, params object[] keyValues)
        {
            var compositeKey = keyValues.Select((k, i) => new { Name = "prop" + i, Value = k }).ToArray();
            var allKeys      = keyValues.Select(k => new[] { new { Name = "prop", Value = k } }).Concat(new[] { compositeKey });

            foreach (var key in allKeys)
            {
                if (builder.Length > 0)
                {
                    builder.AppendLine();
                }

                var properties = key.Select(p => new EdmPropertyValue(p.Name, EdmValueUtils.ConvertPrimitiveValue(p.Value, null).Value)).ToList();
                var entityType = new EdmEntityType("Fake", "Fake");
                entityType.AddKeys(properties.Select(p => new EdmStructuralProperty(entityType, p.Name, p.Value.Type)));
                var entity = new EdmStructuredValue(new EdmEntityTypeReference(entityType, false), properties);
                ODataConventionalUriBuilder uriBuilder = new ODataConventionalUriBuilder(new Uri("http://baseuri.org/"), UrlConvention.CreateWithExplicitValue(false));
                var entityInstanceUri = uriBuilder.BuildEntityInstanceUri(new Uri("http://baseuri.org/Customers"), new Collection <KeyValuePair <string, object> >(properties.Select(p => new KeyValuePair <string, object>(p.Name, ((IEdmPrimitiveValue)p.Value).ToClrValue())).ToList()), entity.Type.FullName());
                builder.Append(entityInstanceUri.OriginalString.Replace("http://baseuri.org/Customers", null).Replace("()", "%28%29"));
            }

            builder.AppendLine();
        }
Пример #20
0
 /// <summary>
 /// Prevents a default instance of the <see cref="ODataUrlConventions"/> class from being created.
 /// </summary>
 /// <param name="urlConvention">The url convention to use.</param>
 private ODataUrlConventions(UrlConvention urlConvention)
 {
     Debug.Assert(urlConvention != null, "urlConvention != null");
     this.urlConvention = urlConvention;
 }
Пример #21
0
 /// <summary>
 /// Prevents a default instance of the <see cref="DataServiceUrlConventions"/> class from being created.
 /// </summary>
 /// <param name="urlConvention">The url convention to use.</param>
 private DataServiceUrlConventions(UrlConvention urlConvention)
 {
     Debug.Assert(urlConvention != null, "urlConvention != null");
     this.urlConvention = urlConvention;
     this.keySerializer = KeySerializer.Create(urlConvention);
 }
Пример #22
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="urlConvention">The current url convention for the server.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, IPathSegment previous, UrlConvention urlConvention, out IPathSegment keySegment)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            keySegment = null;

            // If the current convention is not keys-as-segments, then this does not apply.
            if (!urlConvention.GenerateKeyAsSegment)
            {
                return(false);
            }

            // If the current identifier was preceeded by a '$' segment, then do not treat it as a key.
            if (previous.IsEscapeMarker)
            {
                return(false);
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return(false);
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return(false);
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;

            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return(false);
            }

            // If the resource type has more than 1 key property, then do not treat the segment as a key.
            var keyProperties = targetEntityType.Key().ToList();

            if (keyProperties.Count > 1)
            {
                return(false);
            }

            // At this point it must be treated as a key, so fail if it is malformed.
            Debug.Assert(keyProperties.Count == 1, "keyProperties.Count == 1");
            keySegment = CreateKeySegment(previous, KeyInstance.FromSegment(segmentText));

            return(true);
        }
Пример #23
0
 /// <summary>
 /// Prevents a default instance of the <see cref="ODataUrlConventions"/> class from being created.
 /// </summary>
 /// <param name="urlConvention">The url convention to use.</param>
 private ODataUrlConventions(UrlConvention urlConvention)
 {
     Debug.Assert(urlConvention != null, "urlConvention != null");
     this.urlConvention = urlConvention;
 }
Пример #24
0
        public void InitTest()
        {
            this.navigationLink = new ODataNavigationLink();

            var entry = new ODataEntry
            {
                TypeName   = "ns.DerivedType",
                Properties = new[]
                {
                    new ODataProperty {
                        Name = "Id", Value = 1, SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.Key
                        }
                    },
                    new ODataProperty {
                        Name = "Name", Value = "Bob", SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.ETag
                        }
                    }
                }
            };

            var serializationInfo = new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.BaseType", ExpectedTypeName = "ns.BaseType"
            };
            var typeContext          = ODataFeedAndEntryTypeContext.Create(serializationInfo, null, null, null, EdmCoreModel.Instance, true);
            var metadataContext      = new TestMetadataContext();
            var entryMetadataContext = ODataEntryMetadataContext.Create(entry, typeContext, serializationInfo, null, metadataContext, SelectedPropertiesNode.EntireSubtree);
            var metadataBuilder      = new ODataConventionalEntityMetadataBuilder(entryMetadataContext, metadataContext, new ODataConventionalUriBuilder(ServiceUri, UrlConvention.CreateWithExplicitValue(false)));

            this.navigationLinkWithFullBuilder = new ODataNavigationLink {
                Name = "NavProp"
            };
            this.navigationLinkWithFullBuilder.MetadataBuilder = metadataBuilder;

            this.navigationLinkWithNoOpBuilder = new ODataNavigationLink {
                Name = "NavProp"
            };
            this.navigationLinkWithNoOpBuilder.MetadataBuilder = new NoOpEntityMetadataBuilder(entry);

            this.navigationLinkWithNullBuilder = new ODataNavigationLink {
                Name = "NavProp"
            };
            this.navigationLinkWithNullBuilder.MetadataBuilder = ODataEntityMetadataBuilder.Null;
        }
        public ODataConventionalUriBuilderTests()
        {
            this.defaultBaseUri = new Uri("http://odata.org/base/");
            this.builder        = new ODataConventionalUriBuilder(this.defaultBaseUri, UrlConvention.CreateWithExplicitValue(false));

            this.model = TestModel.BuildDefaultTestModel();
            this.defaultProductInstance     = TestModel.BuildDefaultProductValue(TestModel.GetEntityType(this.model, "TestModel.Product"));
            this.defaultMultipleKeyInstance = TestModel.BuildDefaultMultipleKeyValue(this.model);

            this.idPropertyList = new Dictionary <string, IEdmValue>()
            {
                { "Id", new EdmIntegerConstant(EdmCoreModel.Instance.GetInt32(false), 42) }
            };

            this.typeWithStringKey = new EdmEntityType("Test.Model", "StringKey");
            this.typeWithStringKey.AddKeys(this.typeWithStringKey.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String));
        }
Пример #26
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="urlConvention">The current url convention for the server.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, ODataPathSegment previous, KeySegment previousKeySegment, UrlConvention urlConvention, out KeySegment keySegment, bool enableUriTemplateParsing = false, ODataUriResolver resolver = null)
        {
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            keySegment = null;

            // If the current convention is not keys-as-segments, then this does not apply.
            if (!urlConvention.GenerateKeyAsSegment)
            {
                return(false);
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return(false);
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return(false);
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;

            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return(false);
            }

            // If the resource type has more than 1 key property, then do not treat the segment as a key.
            var keyProperties = targetEntityType.Key().ToList();

            if (keyProperties.Count > 1)
            {
                return(false);
            }

            // At this point it must be treated as a key, so fail if it is malformed.
            Debug.Assert(keyProperties.Count == 1, "keyProperties.Count == 1");
            keySegment = CreateKeySegment(previous, previousKeySegment, SegmentArgumentParser.FromSegment(segmentText, enableUriTemplateParsing), resolver);

            return(true);
        }
 /// <summary>
 /// Private constructor since the singleton instance is sufficient.
 /// </summary>
 /// <param name="urlConventions">Whether use key as segment</param>
 public PathSegmentToResourcePathTranslator(UrlConvention urlConventions)
 {
     KeySerializer = KeySerializer.Create(urlConventions);
 }
 /// <summary>
 /// Private constructor since the singleton instance is sufficient.
 /// </summary>
 /// <param name="keyAsSegment">Whether use key as segment</param>
 private PathSegmentToContextUrlPathTranslator(bool keyAsSegment)
 {
     KeySerializer = KeySerializer.Create(UrlConvention.CreateWithExplicitValue(keyAsSegment));
 }
Пример #29
0
        public ODataEntryTests()
        {
            this.odataEntry = new ODataEntry();

            this.odataEntryWithFullBuilder = new ODataEntry
            {
                TypeName   = "ns.DerivedType",
                Properties = new[]
                {
                    new ODataProperty {
                        Name = "Id", Value = 1, SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.Key
                        }
                    },
                    new ODataProperty {
                        Name = "Name", Value = "Bob", SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.ETag
                        }
                    }
                }
            };
            var serializationInfo = new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.BaseType", ExpectedTypeName = "ns.BaseType"
            };
            var typeContext          = ODataFeedAndEntryTypeContext.Create(serializationInfo, null, null, null, EdmCoreModel.Instance, true);
            var metadataContext      = new TestMetadataContext();
            var entryMetadataContext = ODataEntryMetadataContext.Create(this.odataEntryWithFullBuilder, typeContext, serializationInfo, null, metadataContext, SelectedPropertiesNode.EntireSubtree);

            this.odataEntryWithFullBuilder.MetadataBuilder = new ODataConventionalEntityMetadataBuilder(entryMetadataContext, metadataContext, new ODataConventionalUriBuilder(new Uri("http://service/", UriKind.Absolute), UrlConvention.CreateWithExplicitValue(false)));

            this.odataEntryWithNullBuilder = new ODataEntry {
                MetadataBuilder = ODataEntityMetadataBuilder.Null
            };
        }
Пример #30
0
        public ODataOperationTests()
        {
            this.testSubject = new TestODataOperation();

            var entry = new ODataEntry
            {
                TypeName   = "ns.DerivedType",
                Properties = new[]
                {
                    new ODataProperty {
                        Name = "Id", Value = 1, SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.Key
                        }
                    },
                    new ODataProperty {
                        Name = "Name", Value = "Bob", SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.ETag
                        }
                    }
                }
            };

            var serializationInfo = new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.BaseType", ExpectedTypeName = "ns.BaseType"
            };
            var typeContext          = ODataFeedAndEntryTypeContext.Create(serializationInfo, null, null, null, EdmCoreModel.Instance, true);
            var metadataContext      = new TestMetadataContext();
            var entryMetadataContext = ODataEntryMetadataContext.Create(entry, typeContext, serializationInfo, null, metadataContext, SelectedPropertiesNode.EntireSubtree);
            var fullMetadataBuilder  = new ODataConventionalEntityMetadataBuilder(entryMetadataContext, metadataContext, new ODataConventionalUriBuilder(ServiceUri, UrlConvention.CreateWithExplicitValue(false)));

            this.operationWithFullBuilder = new TestODataOperation {
                Metadata = ContextUri
            };
            this.operationWithFullBuilder.SetMetadataBuilder(fullMetadataBuilder, MetadataDocumentUri);
        }
Пример #31
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="urlConvention">The current url convention for the server.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, ODataPathSegment previous, KeySegment previousKeySegment, UrlConvention urlConvention, out KeySegment keySegment, bool enableUriTemplateParsing = false, ODataUriResolver resolver = null)
        {
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            keySegment = null;

            // If the current convention does not support keys-as-segments, then this does not apply.
            if (!(urlConvention.GenerateKeyAsSegment || urlConvention.ODataSimplified))
            {
                return(false);
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return(false);
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return(false);
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;

            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return(false);
            }

            // Previously KeyAsSegment only allows single key, but we can also leverage related key finder to auto fill
            // missed key value from referential constraint information, which would be done in CreateKeySegment.
            // CreateKeySegment method will check whether key properties are missing after taking in related key values.
            keySegment = CreateKeySegment(previous, previousKeySegment, SegmentArgumentParser.FromSegment(segmentText, enableUriTemplateParsing), resolver);

            return(true);
        }