/// <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); } }
/// <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); }
public void UrlConventionFromSettingAndTypeContextShouldReturnKeyAsSegmentIfSettingIsNullAndTypeContextReturnsKeyAsSegment() { var typeContext = new TestFeedAndEntryTypeContext() { UrlConvention = UrlConvention.CreateWithExplicitValue(/*generateKeyAsSegment*/ true) }; UrlConvention.ForUserSettingAndTypeContext(null, typeContext).GenerateKeyAsSegment.Should().BeTrue(); }
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(); }
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(); }
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); }
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 }; }
/// <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; }
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>(); }
/// <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); }
/// <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; }
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)); }
/// <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)); }
/// <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)); }
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(); }
/// <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; }
/// <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); }
/// <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); }
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)); }
/// <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)); }
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 }; }
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); }
/// <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); }