Esempio n. 1
0
        public void CanRenamePropertiesInRegularModelBuilder()
        {
            HttpRequestMessage  request  = new HttpRequestMessage(HttpMethod.Get, BaseAddress + "/explicit/$metadata");
            HttpResponseMessage response = Client.SendAsync(request).Result;
            IEdmModel           model    = CsdlReader.Parse(XmlReader.Create(response.Content.ReadAsStreamAsync().Result));
            // Can change the name of regular, complex and navigation properties.
            IEdmEntityType customer = model.FindDeclaredType("ModelAliasing.Customer") as IEdmEntityType;

            Assert.NotNull(customer);
            Assert.NotNull(customer.FindProperty("FinancialAddress"));
            Assert.NotNull(customer.FindProperty("ClientName"));
            Assert.NotNull(customer.FindProperty("Purchases"));
            // Can change the name of properties on complex objects
            IEdmComplexType address = model.FindDeclaredType("Location.Direction") as IEdmComplexType;

            Assert.NotNull(address);
            Assert.NotNull(address.FindProperty("Reign"));
            //Can change the name of properties on derived entities.
            IEdmEntityType expressOrder = model.FindDeclaredType("Purchasing.ExpressOrder") as IEdmEntityType;

            Assert.NotNull(expressOrder);
            //Can change the name of properties on derived entities when added explicitly.
            Assert.NotNull(expressOrder.FindProperty("Fee"));
            //Data contract attribute doesn't change the name of the property.
            Assert.Null(expressOrder.FindProperty("DeliveryDate"));
            Assert.Null(expressOrder.FindProperty("GuanteedDeliveryDate"));
            // Data contract attribute doesn't change the names of the properties
            IEdmEntityType ordersLines = model.FindDeclaredType("WebStack.QA.Test.OData.ModelAliasing.ModelAliasingMetadataOrderLine") as IEdmEntityType;

            Assert.NotNull(ordersLines);
            Assert.Null(ordersLines.FindProperty("Product"));
            Assert.NotNull(ordersLines.FindProperty("Item"));
            // Data contract attribute doesn't override any explicit configuration on the model builder
            Assert.NotNull(ordersLines.FindProperty("Cost"));
        }
Esempio n. 2
0
        public async Task CanRenamePropertiesInConventionModelBuilder()
        {
            HttpRequestMessage  request  = new HttpRequestMessage(HttpMethod.Get, BaseAddress + "/convention/$metadata");
            HttpResponseMessage response = await Client.SendAsync(request);

            IEdmModel model = CsdlReader.Parse(XmlReader.Create(await response.Content.ReadAsStreamAsync()));
            // Can change the name of regular, complex and navigation properties.
            IEdmEntityType customer = model.FindDeclaredType("ModelAliasing.Customer") as IEdmEntityType;

            Assert.NotNull(customer);
            Assert.NotNull(customer.FindProperty("FinancialAddress"));
            Assert.NotNull(customer.FindProperty("ClientName"));
            Assert.NotNull(customer.FindProperty("Purchases"));
            // Can change the name of properties on complex objects
            IEdmComplexType address = model.FindDeclaredType("Location.Direction") as IEdmComplexType;

            Assert.NotNull(address);
            Assert.NotNull(address.FindProperty("Reign"));
            //Can change the name of properties on derived entities.
            IEdmEntityType expressOrder = model.FindDeclaredType("Purchasing.ExpressOrder") as IEdmEntityType;

            Assert.NotNull(expressOrder);
            //Can change the name of properties on derived entities when added explicitly.
            Assert.NotNull(expressOrder.FindProperty("Fee"));
            //Can change the name of properties on derived entities using data contract attribute.
            Assert.NotNull(expressOrder.FindProperty("DeliveryDate"));
            // Can change the name of the properties using DataContract attribute
            IEdmEntityType ordersLines = model.FindDeclaredType("Billing.OrderLine") as IEdmEntityType;

            Assert.NotNull(ordersLines);
            Assert.NotNull(ordersLines.FindProperty("Product"));
            // Data contract attribute override any explicit configuration on the model builder
            Assert.NotNull(ordersLines.FindProperty("Cost"));
        }
        public void ReadMetadataDocument_WorksForJsonCSDL()
        {
            Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{
  ""$Version"": ""4.0"",
  ""$EntityContainer"": ""NS.Container"",
  ""NS"": {
    ""Customer"": {
      ""$Kind"": ""EntityType"",
      ""$Key"": [
        ""Id""
      ],
      ""Id"": {
        ""$Type"": ""Edm.Int32""
      },
      ""Name"": {}
    },
    ""Container"": {
      ""$Kind"": ""EntityContainer"",
      ""Customers"": {
        ""$Collection"": true,
        ""$Type"": ""NS.Customer""
      }
    }
  }
}"));

            IODataResponseMessage responseMessage = new InMemoryMessage()
            {
                StatusCode = 200, Stream = stream
            };

            responseMessage.SetHeader("Content-Type", "application/json");
            ODataMessageReader reader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), new EdmModel());

#if NETCOREAPP3_1 || NETCOREAPP2_1
            IEdmModel model = reader.ReadMetadataDocument();

            IEdmEntityType customerType = model.FindDeclaredType("NS.Customer") as IEdmEntityType;
            Assert.NotNull(customerType);

            IEdmProperty idProperty = customerType.FindProperty("Id");
            Assert.NotNull(idProperty);
            Assert.Equal("Edm.Int32", idProperty.Type.FullName());

            IEdmProperty nameProperty = customerType.FindProperty("Name");
            Assert.NotNull(nameProperty);
            Assert.Equal("Edm.String", nameProperty.Type.FullName());

            IEdmEntitySet customers = Assert.Single(model.EntityContainer.EntitySets());
            Assert.Equal("Customers", customers.Name);
            Assert.Same(customerType, customers.EntityType());
#else
            Action test = () => reader.ReadMetadataDocument();

            ODataException exception = Assert.Throws <ODataException>(test);
            Assert.Equal("The JSON metadata is not supported at this platform. It's only supported at platform implementing .NETStardard 2.0.", exception.Message);
