/// <summary>
        /// Validates property uniqueness.
        /// </summary>
        /// <param name="property">The property.</param>
        public void ValidatePropertyUniqueness(ODataNestedResourceInfo property)
        {
            State state;

            if (!propertyState.TryGetValue(property.Name, out state))
            {
                propertyState[property.Name] = State.NestedResource;
            }
            else
            {
                if (state != State.AssociationLink)
                {
                    throw new ODataException(
                              Strings.DuplicatePropertyNamesNotAllowed(
                                  property.Name));
                }
                else
                {
                    propertyState[property.Name] = State.AssociationLink | State.NestedResource;
                }
            }
        }
        internal static IEdmNavigationProperty ValidateNestedResourceInfo(
            ODataNestedResourceInfo nestedResourceInfo,
            IEdmStructuredType declaringStructuredType,
            ODataPayloadKind?expandedPayloadKind,
            bool throwOnUndeclaredProperty)
        {
            Debug.Assert(nestedResourceInfo != null, "nestedResourceInfo != null");
            Debug.Assert(
                !expandedPayloadKind.HasValue ||
                expandedPayloadKind.Value == ODataPayloadKind.EntityReferenceLink ||
                expandedPayloadKind.Value == ODataPayloadKind.Resource ||
                expandedPayloadKind.Value == ODataPayloadKind.ResourceSet,
                "If an expanded payload kind is specified it must be resource, resource set or entity reference link.");

            // Navigation link must have a non-empty name
            if (string.IsNullOrEmpty(nestedResourceInfo.Name))
            {
                throw new ODataException(Strings.ValidationUtils_LinkMustSpecifyName);
            }

            // If we write an entity reference link, don't validate the multiplicity of the IsCollection
            // property if it is 'false' (since we allow writing a singleton navigation link for
            // a collection navigation property in requests) nor the consistency of payload kind and metadata
            // (which is done separately in ODataWriterCore.CheckForNestedResourceInfoWithContent).
            bool isEntityReferenceLinkPayload = expandedPayloadKind == ODataPayloadKind.EntityReferenceLink;

            // true only if the expandedPayloadKind has a value and the value is 'Resource Set'
            bool isResourceSetPayload = expandedPayloadKind == ODataPayloadKind.ResourceSet;

            // Make sure the IsCollection property agrees with the payload kind for resource and resource set payloads
            Func <object, string> errorTemplate = null;

            if (!isEntityReferenceLinkPayload && nestedResourceInfo.IsCollection.HasValue && expandedPayloadKind.HasValue)
            {
                // For resource set/resource make sure the IsCollection property is set correctly.
                if (isResourceSetPayload != nestedResourceInfo.IsCollection.Value)
                {
                    errorTemplate = expandedPayloadKind.Value == ODataPayloadKind.ResourceSet
                        ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithResourceSetContent
                        : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithResourceContent;
                }
            }

            IEdmNavigationProperty navigationProperty = null;

            if (errorTemplate == null && declaringStructuredType != null)
            {
                navigationProperty = ValidateNavigationPropertyDefined(nestedResourceInfo.Name, declaringStructuredType, throwOnUndeclaredProperty);
                if (navigationProperty != null)
                {
                    bool isCollectionType = navigationProperty.Type.TypeKind() == EdmTypeKind.Collection;

                    // Make sure the IsCollection property agrees with the metadata type for resource and resource set payloads
                    if (nestedResourceInfo.IsCollection.HasValue && isCollectionType != nestedResourceInfo.IsCollection)
                    {
                        // Ignore the case where IsCollection is 'false' and we are writing an entity reference link
                        // (see comment above)
                        if (!(nestedResourceInfo.IsCollection == false && isEntityReferenceLinkPayload))
                        {
                            errorTemplate = isCollectionType
                                ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithResourceSetMetadata
                                : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithResourceMetadata;
                        }
                    }

                    // Make sure that the payload kind agrees with the metadata.
                    // For entity reference links we check separately in ODataWriterCore.CheckForNestedResourceInfoWithContent.
                    if (!isEntityReferenceLinkPayload && expandedPayloadKind.HasValue && isCollectionType != isResourceSetPayload)
                    {
                        errorTemplate = isCollectionType
                            ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkWithResourcePayloadAndResourceSetMetadata
                            : Strings.WriterValidationUtils_ExpandedLinkWithResourceSetPayloadAndResourceMetadata;
                    }
                }
            }

            if (errorTemplate != null)
            {
                string uri = nestedResourceInfo.Url == null ? "null" : UriUtils.UriToString(nestedResourceInfo.Url);
                throw new ODataException(errorTemplate(uri));
            }

            return(navigationProperty);
        }