#endif
        }
        private IEdmNavigationProperty ResolveNavigationPropertyPathForBinding(CsdlNavigationPropertyBinding binding)
        {
            Debug.Assert(binding != null, "binding != null");

            string bindingPath = binding.Path;

            Debug.Assert(bindingPath != null, "bindingPath != null");

            IEdmEntityType definingType = this.typeCache.GetValue(this, ComputeElementTypeFunc, null);

            const char Slash = '/';

            if (bindingPath.Length == 0 || bindingPath[bindingPath.Length - 1] == Slash)
            {
                // if the path did not actually contain a navigation property, then treat it as an unresolved path.
                // TODO: improve the error given in this case?
                return(new UnresolvedNavigationPropertyPath(definingType, bindingPath, binding.Location));
            }

            IEdmNavigationProperty navigationProperty;

            string[] pathSegements = bindingPath.Split(Slash);
            for (int index = 0; index < pathSegements.Length - 1; index++)
            {
                string pathSegement = pathSegements[index];
                if (pathSegement.Length == 0)
                {
                    // TODO: improve the error given in this case?
                    return(new UnresolvedNavigationPropertyPath(definingType, bindingPath, binding.Location));
                }

                IEdmEntityType derivedType = this.container.Context.FindType(pathSegement) as IEdmEntityType;
                if (derivedType == null)
                {
                    IEdmProperty property = definingType.FindProperty(pathSegement);
                    navigationProperty = property as IEdmNavigationProperty;
                    if (navigationProperty == null)
                    {
                        return(new UnresolvedNavigationPropertyPath(definingType, bindingPath, binding.Location));
                    }

                    definingType = navigationProperty.ToEntityType();
                }
                else
                {
                    definingType = derivedType;
                }
            }

            navigationProperty = definingType.FindProperty(pathSegements.Last()) as IEdmNavigationProperty;
            if (navigationProperty == null)
            {
                // TODO: improve the error given in this case?
                navigationProperty = new UnresolvedNavigationPropertyPath(definingType, bindingPath, binding.Location);
            }

            return(navigationProperty);
        }
Esempio n. 5
0
        public void LocateEntityContainer()
        {
            const string csdl =
                @"<?xml version=""1.0"" encoding=""utf-16""?>
<Schema Namespace=""Hot"" Alias=""Fuzz"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
  <EntityType Name=""Person"">
    <Key>
      <PropertyRef Name=""Id"" />
    </Key>
    <Property Name=""Id"" Type=""Int32"" Nullable=""false"" />
    <Property Name=""Address"" Type=""String"" MaxLength=""100"" />
  </EntityType>
  <EntityType Name=""Pet"">
    <Key>
      <PropertyRef Name=""PetId"" />
    </Key>
    <Property Name=""Id"" Type=""Int32"" Nullable=""false"" />
    <Property Name=""OwnerId"" Type=""Int32"" Nullable=""false"" />
  </EntityType>
  <EntityContainer Name=""Wild"">
    <EntitySet Name=""People"" EntityType=""Hot.Person"" />
    <EntitySet Name=""Pets"" EntityType=""Hot.Pet"" />
  </EntityContainer>
</Schema>";

            IEdmModel model;
            IEnumerable <EdmError> errors;
            bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors);

            Assert.IsTrue(parsed, "parsed");
            Assert.IsTrue(errors.Count() == 0, "No errors");

            IEdmEntityType person        = (IEdmEntityType)model.FindType("Hot.Person");
            IEdmProperty   personId      = person.FindProperty("Id");
            IEdmProperty   personAddress = person.FindProperty("Address");
            IEdmEntityType pet           = (IEdmEntityType)model.FindType("Hot.Pet");
            IEdmProperty   petId         = pet.FindProperty("Id");
            IEdmProperty   ownerId       = pet.FindProperty("OwnerId");

            IEdmEntityContainer wild   = model.EntityContainer;
            IEdmEntitySet       people = model.EntityContainer.FindEntitySet("People");
            IEdmEntitySet       pets   = model.EntityContainer.FindEntitySet("Pets");

            AssertCorrectLocation((CsdlLocation)person.Location(), csdl, @"EntityType Name=""Person""");
            AssertCorrectLocation((CsdlLocation)personId.Location(), csdl, @"Property Name=""Id"" Type=""Int32"" Nullable=""false""");
            AssertCorrectLocation((CsdlLocation)personAddress.Location(), csdl, @"Property Name=""Address"" Type=""String"" MaxLength=""100"" ");
            AssertCorrectLocation((CsdlLocation)pet.Location(), csdl, @"EntityType Name=""Pet""");
            AssertCorrectLocation((CsdlLocation)petId.Location(), csdl, @"Property Name=""Id"" Type=""Int32"" Nullable=""false"" ");
            AssertCorrectLocation((CsdlLocation)ownerId.Location(), csdl, @"Property Name=""OwnerId"" Type=""Int32"" Nullable=""false"" ");
            AssertCorrectLocation((CsdlLocation)wild.Location(), csdl, @"EntityContainer Name=""Wild""");
            AssertCorrectLocation((CsdlLocation)people.Location(), csdl, @"EntitySet Name=""People"" EntityType=""Hot.Person"" ");
            AssertCorrectLocation((CsdlLocation)pets.Location(), csdl, @"EntitySet Name=""Pets"" EntityType=""Hot.Pet"" ");
        }
Esempio n. 6
0
        private static void AnnotationsThreadFunction(object o)
        {
            IEdmModel model = (IEdmModel)o;

            IEdmEntityType person = model.FindEntityType("foo.Person");
            IEdmProperty   name   = person.FindProperty("Name");

            string bogus = "http://bogus.com";
            string goop  = "goop";
            string droop = "droop";
            string scoop = "scoop";

            int index = ++ThreadIndex;

            for (int i = 0; i < 10000; i++)
            {
                var setters = new IEdmDirectValueAnnotationBinding[]
                {
                    new EdmDirectValueAnnotationBinding(person, bogus, goop, index),
                    new EdmDirectValueAnnotationBinding(person, bogus, droop, index),
                    new EdmDirectValueAnnotationBinding(person, bogus, scoop, index),
                    new EdmDirectValueAnnotationBinding(name, bogus, goop, index),
                    new EdmDirectValueAnnotationBinding(name, bogus, droop, index),
                    new EdmDirectValueAnnotationBinding(name, bogus, scoop, index)
                };

                model.SetAnnotationValues(setters);
            }
        }