Beispiel #3
0
 /// <summary>
 /// Validates that the specified nested resource info has cardinality set, i.e., it has the
 /// IsCollection value set.
 /// </summary>
 /// <param name="nestedResourceInfo">The nested resource info to validate.</param>
 public virtual void ValidateNestedResourceInfoHasCardinality(
     ODataNestedResourceInfo nestedResourceInfo)
 {
     WriterValidationUtils.ValidateNestedResourceInfoHasCardinality(nestedResourceInfo);
 }
Beispiel #4
0
 /// <summary>
 /// Asynchronously start writing a nested resource info.
 /// </summary>
 /// <param name="nestedResourceInfo">The nested resource info to write.</param>
 /// <returns>A task instance that represents the asynchronous write operation.</returns>
 public abstract Task WriteStartAsync(ODataNestedResourceInfo nestedResourceInfo);
Beispiel #5
0
 /// <summary>
 /// Start writing a nested resource info.
 /// </summary>
 /// <param name="nestedResourceInfo">The nested resource info to write.</param>
 public abstract void WriteStart(ODataNestedResourceInfo nestedResourceInfo);
Beispiel #6
0
 /// <summary>Writes a nested resource info.</summary>
 /// <param name="nestedResourceInfo">The nested resource info to write.</param>
 /// <returns>This ODataWriter, allowing for chaining operations.</returns>
 public ODataWriter Write(ODataNestedResourceInfo nestedResourceInfo)
 {
     WriteStart(nestedResourceInfo);
     WriteEnd();
     return(this);
 }
Beispiel #7
0
 /// <summary> Asynchronously start writing a nested resource info. </summary>
 /// <returns>A task instance that represents the asynchronous write operation.</returns>
 /// <param name="nestedResourceInfo">The nested resource info to writer.</param>
 public virtual Task WriteStartAsync(ODataNestedResourceInfo nestedResourceInfo)
 {
     return(TaskUtils.GetTaskForSynchronousOperation(() => this.WriteStart(nestedResourceInfo)));
 }
 public void ValidatePropertyUniqueness(ODataNestedResourceInfo property)
 {
     // nop
 }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataWriter"/> for <paramref name="nestedResourceInfo"/>.
 /// </summary>
 /// <param name="nestedResourceInfo">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataNestedResourceInfo nestedResourceInfo, ODataNestedResourceInfoSerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(nestedResourceInfo, "resource");
     nestedResourceInfo.SerializationInfo = serializationInfo;
 }