Esempio n. 7
0
        private IEdmNavigationProperty ComputePartner()
        {
            string partnerPropertyName = this.navigationProperty.Partner;

            IEdmEntityType targetEntityType = this.TargetEntityType;

            if (partnerPropertyName != null)
            {
                var partner = targetEntityType.FindProperty(partnerPropertyName) as IEdmNavigationProperty;

                if (partner == null)
                {
                    partner = new UnresolvedNavigationPropertyPath(targetEntityType, partnerPropertyName, this.Location);
                }

                return(partner);
            }

            foreach (IEdmNavigationProperty potentialPartner in targetEntityType.NavigationProperties())
            {
                if (potentialPartner == this)
                {
                    continue;
                }

                if (potentialPartner.Partner == this)
                {
                    return(potentialPartner);
                }
            }

            return(null);
        }
Esempio n. 8
0
        public void PrimitiveExamplevalueInitializeWorksForPrimitiveData(string data, object except)
        {
            // Arrange
            string annotation = $@"<Annotation Term=""Org.OData.Core.V1.Example"">
                <Record Type=""Org.OData.Core.V1.PrimitiveExampleValue"">
                  <PropertyValue Property=""Description"" String=""Primitive example value"" />
                  <PropertyValue Property=""Value"" {data} />
                </Record>
              </Annotation>";

            IEdmModel model = GetEdmModel(annotation);

            Assert.NotNull(model); // guard

            IEdmEntityType customer = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer");

            Assert.NotNull(customer); // guard
            IEdmProperty dataProperty = customer.FindProperty("Data");

            Assert.NotNull(dataProperty);

            // Act
            PrimitiveExampleValue value = model.GetRecord <PrimitiveExampleValue>(dataProperty, "Org.OData.Core.V1.Example");

            // Assert
            Assert.NotNull(value);
            Assert.Equal("Primitive example value", value.Description);
            Assert.NotNull(value.Value);
            Assert.Equal(except, value.Value.Value);
        }
Esempio n. 9
0
        public void EvaluateUnboundTerms()
        {
            const string applicationCsdl =
                @"<Schema Namespace=""bar"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
    <Annotations Target=""bar.Person"">
        <Annotation Term=""bar.RandomTerm"" Path=""Extra"" />
    </Annotations>
    <EntityType Name=""Person"">
        <Key>
            <PropertyRef Name=""Name"" />
        </Key>
        <Property Name=""Name"" Type=""String"" Nullable=""false"" />
        <Property Name=""Decoration"" Type=""bar.Decoration"">
            <Annotation Term=""bar.DecorationTerm"" Qualifier=""Goodness"" String=""Excellent"" />
        </Property>
    </EntityType>
    <ComplexType Name=""Decoration"">
        <Property Name=""One"" Type=""Int32"" />
        <Property Name=""Two"" Type=""Int32"" />
    </ComplexType>
</Schema>";
            IEdmModel      applicationModel = this.Parse(applicationCsdl);
            IEdmEntityType person           = (IEdmEntityType)applicationModel.FindType("bar.Person");
            IEdmProperty   personDecoration = person.FindProperty("Decoration");

            EdmToClrEvaluator evaluator = new EdmToClrEvaluator(null);

            List <IEdmPropertyValue> decorationPropertyValues = new List <IEdmPropertyValue>();

            decorationPropertyValues.Add(new EdmPropertyValue("One", new EdmIntegerConstant(1)));
            decorationPropertyValues.Add(new EdmPropertyValue("Two", new EdmIntegerConstant(2)));

            List <IEdmPropertyValue> propertyValues = new List <IEdmPropertyValue>();

            propertyValues.Add(new EdmPropertyValue("Name", new EdmStringConstant("Goober")));
            propertyValues.Add(new EdmPropertyValue("Decoration", new EdmStructuredValue(null, decorationPropertyValues)));
            propertyValues.Add(new EdmPropertyValue("Extra", new EdmStringConstant("Extra value!")));
            IEdmStructuredValue context = new EdmStructuredValue(new EdmEntityTypeReference(person, false), propertyValues);

            string random = applicationModel.GetTermValue <string>(context, "bar.RandomTerm", evaluator);

            Assert.AreEqual("Extra value!", random, "Annotation evaluated value.");

            IEdmValue randomValue = applicationModel.GetTermValue(context, "bar.RandomTerm", evaluator);

            Assert.AreEqual("Extra value!", ((IEdmStringValue)randomValue).Value, "Annotation evaluated value.");

            string goodness = applicationModel.GetTermValue <string>(personDecoration, "bar.DecorationTerm", "Goodness", evaluator);

            Assert.AreEqual("Excellent", goodness, "Annotation evaluated value.");

            IEdmValue goodnessValue = applicationModel.GetTermValue(personDecoration, "bar.DecorationTerm", "Goodness", evaluator);

            Assert.AreEqual("Excellent", ((IEdmStringValue)goodnessValue).Value, "Annotation evaluated value.");

            IEdmVocabularyAnnotation randomTermAnnotation = applicationModel.FindVocabularyAnnotations <IEdmVocabularyAnnotation>(person, "bar.RandomTerm").Single();

            random = evaluator.EvaluateToClrValue <string>(randomTermAnnotation.Value, context);
            Assert.AreEqual("Extra value!", random, "Annotation evaluated value.");
        }