Beispiel #10
0
        public void MaterializeEntityShouldWork()
        {
            var odataEntry = new OData.ODataResource()
            {
                Id = new Uri("http://www.odata.org/service.svc/entitySet(1)")
            };

            odataEntry.Properties = new OData.ODataProperty[]
            {
                new OData.ODataProperty {
                    Name = "keyProp", Value = 1
                },
                new OData.ODataProperty {
                    Name = "colorProp", Value = new OData.ODataEnumValue("blue")
                },
                new OData.ODataProperty {
                    Name  = "primitiveCollection",
                    Value = new OData.ODataCollectionValue
                    {
                        TypeName = "Edm.Int32",
                        Items    = new List <object> {
                            1, 2, 3
                        }
                    }
                },
                new OData.ODataProperty {
                    Name  = "enumCollection",
                    Value = new OData.ODataCollectionValue
                    {
                        TypeName = "color",
                        Items    = new List <OData.ODataEnumValue> {
                            new OData.ODataEnumValue("white"), new OData.ODataEnumValue("blue")
                        }
                    }
                }
            };

            var complexP = new OData.ODataNestedResourceInfo()
            {
                Name         = "complexProp",
                IsCollection = false
            };

            var complexResource = new OData.ODataResource
            {
                Properties = new OData.ODataProperty[]
                {
                    new OData.ODataProperty {
                        Name = "age", Value = 11
                    },
                    new OData.ODataProperty {
                        Name = "name", Value = "June"
                    }
                }
            };

            var complexColP = new OData.ODataNestedResourceInfo
            {
                Name         = "complexCollection",
                IsCollection = true
            };

            var complexColResourceSet = new OData.ODataResourceSet();

            var items = new List <OData.ODataResource>
            {
                new OData.ODataResource
                {
                    Properties = new OData.ODataProperty[]
                    {
                        new OData.ODataProperty {
                            Name = "name", Value = "Aug"
                        },
                        new OData.ODataProperty {
                            Name = "age", Value = 8
                        },
                        new OData.ODataProperty {
                            Name = "color", Value = new OData.ODataEnumValue("white")
                        }
                    }
                },
                new OData.ODataResource
                {
                    Properties = new OData.ODataProperty[]
                    {
                        new OData.ODataProperty {
                            Name = "name", Value = "Sep"
                        },
                        new OData.ODataProperty {
                            Name = "age", Value = 9
                        },
                        new OData.ODataProperty {
                            Name = "color", Value = new OData.ODataEnumValue("blue")
                        }
                    }
                }
            };

            var clientEdmModel    = new ClientEdmModel(ODataProtocolVersion.V4);
            var context           = new DataServiceContext();
            var materializerEntry = MaterializerEntry.CreateEntry(odataEntry, OData.ODataFormat.Json, true, clientEdmModel);

            MaterializerNavigationLink.CreateLink(complexP, MaterializerEntry.CreateEntry(complexResource, OData.ODataFormat.Json, true, clientEdmModel));
            MaterializerFeed.CreateFeed(complexColResourceSet, items);
            MaterializerNavigationLink.CreateLink(complexColP, complexColResourceSet);

            var materializerContext = new TestMaterializerContext()
            {
                Model = clientEdmModel, Context = context
            };
            var             adapter    = new EntityTrackingAdapter(new TestEntityTracker(), MergeOption.OverwriteChanges, clientEdmModel, context);
            QueryComponents components = new QueryComponents(new Uri("http://foo.com/Service"), new Version(4, 0), typeof(EntityType), null, new Dictionary <Expression, Expression>());

            var entriesMaterializer = new ODataEntriesEntityMaterializer(new OData.ODataResource[] { odataEntry }, materializerContext, adapter, components, typeof(EntityType), null, OData.ODataFormat.Json);

            var customersRead = new List <EntityType>();

            while (entriesMaterializer.Read())
            {
                customersRead.Add(entriesMaterializer.CurrentValue as EntityType);
            }

            customersRead.Should().HaveCount(1);
            customersRead[0].KeyProp.Should().Be(1);
            customersRead[0].ComplexProp.Should().Equals(new ComplexType {
                Age = 11, Name = "June"
            });
            customersRead[0].ColorProp.Should().Equals(Color.Blue);
            customersRead[0].PrimitiveCollection.Should().Equals(new List <int> {
                1, 2, 3
            });
            ComplexType complex1 = new ComplexType {
                Name = "Aug", Age = 8, Color = Color.White
            };
            ComplexType complex2 = new ComplexType {
                Name = "Sep", Age = 9, Color = Color.Blue
            };

            customersRead[0].ComplexCollection.Should().Equals(new List <ComplexType> {
                complex1, complex2
            });
            customersRead[0].EnumCollection.Should().Equals(new List <Color> {
                Color.White, Color.Blue
            });
        }