Esempio n. 10
0
 /// <summary>
 /// Validates an <see cref="ODataNavigationLink"/> to ensure all required information is specified and valid.
 /// </summary>
 /// <param name="navigationLink">The navigation link to validate.</param>
 /// <param name="declaringEntityType">The <see cref="IEdmEntityType"/> declaring the navigation property; or null if metadata is not available.</param>
 /// <param name="expandedPayloadKind">The <see cref="ODataPayloadKind"/> of the expanded content of this navigation link or null for deferred links.</param>
 /// <returns>The type of the navigation property for this navigation link; or null if no <paramref name="declaringEntityType"/> was specified.</returns>
 public IEdmNavigationProperty ValidateNavigationLink(
     ODataNavigationLink navigationLink,
     IEdmEntityType declaringEntityType,
     ODataPayloadKind?expandedPayloadKind)
 {
     return(declaringEntityType == null ? null : declaringEntityType.FindProperty(navigationLink.Name) as IEdmNavigationProperty);
 }
        public void TryMatchMediaType_DoesnotMatchRequest_ODataEnumValueMediaTypeMappingWithNonRawvalueRequest()
        {
            // Arrange
            IEdmModel      model          = GetEnumModel();
            IEdmEntitySet  enumEntity     = model.EntityContainer.FindEntitySet("EnumEntity");
            IEdmEntityType enumEntityType =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "EnumEntity");

            IEdmStructuralProperty property = enumEntityType.FindProperty("EnumProperty") as IEdmStructuralProperty;

            Assert.NotNull(property); // Guard
            PropertySegment propertySegment = new PropertySegment(property);

            var        keys       = new[] { new KeyValuePair <string, object>("Id", 1) };
            KeySegment keySegment = new KeySegment(keys, enumEntityType, enumEntity);

            ODataPath path = new ODataPath(new EntitySetSegment(enumEntity), keySegment, propertySegment);
            ODataEnumValueMediaTypeMapping mapping = new ODataEnumValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/EnumEntity(1)/EnumProperty/");

            request.ODataContext().Path = path;

            // Act
            double mapResult = mapping.TryMatchMediaType(request);

            // Assert
            Assert.Equal(0, mapResult);
        }
        public void TryMatchMediaType_MatchesRequest_WithEnumRawValue()
        {
            // Arrange
            IEdmModel model = GetEnumModel();

            IEdmEntitySet  enumEntity     = model.EntityContainer.FindEntitySet("EnumEntity");
            IEdmEntityType enumEntityType =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "EnumEntity");

            IEdmStructuralProperty property = enumEntityType.FindProperty("EnumProperty") as IEdmStructuralProperty;

            Assert.NotNull(property); // Guard
            PropertySegment propertySegment = new PropertySegment(property);

            var        keys       = new[] { new KeyValuePair <string, object>("Id", 1) };
            KeySegment keySegment = new KeySegment(keys, enumEntityType, enumEntity);

            ODataPath path = new ODataPath(new EntitySetSegment(enumEntity), keySegment, propertySegment, new ValueSegment(propertySegment.EdmType));
            ODataEnumValueMediaTypeMapping mapping = new ODataEnumValueMediaTypeMapping();
            HttpRequestMessage             request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/EnumEntity(1)/EnumProperty/$value");

            request.ODataProperties().Path = path;

            // Act
            double mapResult = mapping.TryMatchMediaType(request);

            // Assert
            Assert.Equal(1.0, mapResult);
        }
        private bool IsRequired(PropertyInfo propertyInfo)
        {
            IEdmEntityType entityType  = GetEntityTypeByName(propertyInfo.DeclaringType.FullName);
            IEdmProperty   edmProperty = entityType.FindProperty(propertyInfo.Name);

            return(!edmProperty.Type.IsNullable);
        }
        public void TryMatchMediaType_WithNonRawvalueRequest_DoesntMatchRequest()
        {
            IEdmModel      model      = ODataTestUtil.GetEdmModel();
            IEdmEntitySet  people     = model.EntityContainer.FindEntitySet("People");
            IEdmEntityType personType =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "FormatterPerson");

            IEdmStructuralProperty ageProperty = personType.FindProperty("Age") as IEdmStructuralProperty;

            Assert.NotNull(ageProperty); // Guard
            PropertySegment propertySegment = new PropertySegment(ageProperty);

            var        keys       = new[] { new KeyValuePair <string, object>("PerId", 1) };
            KeySegment keySegment = new KeySegment(keys, personType, people);

            ODataPath path = new ODataPath(new EntitySetSegment(people), keySegment, propertySegment);
            ODataPrimitiveValueMediaTypeMapping mapping = new ODataPrimitiveValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/People(1)/Age/");

            request.ODataContext().Path = path;

            double mapResult = mapping.TryMatchMediaType(request);

            Assert.Equal(0, mapResult);
        }
        public void TryMatchMediaType_WithNonRawvalueRequest_DoesntMatchRequest_OnSingleton()
        {
            // Arrange
            IEdmModel     model     = ODataTestUtil.GetEdmModel();
            IEdmSingleton president = model.EntityContainer.FindSingleton("President");

            model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "FormatterPerson");

            IEdmEntityType personType =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "FormatterPerson");

            IEdmStructuralProperty ageProperty = personType.FindProperty("Age") as IEdmStructuralProperty;

            Assert.NotNull(ageProperty); // Guard
            PropertySegment propertySegment = new PropertySegment(ageProperty);

            ODataPath path = new ODataPath(new SingletonSegment(president), propertySegment);
            ODataPrimitiveValueMediaTypeMapping mapping = new ODataPrimitiveValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/President/Age/");

            request.ODataContext().Path = path;

            // Act
            double mapResult = mapping.TryMatchMediaType(request);

            // Assert
            Assert.Equal(0, mapResult);
        }
Esempio n. 16
0
        private void AddTypeCastsIfNecessary()
        {
            IEdmEntityType          owningType  = null;
            List <ODataPathSegment> newSegments = new List <ODataPathSegment>();

            foreach (ODataPathSegment segment in _segments)
            {
                NavigationPropertySegment navProp = segment as NavigationPropertySegment;
                if (navProp != null && owningType != null &&
                    owningType.FindProperty(navProp.NavigationProperty.Name) == null)
                {
                    // need a type cast
                    TypeSegment typeCast = new TypeSegment(
                        navProp.NavigationProperty.DeclaringType,
                        navigationSource: null);
                    newSegments.Add(typeCast);
                }

                newSegments.Add(segment);
                IEdmEntityType targetEntityType = GetTargetEntityType(segment);
                if (targetEntityType != null)
                {
                    owningType = targetEntityType;
                }
            }

            _segments = newSegments;
        }
Esempio n. 17
0
        /// <summary>
        /// Tries to resolve the name of a navigation property's target if a server model has been provided.
        /// </summary>
        /// <param name="serverSourceTypeName">The name of the server side source type.</param>
        /// <param name="navigationPropertyName">The name of the navigation property.</param>
        /// <param name="serverTypeName">The server type name if one could be found.</param>
        /// <returns>Whether the type name could be found.</returns>
        internal bool TryResolveNavigationTargetTypeName(string serverSourceTypeName, string navigationPropertyName, out string serverTypeName)
        {
            serverTypeName = null;
            if (this.serviceModel == null || serverSourceTypeName == null)
            {
                return(false);
            }

            IEdmEntityType parentServerType = this.serviceModel.FindType(serverSourceTypeName) as IEdmEntityType;

            if (parentServerType == null)
            {
                return(false);
            }

            IEdmNavigationProperty serverNavigation = parentServerType.FindProperty(navigationPropertyName) as IEdmNavigationProperty;

            if (serverNavigation == null)
            {
                return(false);
            }

            IEdmTypeReference targetType = serverNavigation.Type;

            if (targetType.IsCollection())
            {
                targetType = targetType.AsCollection().ElementType();
            }

            serverTypeName = targetType.FullName();
            return(true);
        }
            /// <summary>
            /// Returns the navigation property for the given payload element (only for entity reference links).
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the navigation property from.</param>
            /// <returns>The expected navigation property for the specified payload element.</returns>
            private static IEdmNavigationProperty GetExpectedNavigationProperty(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model)
            {
                ExceptionUtilities.Assert(model != null, "model != null");

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmNavigationProperty != null)
                    {
                        return(expectedTypeAnnotation.EdmNavigationProperty as IEdmNavigationProperty);
                    }
                    NavigationProperty expectedNavigationProperty = expectedTypeAnnotation.NavigationProperty;
                    if (expectedNavigationProperty != null)
                    {
                        NamedStructuralType expectedOwningType = expectedTypeAnnotation.OwningType;
                        ExceptionUtilities.Assert(expectedOwningType != null, "Need an owning type if a navigation property is specified.");

                        IEdmEntityType owningEntityType = model.FindType(expectedOwningType.FullName) as IEdmEntityType;
                        ExceptionUtilities.Assert(owningEntityType != null, "Did not find expected entity type in the model.");

                        IEdmNavigationProperty navigationProperty = owningEntityType.FindProperty(expectedNavigationProperty.Name) as IEdmNavigationProperty;
                        ExceptionUtilities.Assert(navigationProperty != null, "Did not find expected navigation property in the model.");

                        return(navigationProperty);
                    }
                }

                return(null);
            }
Esempio n. 19
0
        public void Term_FunctionApplication_OnNavigationProperty()
        {
            this.SetupModelsAndValues();

            const string applicationCsdl =
                @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
    <Annotations Target=""foo.Person/Address"">
        <Annotation Term=""bar.StringValue"">
            <Apply Function=""Functions.StringConcat"">
                <Path>Zip/Main</Path>
                <Apply Function=""Functions.StringConcat"">
                    <String>-</String>
                    <Path>Zip/Extension</Path>
                </Apply>
            </Apply>
        </Annotation>
    </Annotations>
</Schema>";
            IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel, this.operationsModel);
            EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup);

            IEdmEntityType    person               = this.baseModel.FindEntityType("foo.Person");
            IEdmProperty      property             = person.FindProperty("Address");
            IEdmPropertyValue contextPropertyValue = ((IEdmStructuredValue)this.personValue).FindPropertyValue("Address");

            IEdmTerm termStringValue = this.vocabularyDefinitionModel.FindTerm("bar.StringValue");
            IEdmVocabularyAnnotation annotationString = property.VocabularyAnnotations(applicationModel).SingleOrDefault(a => a.Term == termStringValue);
            IEdmValue annotationStringValue           = expressionEvaluator.Evaluate(annotationString.Value, (IEdmStructuredValue)contextPropertyValue.Value);

            Assert.AreEqual("98052-0000", ((IEdmStringValue)annotationStringValue).Value, "Term annotation value");
        }
Esempio n. 20
0
        public void Term_Path_OnProperty()
        {
            this.SetupModelsAndValues();

            const string applicationCsdl =
                @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
    <Annotations Target=""foo.Person/ContactInfo"">
        <Annotation Term=""bar.Int16Value"" Qualifier=""WorkPhoneLocal"" Path=""WorkPhone/Local"" />
    </Annotations>
</Schema>";
            IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel);
            EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup);

            IEdmEntityType    person               = this.baseModel.FindEntityType("foo.Person");
            IEdmProperty      property             = person.FindProperty("ContactInfo");
            IEdmPropertyValue contextPropertyValue = ((IEdmStructuredValue)this.personValue).FindPropertyValue("ContactInfo");

            IEdmTerm termInt16Value = this.vocabularyDefinitionModel.FindTerm("bar.Int16Value");
            // ?? Assumes Entity always??
            // IEdmValue annotationHotIndex = applicationModel.GetTermValue(contextPropertyValue.Value, termInt16Value, evaluator);
            IEdmVocabularyAnnotation annotation = property.VocabularyAnnotations(applicationModel).SingleOrDefault(a => a.Term == termInt16Value);
            IEdmExpression           expression = annotation.Value;
            IEdmValue annotationWorkphoneLocal  = expressionEvaluator.Evaluate(expression, (IEdmStructuredValue)contextPropertyValue.Value);

            Assert.AreEqual(9991234, ((IEdmIntegerValue)annotationWorkphoneLocal).Value, "Term annotation value");
        }
        public void TryMatchMediaTypeWithBinaryRawValueMatchesRequest_OnODataSingleton()
        {
            // Arrange
            IEdmModel model = GetBinaryModel();

            IEdmSingleton  rawSingletonValue = model.EntityContainer.FindSingleton("RawSingletonValue");
            IEdmEntityType rawValueEntity    =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "RawValueEntity");

            IEdmStructuralProperty property = rawValueEntity.FindProperty("BinaryProperty") as IEdmStructuralProperty;

            Assert.NotNull(property); // Guard
            PropertySegment propertySegment = new PropertySegment(property);

            ODataPath path = new ODataPath(new SingletonSegment(rawSingletonValue), propertySegment, new ValueSegment(propertySegment.EdmType));
            ODataBinaryValueMediaTypeMapping mapping = new ODataBinaryValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/RawSingletonValue/BinaryProperty/$value");

            request.ODataContext().Path = path;

            // Act
            double mapResult = mapping.TryMatchMediaType(request);

            // Assert
            Assert.Equal(1.0, mapResult);
        }
        public void TryMatchMediaTypeWithBinaryRawValueMatchesRequest()
        {
            IEdmModel model = GetBinaryModel();

            IEdmEntitySet  rawValues      = model.EntityContainer.FindEntitySet("RawValue");
            IEdmEntityType rawValueEntity =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "RawValueEntity");

            IEdmStructuralProperty property = rawValueEntity.FindProperty("BinaryProperty") as IEdmStructuralProperty;

            Assert.NotNull(property); // Guard
            PropertySegment propertySegment = new PropertySegment(property);

            var        keys       = new[] { new KeyValuePair <string, object>("Id", 1) };
            KeySegment keySegment = new KeySegment(keys, rawValueEntity, rawValues);

            ODataPath path = new ODataPath(new EntitySetSegment(rawValues), keySegment, propertySegment, new ValueSegment(propertySegment.EdmType));
            ODataBinaryValueMediaTypeMapping mapping = new ODataBinaryValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/RawValue(1)/BinaryProperty/$value");

            request.ODataContext().Path = path;

            double mapResult = mapping.TryMatchMediaType(request);

            Assert.Equal(1.0, mapResult);
        }
Esempio n. 23
0
        /// <summary>
        /// Gets resource path from service root, and request Uri.
        /// </summary>
        /// <param name="baseUri">The service root Uri.</param>
        /// <param name="odataUri">The request Uri.</param>
        /// <returns>The resource path.</returns>
        private Uri GetContainingEntitySetUri(Uri baseUri, ODataUri odataUri)
        {
            if (odataUri == null || odataUri.Path == null)
            {
                throw new ODataException(OData.Core.Strings.ODataMetadataBuilder_MissingODataUri);
            }

            ODataPath path = odataUri.Path;
            List <ODataPathSegment> segments    = path.ToList();
            ODataPathSegment        lastSegment = segments.Last();

            while (!(lastSegment is NavigationPropertySegment))
            {
                segments.Remove(lastSegment);
                lastSegment = segments.Last();
            }

            // also removed the last navigation property segment
            segments.Remove(lastSegment);

            // Remove the unnecessary type cast segment.
            ODataPathSegment nextToLastSegment = segments.Last();

            while (nextToLastSegment is TypeSegment)
            {
                ODataPathSegment previousSegment = segments[segments.Count - 2];
                IEdmEntityType   ownerType       = previousSegment.TargetEdmType as IEdmEntityType;
                if (ownerType != null && ownerType.FindProperty(lastSegment.Identifier) != null)
                {
                    segments.Remove(nextToLastSegment);
                    nextToLastSegment = segments.Last();
                }
                else
                {
                    break;
                }
            }

            // append each segment to base uri
            Uri uri = baseUri;

            foreach (ODataPathSegment segment in segments)
            {
                var keySegment = segment as KeySegment;
                if (keySegment == null)
                {
                    uri = this.uriBuilder.BuildEntitySetUri(uri, segment.Identifier);
                }
                else
                {
                    uri = this.uriBuilder.BuildEntityInstanceUri(
                        uri,
                        keySegment.Keys.ToList(),
                        keySegment.EdmType.FullTypeName());
                }
            }

            return(uri);
        }
Esempio n. 24
0
        public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmNavigationSource navigationSource)
        {
            Contract.Assert(model != null);
            Contract.Assert(navigationSource != null);

            IEnumerable <IEdmStructuralProperty> cachedProperties;

            if (_concurrencyProperties != null && _concurrencyProperties.TryGetValue(navigationSource, out cachedProperties))
            {
                return(cachedProperties);
            }

            IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>();
            IEdmEntityType            entityType   = navigationSource.EntityType();
            IEdmVocabularyAnnotatable annotatable  = navigationSource as IEdmVocabularyAnnotatable;

            IEdmContainedEntitySet navigationSourceAsEntitySet = navigationSource as IEdmContainedEntitySet;

            if (navigationSourceAsEntitySet != null)
            {
                annotatable = navigationSourceAsEntitySet.NavigationProperty as EdmNavigationProperty;
            }

            if (annotatable != null)
            {
                IEdmValueAnnotation annotation = model.FindVocabularyAnnotations <IEdmValueAnnotation>(annotatable, CoreVocabularyModel.ConcurrencyTerm).FirstOrDefault();
                if (annotation != null)
                {
                    IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression;
                    if (properties != null)
                    {
                        foreach (var property in properties.Elements)
                        {
                            IEdmPathExpression pathExpression = property as IEdmPathExpression;
                            if (pathExpression != null)
                            {
                                // So far, we only consider the single path, because only the direct properties from declaring type are used.
                                // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472
                                string                 propertyName       = pathExpression.Path.Single();
                                IEdmProperty           edmProperty        = entityType.FindProperty(propertyName);
                                IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty;
                                if (structuralProperty != null)
                                {
                                    results.Add(structuralProperty);
                                }
                            }
                        }
                    }
                }
            }

            if (_concurrencyProperties == null)
            {
                _concurrencyProperties = new ConcurrentDictionary <IEdmNavigationSource, IEnumerable <IEdmStructuralProperty> >();
            }

            _concurrencyProperties[navigationSource] = results;
            return(results);
        }
Esempio n. 25
0
        public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmNavigationSource navigationSource)
        {
            Contract.Assert(model != null);
            Contract.Assert(navigationSource != null);

            // Ensure that concurrency properties cache is attached to model as an annotation to avoid expensive calculations each time
            ConcurrencyPropertiesAnnotation concurrencyProperties = model.GetAnnotationValue <ConcurrencyPropertiesAnnotation>(model);

            if (concurrencyProperties == null)
            {
                concurrencyProperties = new ConcurrencyPropertiesAnnotation();
                model.SetAnnotationValue(model, concurrencyProperties);
            }

            IEnumerable <IEdmStructuralProperty> cachedProperties;

            if (concurrencyProperties.TryGetValue(navigationSource, out cachedProperties))
            {
                return(cachedProperties);
            }

            IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>();
            IEdmEntityType            entityType   = navigationSource.EntityType();
            IEdmVocabularyAnnotatable annotatable  = navigationSource as IEdmVocabularyAnnotatable;

            if (annotatable != null)
            {
                var annotations = model.FindVocabularyAnnotations <IEdmVocabularyAnnotation>(annotatable, CoreVocabularyModel.ConcurrencyTerm);
                IEdmVocabularyAnnotation annotation = annotations.FirstOrDefault();
                if (annotation != null)
                {
                    IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression;
                    if (properties != null)
                    {
                        foreach (var property in properties.Elements)
                        {
                            IEdmPathExpression pathExpression = property as IEdmPathExpression;
                            if (pathExpression != null)
                            {
                                // So far, we only consider the single path, because only the direct properties from declaring type are used.
                                // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472
                                string                 propertyName       = pathExpression.PathSegments.First();
                                IEdmProperty           edmProperty        = entityType.FindProperty(propertyName);
                                IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty;
                                if (structuralProperty != null)
                                {
                                    results.Add(structuralProperty);
                                }
                            }
                        }
                    }
                }
            }

            concurrencyProperties[navigationSource] = results;
            return(results);
        }
Esempio n. 26
0
        /// <summary>
        /// Determines whether or not the given operation is selected and takes type-segments into account.
        /// </summary>
        /// <param name="entityType">The current entity type.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="mustBeNamespaceQualified">Whether or not the operation name must be container qualified in the $select string.</param>
        /// <returns>
        ///   <c>true</c> if the operation is selected; otherwise, <c>false</c>.
        /// </returns>
        internal bool IsOperationSelected(IEdmEntityType entityType, IEdmOperation operation, bool mustBeNamespaceQualified)
        {
            Debug.Assert(entityType != null, "entityType != null");
            Debug.Assert(operation != null, "operation != null");

            // If the operation name conflicts with a property name then it must be namespace qualified
            mustBeNamespaceQualified = mustBeNamespaceQualified || entityType.FindProperty(operation.Name) != null;

            return(this.IsOperationSelectedAtThisLevel(operation, mustBeNamespaceQualified) || this.GetMatchingTypeSegments(entityType).Any(typeSegment => typeSegment.IsOperationSelectedAtThisLevel(operation, mustBeNamespaceQualified)));
        }
 public ODataUriParserInjectionTests()
 {
     folderType             = oneDriveModel.SchemaElements.OfType <IEdmComplexType>().Single(e => string.Equals(e.Name, "folder"));
     itemType               = oneDriveModel.SchemaElements.OfType <IEdmEntityType>().Single(e => string.Equals(e.Name, "item"));
     specialItemType        = oneDriveModel.SchemaElements.OfType <IEdmEntityType>().Single(e => string.Equals(e.Name, "specialItem"));
     folderProp             = itemType.FindProperty("folder") as IEdmStructuralProperty;
     sizeProp               = itemType.FindProperty("size") as IEdmStructuralProperty;
     driveType              = oneDriveModel.SchemaElements.OfType <IEdmEntityType>().Single(e => string.Equals(e.Name, "drive"));
     itemsNavProp           = driveType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == "items");
     childrenNavProp        = itemType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == "children");
     thumbnailsNavProp      = itemType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == "thumbnails");
     drivesEntitySet        = oneDriveModel.EntityContainer.FindEntitySet("drives");
     driveSingleton         = oneDriveModel.EntityContainer.FindSingleton("drive");
     containedItemsNav      = drivesEntitySet.FindNavigationTarget(itemsNavProp);
     containedthumbnailsNav = containedItemsNav.FindNavigationTarget(thumbnailsNavProp);
     copyOp   = oneDriveModel.SchemaElements.OfType <IEdmOperation>().FirstOrDefault(o => o.Name == "copy");
     searchOp = oneDriveModel.SchemaElements.OfType <IEdmOperation>().FirstOrDefault(o => o.Name == "search");
     shareItemBindCollectionOp = oneDriveModel.SchemaElements.OfType <IEdmOperation>().LastOrDefault(o => o.Name == "sharedWithMe");
 }
Esempio n. 28
0
        public void Term_Constant_OnProperty()
        {
            this.SetupModelsAndValues();

            const string applicationCsdl =
                @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
    <Annotations Target=""foo.Person/CoolnessIndex"">
        <Annotation Term=""bar.Int32Value"" Qualifier=""HotIndex"" Int=""-1"" />
        <Annotation Term=""bar.StringValue"" String=""Goofy"" />
    </Annotations>
</Schema>";
            IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel);
            EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup);
            EdmToClrEvaluator      clrEvaluator        = new EdmToClrEvaluator(this.operationsLookup);

            IEdmEntityType    person               = this.baseModel.FindEntityType("foo.Person");
            IEdmProperty      property             = person.FindProperty("CoolnessIndex");
            IEdmPropertyValue contextPropertyValue = ((IEdmStructuredValue)this.personValue).FindPropertyValue("CoolnessIndex");

            IEdmTerm termInt32Value  = this.vocabularyDefinitionModel.FindTerm("bar.Int32Value");
            IEdmTerm termStringValue = this.vocabularyDefinitionModel.FindTerm("bar.StringValue");

            IEdmVocabularyAnnotation annotation = property.VocabularyAnnotations(applicationModel).SingleOrDefault(a => a.Term == termInt32Value);
            IEdmExpression           expression = annotation.Value;
            IEdmValue annotationHotIndex        = expressionEvaluator.Evaluate(expression);

            Assert.AreEqual(-1, ((IEdmIntegerValue)annotationHotIndex).Value, "Term annotation value");

            annotationHotIndex = applicationModel.GetTermValue(property, termInt32Value, "HotIndex", expressionEvaluator);
            Assert.AreEqual(-1, ((IEdmIntegerValue)annotationHotIndex).Value, "Term annotation value");

            annotationHotIndex = applicationModel.GetTermValue(property, "bar.Int32Value", "HotIndex", expressionEvaluator);
            Assert.AreEqual(-1, ((IEdmIntegerValue)annotationHotIndex).Value, "Term annotation value");

            int hotIndex = applicationModel.GetTermValue <int>(property, termInt32Value, "HotIndex", clrEvaluator);

            Assert.AreEqual(-1, hotIndex, "Term annotation value");

            hotIndex = applicationModel.GetTermValue <int>(property, "bar.Int32Value", "HotIndex", clrEvaluator);
            Assert.AreEqual(-1, hotIndex, "Term annotation value");

            IEdmValue annotationString = applicationModel.GetTermValue(property, termStringValue, expressionEvaluator);

            Assert.AreEqual("Goofy", ((IEdmStringValue)annotationString).Value, "Term annotation value");

            annotationString = applicationModel.GetTermValue(property, "bar.StringValue", expressionEvaluator);
            Assert.AreEqual("Goofy", ((IEdmStringValue)annotationString).Value, "Term annotation value");

            string stringValue = applicationModel.GetTermValue <string>(property, termStringValue, clrEvaluator);

            Assert.AreEqual("Goofy", stringValue, "Term annotation value");

            stringValue = applicationModel.GetTermValue <string>(property, "bar.StringValue", clrEvaluator);
            Assert.AreEqual("Goofy", stringValue, "Term annotation value");
        }
Esempio n. 29
0
        /// <summary>
        /// Determines whether or not the given operation is selected and takes type-segments into account.
        /// </summary>
        /// <param name="entityType">The current entity type.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="mustBeContainerQualified">Whether or not the operation name must be container qualified in the $select string.</param>
        /// <returns>
        ///   <c>true</c> if the operation is selected; otherwise, <c>false</c>.
        /// </returns>
        internal bool IsOperationSelected(IEdmEntityType entityType, IEdmFunctionImport operation, bool mustBeContainerQualified)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(entityType != null, "entityType != null");
            Debug.Assert(operation != null, "operatio != null");

            // If the functionImport name conflicts with a property name then it must be container qualified
            mustBeContainerQualified = mustBeContainerQualified || entityType.FindProperty(operation.Name) != null;

            return(this.IsOperationSelectedAtThisLevel(operation, mustBeContainerQualified) || this.GetMatchingTypeSegments(entityType).Any(typeSegment => typeSegment.IsOperationSelectedAtThisLevel(operation, mustBeContainerQualified)));
        }
        /// <summary>
        /// Resolves a navigation property name to an IEdmNavigationProperty.
        /// </summary>
        /// <param name="entityType">Entity Type to look for the navigation property on.</param>
        /// <param name="navigationPropertyName">Navigation property name to find.</param>
        /// <returns>Returns the navigation property of throws an exception if it cannot be found.</returns>
        private IEdmNavigationProperty ResolveNavigationProperty(IEdmEntityType entityType, string navigationPropertyName)
        {
            IEdmNavigationProperty navigationProperty = null;
            IEdmProperty           property           = entityType.FindProperty(navigationPropertyName);

            navigationProperty = property as IEdmNavigationProperty;

            if (navigationProperty == null)
            {
                throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidPropertyForEntityReferenceLinkUri(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), navigationPropertyName));
            }

            return(navigationProperty);
        }
 /// <summary>
 /// Validates an <see cref="ODataNavigationLink"/> to ensure all required information is specified and valid.
 /// </summary>
 /// <param name="navigationLink">The navigation link to validate.</param>
 /// <param name="declaringEntityType">The <see cref="IEdmEntityType"/> declaring the navigation property; or null if metadata is not available.</param>
 /// <param name="expandedPayloadKind">The <see cref="ODataPayloadKind"/> of the expanded content of this navigation link or null for deferred links.</param>
 /// <returns>The type of the navigation property for this navigation link; or null if no <paramref name="declaringEntityType"/> was specified.</returns>
 public IEdmNavigationProperty ValidateNavigationLink(
     ODataNavigationLink navigationLink,
     IEdmEntityType declaringEntityType,
     ODataPayloadKind? expandedPayloadKind)
 {
     return declaringEntityType == null ? null : declaringEntityType.FindProperty(navigationLink.Name) as IEdmNavigationProperty;
 }
        internal static IEdmNavigationProperty ValidateNavigationLink(
            ODataNavigationLink navigationLink,
            IEdmEntityType declaringEntityType,
            ODataPayloadKind? expandedPayloadKind,
            bool bypassValidation = false)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(
                !expandedPayloadKind.HasValue ||
                expandedPayloadKind.Value == ODataPayloadKind.EntityReferenceLink ||
                expandedPayloadKind.Value == ODataPayloadKind.Entry ||
                expandedPayloadKind.Value == ODataPayloadKind.Feed,
                "If an expanded payload kind is specified it must be entry, feed or entity reference link.");

            if (bypassValidation)
            {
                return declaringEntityType == null ? null : declaringEntityType.FindProperty(navigationLink.Name) as IEdmNavigationProperty;
            }

            // Navigation link must have a non-empty name
            if (string.IsNullOrEmpty(navigationLink.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.CheckForNavigationLinkWithContent).
            bool isEntityReferenceLinkPayload = expandedPayloadKind == ODataPayloadKind.EntityReferenceLink;

            // true only if the expandedPayloadKind has a value and the value is 'Feed'
            bool isFeedPayload = expandedPayloadKind == ODataPayloadKind.Feed;

            // Make sure the IsCollection property agrees with the payload kind for entry and feed payloads
            Func<object, string> errorTemplate = null;
            if (!isEntityReferenceLinkPayload && navigationLink.IsCollection.HasValue && expandedPayloadKind.HasValue)
            {
                // For feed/entry make sure the IsCollection property is set correctly.
                if (isFeedPayload != navigationLink.IsCollection.Value)
                {
                    errorTemplate = expandedPayloadKind.Value == ODataPayloadKind.Feed
                        ? (Func<object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent
                        : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent;
                }
            }

            IEdmNavigationProperty navigationProperty = null;
            if (errorTemplate == null && declaringEntityType != null)
            {
                navigationProperty = WriterValidationUtils.ValidateNavigationPropertyDefined(navigationLink.Name, declaringEntityType);
                Debug.Assert(navigationProperty != null, "If we have a declaring type we expect a non-null navigation property since open nav props are not allowed.");

                bool isCollectionType = navigationProperty.Type.TypeKind() == EdmTypeKind.Collection;

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

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

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

            return navigationProperty;
        }
Esempio n. 33
0
        /// <summary>
        /// Determines whether or not the given operation is selected and takes type-segments into account.
        /// </summary>
        /// <param name="entityType">The current entity type.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="mustBeNamespaceQualified">Whether or not the operation name must be container qualified in the $select string.</param>
        /// <returns>
        ///   <c>true</c> if the operation is selected; otherwise, <c>false</c>.
        /// </returns>
        internal bool IsOperationSelected(IEdmEntityType entityType, IEdmOperation operation, bool mustBeNamespaceQualified)
        {
            Debug.Assert(entityType != null, "entityType != null");
            Debug.Assert(operation != null, "operation != null");

            // If the operation name conflicts with a property name then it must be namespace qualified
            mustBeNamespaceQualified = mustBeNamespaceQualified || entityType.FindProperty(operation.Name) != null;

            return this.IsOperationSelectedAtThisLevel(operation, mustBeNamespaceQualified) || this.GetMatchingTypeSegments(entityType).Any(typeSegment => typeSegment.IsOperationSelectedAtThisLevel(operation, mustBeNamespaceQualified));
        }