public void Apply_SetOperationLinkBuilder_ForActionBoundToEntity()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            var action = builder.EntityType <Customer>().Action("MyAction");

            // Act
            Assert.Null(action.GetActionLink());     // Guard
            Assert.Null(action.GetFeedActionLink()); // Guard

            ActionLinkGenerationConvention convention = new ActionLinkGenerationConvention();

            convention.Apply(action, builder);

            // Assert
            var actionLink = action.GetActionLink();

            Assert.NotNull(actionLink);
            Assert.IsType <Func <ResourceContext, Uri> >(actionLink);

            Assert.Null(action.GetFeedActionLink());
        }
Example #2
0
        private static System.Web.Http.HttpServer CreateServer(string customersEntitySet)
#endif
        {
            // We need to do this to avoid controllers with incorrect attribute
            // routing configuration in this assembly that cause an exception to
            // be thrown at runtime. With this, we restrict the test to the following
            // set of controllers.
            Type[] controllers = new Type[]
            {
                typeof(OnlyFilterAllowedCustomersController),
                typeof(OnlyFilterAndEqualsAllowedCustomersController),
                typeof(FilterDisabledCustomersController),
                typeof(EverythingAllowedCustomersController),
                typeof(OtherLimitationsCustomersController),
            };

            ODataModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <EnableQueryCustomer>(customersEntitySet);
            builder.EntityType <PremiumEnableQueryCustomer>();

            builder.EntitySet <EnableQueryCategory>("EnableQueryCategories");
            builder.EntityType <PremiumEnableQueryCategory>();

            builder.EntitySet <EnableQueryOrder>("EnableQueryOrders");
            builder.EntityType <DiscountedEnableQueryOrder>();

            builder.EntitySet <EnableQueryOrderLine>("EnableQueryOrderLines");

            builder.ComplexType <EnableQueryAddress>();

            IEdmModel model = builder.GetEdmModel();

            return(TestServerFactory.Create(controllers, (config) =>
            {
                config.MapODataServiceRoute("odata", "odata", model);
                config.Count().OrderBy().Filter().Expand().MaxTop(null).Select().SkipToken();
            }));
        }
        public void Apply_Doesnot_Override_UserConfiguration()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            var customers   = builder.EntitySet <Customer>("Customers");
            var paintAction = customers.EntityType.Action("Paint");

            paintAction.HasActionLink(ctxt => new Uri("http://localhost/ActionTestWorks"), followsConventions: false);
            ActionLinkGenerationConvention convention = new ActionLinkGenerationConvention();

            // Act
            convention.Apply(paintAction, builder);

            IEdmModel model        = builder.GetEdmModel();
            var       edmCustomers = model.EntityContainer.FindEntitySet("Customers");
            var       edmCustomer  = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer");
            var       edmAction    = model.SchemaElements.OfType <IEdmAction>().First(a => a.Name == "Paint");

            Assert.NotNull(edmAction);

            string routeName     = "OData";
            var    configuration = RoutingConfigurationFactory.CreateWithRootContainer(routeName);

            configuration.MapODataServiceRoute(routeName, null, model);

            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost", configuration, routeName);

            OperationLinkBuilder actionLinkBuilder = model.GetOperationLinkBuilder(edmAction);

            var serializerContext = ODataSerializerContextFactory.Create(model, edmCustomers, request);
            var entityContext     = new ResourceContext(serializerContext, edmCustomer.AsReference(), new Customer {
                Id = 2009
            });

            // Assert
            Uri link = actionLinkBuilder.BuildLink(entityContext);

            Assert.Equal("http://localhost/ActionTestWorks", link.AbsoluteUri);
        }
        public void Apply_IgnoresKey_NonEntityTypeConfiguration()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            Mock <PropertyInfo> property = new Mock <PropertyInfo>();

            property.Setup(p => p.Name).Returns("Property");
            property.Setup(p => p.PropertyType).Returns(typeof(int));
            property.Setup(p => p.GetCustomAttributes(It.IsAny <bool>())).Returns(new[] { new KeyAttribute() });

            Mock <ComplexTypeConfiguration> complexType = new Mock <ComplexTypeConfiguration>(MockBehavior.Strict);

            Mock <PrimitivePropertyConfiguration> primitiveProperty =
                new Mock <PrimitivePropertyConfiguration>(property.Object, complexType.Object);

            // Act
            new KeyAttributeEdmPropertyConvention().Apply(primitiveProperty.Object, complexType.Object, builder);

            // Assert
            complexType.Verify();
        }
        private static IEdmModel GetEdmModel()
        {
            var builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <Account>("Accounts");
            builder.EntitySet <PaymentInstrument>("Payments");

            builder.EntityType <Account>().Collection.Action("Clear").Parameter <int>("p1");
            builder.EntityType <Account>()
            .Collection.Function("MyCollectionFunction")
            .Returns <string>()
            .Parameter <int>("land");

            builder.EntityType <PreminumAccount>().Collection.Function("MyCollectionFunction")
            .Returns <string>()
            .Parameter <int>("land");

            builder.EntityType <Account>().Action("ClearSingle").Parameter <string>("pa");

            builder.EntityType <Account>().Function("MyFunction").Returns <string>().Parameter <string>("p1");
            return(builder.GetEdmModel());
        }
Example #6
0
        public void NavigationLinksGenerationConvention_GeneratesLinksWithoutCast_ForBaseProperties()
        {
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <SportBike>("vehicles");
            builder.EntitySet <Manufacturer>("manufacturers");

            IEdmModel              model = builder.GetEdmModel();
            IEdmEntitySet          vehiclesEdmEntitySet           = model.EntityContainer.FindEntitySet("vehicles");
            IEdmEntityType         sportbikeType                  = model.AssertHasEntityType(typeof(SportBike));
            IEdmNavigationProperty motorcycleManufacturerProperty = sportbikeType.AssertHasNavigationProperty(model, "Manufacturer", typeof(MotorcycleManufacturer), isNullable: true, multiplicity: EdmMultiplicity.ZeroOrOne);

            var    configuration = RoutingConfigurationFactory.Create();
            string routeName     = "Route";

            configuration.MapODataServiceRoute(routeName, null, model);

            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost", configuration, routeName);

            NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(vehiclesEdmEntitySet);

            linkBuilder.AddNavigationPropertyLinkBuilder(motorcycleManufacturerProperty, new NavigationLinkBuilder((context, property) => context.GenerateNavigationPropertyLink(property, includeCast: false), false));
            var serializerContext = ODataSerializerContextFactory.Create(model, vehiclesEdmEntitySet, request);
            var entityContext     = new ResourceContext(serializerContext, sportbikeType.AsReference(), new SportBike {
                Model = 2009, Name = "Ninja"
            });

            // We might get one of these:
            // http://localhost/vehicles(Model=2009,Name='Ninja')/Manufacturer
            // http://localhost/vehicles(Name='Ninja',Model=2009)/Manufacturer
            Uri    uri        = linkBuilder.BuildNavigationLink(entityContext, motorcycleManufacturerProperty, ODataMetadataLevel.MinimalMetadata);
            string aboluteUri = uri.AbsoluteUri;

            Assert.Contains("http://localhost/vehicles(", aboluteUri);
            Assert.Contains("Model=2009", aboluteUri);
            Assert.Contains("Name='Ninja'", aboluteUri);
            Assert.Contains(")/Manufacturer", aboluteUri);
        }
Example #7
0
        public void LowerCamelCaser_ProcessReflectedPropertyNames()
        {
            // Arrange
            var builder = ODataConventionModelBuilderFactory.Create().EnableLowerCamelCase(NameResolverOptions.ProcessReflectedPropertyNames);
            EntityTypeConfiguration <LowerCamelCaserModelAliasEntity> entity = builder.EntitySet <LowerCamelCaserModelAliasEntity>("Entities").EntityType;

            entity.HasKey(e => e.ID).Property(e => e.ID).Name = "IDExplicitly";
            entity.Property(d => d.Price).Name = "Price";

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            IEdmEntityType lowerCamelCaserModelAliasEntity =
                Assert.Single(model.SchemaElements.OfType <IEdmEntityType>().Where(e => e.Name == "LowerCamelCaserModelAliasEntity"));

            Assert.Equal(5, lowerCamelCaserModelAliasEntity.Properties().Count());
            Assert.Single(lowerCamelCaserModelAliasEntity.Properties().Where(p => p.Name == "IDExplicitly"));
            Assert.Single(lowerCamelCaserModelAliasEntity.Properties().Where(p => p.Name == "name"));
            Assert.Single(lowerCamelCaserModelAliasEntity.Properties().Where(p => p.Name == "Something"));
            Assert.Single(lowerCamelCaserModelAliasEntity.Properties().Where(p => p.Name == "color"));
            Assert.Single(lowerCamelCaserModelAliasEntity.Properties().Where(p => p.Name == "Price"));
        }
        public void SelfLinksGenerationConvention_Uses_WithoutCast_IfDerivedTypeDoesnotHaveNavigationProperty_ForSingleton()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            var myMotorcycle = builder.Singleton <Motorcycle>("MyMotor");

            IEdmModel      model = builder.GetEdmModel();
            IEdmSingleton  vehicleEdmSingleton = model.EntityContainer.FindSingleton("MyMotor");
            IEdmEntityType sportbikeType       = model.AssertHasEntityType(typeof(SportBike));

            var request = RequestFactory.CreateFromModel(model);
            NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(vehicleEdmSingleton);
            var serializerContext = ODataSerializerContextFactory.Create(model, vehicleEdmSingleton, request);
            var entityContext     = new ResourceContext(serializerContext, sportbikeType.AsReference(), new SportBike {
                Model = 2014, Name = "Ninja"
            });

            // Act
            EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(entityContext, ODataMetadataLevel.FullMetadata);

            // Assert
            Assert.Equal("http://localhost/MyMotor", selfLinks.IdLink.ToString());
        }
Example #9
0
        public void ODataMetadataSerializer_Works_ForSingleton()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            builder.Singleton <Customer>("Me");
            builder.EntitySet <Order>("MyOrders");
            IEdmModel model = builder.GetEdmModel();

            ODataMetadataSerializer    serializer = new ODataMetadataSerializer();
            MemoryStream               stream     = new MemoryStream();
            IODataResponseMessage      message    = new ODataMessageWrapper(stream);
            ODataMessageWriterSettings settings   = new ODataMessageWriterSettings();

            // Act
            serializer.WriteObject(model, typeof(IEdmModel), new ODataMessageWriter(message, settings, model), new ODataSerializerContext());

            // Assert
            stream.Seek(0, SeekOrigin.Begin);
            string result = new StreamReader(stream).ReadToEnd();

            Assert.Contains("<Singleton Name=\"Me\" Type=\"Microsoft.Test.AspNet.OData.Formatter.Serialization.Models.Customer\">", result);
        }
Example #10
0
        public async Task NullPrimitiveValueSerializeAsODataThrows(Type valueType, object value, string mediaType, string unused)
        {
            // Arrange
            Assert.NotNull(valueType);
            Assert.NotNull(unused);

            ODataConventionModelBuilder modelBuilder = ODataConventionModelBuilderFactory.Create();

            modelBuilder.EntitySet <WorkItem>("WorkItems");
            IEdmModel    model         = modelBuilder.GetEdmModel();
            IEdmProperty property      = model.EntityContainer.EntitySets().Single().EntityType().Properties().First();
            ODataPath    path          = new ODataPath(new PropertySegment(property as IEdmStructuralProperty));
            var          configuration = RoutingConfigurationFactory.CreateWithRootContainer("OData");
            var          request       = RequestFactory.Create(HttpMethod.Get, "http://localhost/WorkItems(10)/ID", configuration, "OData", path);

            var formatter = FormatterTestHelper.GetFormatter(new ODataPayloadKind[] { ODataPayloadKind.Property }, request, mediaType);

            // Act & Assert
            Type type    = (value != null) ? value.GetType() : typeof(Nullable <int>);
            var  content = FormatterTestHelper.GetContent(value, type, formatter, mediaType.ToString());
            await ExceptionAssert.ThrowsAsync <ODataException>(
                () => FormatterTestHelper.GetContentResult(content, request),
                "Cannot write the value 'null' in top level property; return 204 instead.");
        }
Example #11
0
        public void TimestampConvention_DoesntApplyWhenTheAttributeIsAppliedToMultipleProperties_InATypeHierarchy()
        {
            // Arrange
            PropertyInfo            property       = CreateMockPropertyInfo("TestProperty");
            PropertyInfo            otherProperty  = CreateMockPropertyInfo("OtherTestProperty");
            ODataModelBuilder       modelBuilder   = ODataConventionModelBuilderFactory.Create();
            EntityTypeConfiguration baseEntityType = new EntityTypeConfiguration(modelBuilder, typeof(object));

            EntityTypeConfiguration entityType = new EntityTypeConfiguration(modelBuilder, typeof(Int32));

            entityType.BaseType = baseEntityType;

            PrimitivePropertyConfiguration primitiveProperty = new PrimitivePropertyConfiguration(property, entityType);

            entityType.ExplicitProperties.Add(property, primitiveProperty);
            baseEntityType.ExplicitProperties.Add(otherProperty, new PrimitivePropertyConfiguration(otherProperty, baseEntityType));
            TimestampAttributeEdmPropertyConvention convention = new TimestampAttributeEdmPropertyConvention();

            // Act
            convention.Apply(primitiveProperty, entityType, ODataConventionModelBuilderFactory.Create());

            // Assert
            Assert.False(primitiveProperty.ConcurrencyToken);
        }
Example #12
0
        public void Validate_Throw_WithInvalidMaxExpansionDepth()
        {
            int maxExpansionDepth = -1;
            // Arrange
            string expand  = "Parent($levels=1)";
            var    builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model   = builder.GetEdmModel();
            var       context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));

            context.RequestContainer = new MockContainer();
            var validator = SelectExpandQueryValidator.GetSelectExpandQueryValidator(context);
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);

            // Act & Assert
            ExceptionAssert.Throws <ArgumentOutOfRangeException>(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings {
                MaxExpansionDepth = maxExpansionDepth
            }),
                "Value must be greater than or equal to 0.\r\nParameter name: value\r\nActual value was -1.");
        }
Example #13
0
        public void CreateODataEnumValue_ReturnsCorrectEnumMember()
        {
            // Arrange
            var builder = ODataConventionModelBuilderFactory.Create();

            builder.EnumType <BookCategory>().Namespace = "NS";
            IEdmModel    model    = builder.GetEdmModel();
            IEdmEnumType enumType = model.SchemaElements.OfType <IEdmEnumType>().Single();

            var provider = new DefaultODataSerializerProvider(new MockContainer());
            ODataEnumSerializer    serializer   = new ODataEnumSerializer(provider);
            ODataSerializerContext writeContext = new ODataSerializerContext
            {
                Model = model
            };

            // Act
            ODataEnumValue value = serializer.CreateODataEnumValue(BookCategory.Newspaper,
                                                                   new EdmEnumTypeReference(enumType, false), writeContext);

            // Assert
            Assert.NotNull(value);
            Assert.Equal("news", value.Value);
        }
        public void DataMemberAttributeEdmPropertyConvention_ConfiguresNavigationDataMembers(bool isRequired)
        {
            MockType relatedType =
                new MockType("RelatedEntity")
                .Property <int>("ID");
            MockType type =
                new MockType("Entity")
                .Property(typeof(int), "ID")
                .Property(relatedType, "RelatedEntity", new DataMemberAttribute {
                IsRequired = isRequired
            });

            type.Setup(t => t.GetCustomAttributes(It.IsAny <Type>(), It.IsAny <bool>())).Returns(new[] { new DataContractAttribute() });

            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            builder.AddEntityType(type);

            IEdmModel      model  = builder.GetEdmModel();
            IEdmEntityType entity = model.AssertHasEntityType(type);

            entity.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int32);
            entity.AssertHasNavigationProperty(model, "RelatedEntity", relatedType, isNullable: !isRequired, multiplicity: isRequired ? EdmMultiplicity.One : EdmMultiplicity.ZeroOrOne);
        }
Example #15
0
        private IEdmModel GetModel()
        {
            ODataModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            builder.ContainerName = "Container";
            builder.Namespace     = "org.odata";
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;
            ActionConfiguration action = customer.Action("DoSomething");

            action.Parameter <int>("p1");
            action.Parameter <Address>("p2");
            action.Parameter <Color?>("color");
            action.CollectionParameter <string>("p3");
            action.CollectionParameter <Address>("p4");
            action.CollectionParameter <Color?>("colors");

            action = customer.Collection.Action("MyAction");
            action.EntityParameter <Customer>("Customer");
            action.CollectionEntityParameter <Customer>("Customers");

            action           = customer.Action("CNSAction");
            action.Namespace = "customize";
            return(builder.GetEdmModel());
        }
        public void Apply_SetOperationLinkBuilder_ForFunctionBoundToEntity()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            var function = builder.EntityType <Customer>().Function("MyFunction").Returns <int>();

            function.Parameter <string>("param");

            // Act
            Assert.Null(function.GetFunctionLink());     // Guard
            Assert.Null(function.GetFeedFunctionLink()); // Guard

            FunctionLinkGenerationConvention convention = new FunctionLinkGenerationConvention();

            convention.Apply(function, builder);

            // Assert
            var functionLink = function.GetFunctionLink();

            Assert.NotNull(functionLink);
            Assert.IsType <Func <ResourceContext, Uri> >(functionLink);

            Assert.Null(function.GetFeedFunctionLink());
        }
        public void Convention_GeneratesUri_ForFunctionBoundToEntity()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <Customer>("Customers");
            var function = builder.EntityType <Customer>().Function("MyFunction").Returns <int>();

            function.Parameter <string>("param");
            IEdmModel model = builder.GetEdmModel();

            // Act
            var configuration = RoutingConfigurationFactory.Create();

            configuration.MapODataServiceRoute("odata", "odata", model);

            var request = RequestFactory.Create(HttpMethod.Get, "http://*****:*****@param)",
                         link.AbsoluteUri);
        }
        public void Apply_AddsEnumKey_EntityTypeConfiguration()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            Mock <PropertyInfo> property = new Mock <PropertyInfo>();

            property.Setup(p => p.Name).Returns("Property");
            property.Setup(p => p.PropertyType).Returns(typeof(MyEnumType));
            property.Setup(p => p.GetCustomAttributes(It.IsAny <bool>())).Returns(new[] { new KeyAttribute() });

            Mock <EntityTypeConfiguration> entityType = new Mock <EntityTypeConfiguration>(MockBehavior.Strict);

            entityType.Setup(e => e.HasKey(property.Object)).Returns(entityType.Object).Verifiable();

            Mock <EnumPropertyConfiguration> enumProperty =
                new Mock <EnumPropertyConfiguration>(property.Object, entityType.Object);

            // Act
            new KeyAttributeEdmPropertyConvention().Apply(enumProperty.Object, entityType.Object, builder);

            // Assert
            entityType.Verify();
        }
Example #19
0
        private static IEdmModel SetupModel()
        {
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            // Different types of navigation sources and navigation properties.
            builder.EntitySet <ETagCustomer>("Customers");
            builder.EntitySet <ETagOrder>("Orders");
            builder.EntityType <ETagSpecialOrder>().DerivesFrom <ETagOrder>();
            builder.Singleton <ETagOrder>("BestOrder");
            builder.EntitySet <ETagAddress>("Addresses");

            // Entity without ETag to test that we only write entities with ETag.
            builder.EntitySet <NonEtagEntity>("NonEtagEntity");

            // Just a simplification for referencing the types in cast segments.
            foreach (var type in builder.StructuralTypes)
            {
                type.Namespace = "Test";
            }

            IEdmModel model = builder.GetEdmModel();

            return(model);
        }
        public void Apply_IgnoresKey_NavigationProperty()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();

            Mock <PropertyInfo> property = new Mock <PropertyInfo>();

            property.Setup(p => p.Name).Returns("Property");
            property.Setup(p => p.PropertyType).Returns(typeof(int));
            property.Setup(p => p.GetCustomAttributes(It.IsAny <bool>())).Returns(new[] { new KeyAttribute() });

            Mock <EntityTypeConfiguration> entityType = new Mock <EntityTypeConfiguration>(MockBehavior.Strict);

            Mock <NavigationPropertyConfiguration> navigationProperty =
                new Mock <NavigationPropertyConfiguration>(property.Object, EdmMultiplicity.ZeroOrOne, entityType.Object);

            navigationProperty.Setup(c => c.Kind).Returns(PropertyKind.Navigation);

            // Act
            new KeyAttributeEdmPropertyConvention().Apply(navigationProperty.Object, entityType.Object, builder);

            // Assert
            entityType.Verify();
        }
Example #21
0
        public void WhenFunctionLinksNotManuallyConfigured_ConventionBasedBuilderUsesConventions()
        {
            // Arrange
            string            uriTemplate         = "http://server/Movies({0})/Default.Watch(param=@param)";
            Uri               expectedUri         = new Uri(string.Format(uriTemplate, 1));
            ODataModelBuilder builder             = ODataConventionModelBuilderFactory.Create();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            FunctionConfiguration           watch = movie.Function("Watch").Returns <int>();

            watch.Parameter <string>("param");
            IEdmModel model = builder.GetEdmModel();

            var    configuration = RoutingConfigurationFactory.Create();
            string routeName     = "Route";

            configuration.MapODataServiceRoute(routeName, null, model);

            var request = RequestFactory.Create(HttpMethod.Get, "http://server/Movies", configuration, routeName);

            // Act
            IEdmEntityType         movieType         = model.SchemaElements.OfType <IEdmEntityType>().SingleOrDefault();
            IEdmEntityContainer    container         = model.SchemaElements.OfType <IEdmEntityContainer>().SingleOrDefault();
            IEdmFunction           watchFunction     = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); // Guard
            IEdmEntitySet          entitySet         = container.EntitySets().SingleOrDefault();
            ODataSerializerContext serializerContext = ODataSerializerContextFactory.Create(model, entitySet, request);

            ResourceContext context = new ResourceContext(serializerContext, movieType.AsReference(), new Movie {
                ID = 1, Name = "Avatar"
            });
            OperationLinkBuilder functionLinkBuilder = model.GetAnnotationValue <OperationLinkBuilder>(watchFunction);

            //Assert
            Assert.Equal(expectedUri, watch.GetFunctionLink()(context));
            Assert.NotNull(functionLinkBuilder);
            Assert.Equal(expectedUri, functionLinkBuilder.BuildLink(context));
        }
        public void Apply_WorksFor_ActionBoundToCollectionOfEntity()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            var action = builder.EntityType <Customer>().Collection.Action("MyFunction").Returns <int>();

            action.Parameter <string>("param");

            // Act
            Assert.Null(action.GetActionLink());     // Guard
            Assert.Null(action.GetFeedActionLink()); // Guard

            ActionLinkGenerationConvention convention = new ActionLinkGenerationConvention();

            convention.Apply(action, builder);

            // Assert
            var actionLink = action.GetFeedActionLink();

            Assert.NotNull(actionLink);
            Assert.IsType <Func <ResourceSetContext, Uri> >(actionLink);

            Assert.Null(action.GetActionLink());
        }
Example #23
0
        public void Validate_DoesNotThrow_DefaultLevelsMaxLiteralExpansionDepth(int maxExpansionDepth)
        {
            // Arrange
            string expand    = "Parent($levels=1)";
            var    validator = new SelectExpandQueryValidator(new DefaultQuerySettings {
                EnableExpand = true
            });
            var builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model   = builder.GetEdmModel();
            var       context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));

            context.RequestContainer = new MockContainer();
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);

            // Act & Assert
            ExceptionAssert.DoesNotThrow(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings {
                MaxExpansionDepth = maxExpansionDepth
            }));
        }
        public void SelfLinksGenerationConvention_Uses_WithCast_IfDerivedTypeHasNavigationProperty_ForSingleton()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            var myVehicle = builder.Singleton <Vehicle>("MyVehicle");

            IEdmModel      model = builder.GetEdmModel();
            IEdmSingleton  vehicleEdmSingleton = model.EntityContainer.FindSingleton("MyVehicle");
            IEdmEntityType carType             = model.AssertHasEntityType(typeof(Car));

            var request = RequestFactory.CreateFromModel(model);
            NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(vehicleEdmSingleton);
            var serializerContext = ODataSerializerContextFactory.Create(model, vehicleEdmSingleton, request);
            var entityContext     = new ResourceContext(serializerContext, carType.AsReference(), new Car {
                Model = 2014, Name = "Contoso"
            });

            // Act
            EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(entityContext, ODataMetadataLevel.FullMetadata);

            // Assert
            Assert.Equal("http://localhost/MyVehicle", selfLinks.IdLink.ToString());
            Assert.Equal("http://localhost/MyVehicle/Microsoft.Test.AspNet.OData.Builder.TestModels.Car", selfLinks.EditLink.ToString());
        }
Example #25
0
        public void Validate_DepthChecks_DollarLevels(string expand, int maxExpansionDepth)
        {
            // Arrange
            var validator = new SelectExpandQueryValidator(new DefaultQuerySettings {
                EnableExpand = true
            });
            var builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <ODataLevelsTest.LevelsEntity>("Entities");
            IEdmModel model   = builder.GetEdmModel();
            var       context = new ODataQueryContext(model, typeof(ODataLevelsTest.LevelsEntity));

            context.RequestContainer = new MockContainer();
            var selectExpandQueryOption = new SelectExpandQueryOption(null, expand, context);

            selectExpandQueryOption.LevelsMaxLiteralExpansionDepth = 1;

            // Act & Assert
            ExceptionAssert.Throws <ODataException>(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings {
                MaxExpansionDepth = maxExpansionDepth
            }),
                String.Format(
                    CultureInfo.CurrentCulture,
                    MaxExpandDepthExceededErrorString,
                    maxExpansionDepth));

            ExceptionAssert.DoesNotThrow(
                () => validator.Validate(
                    selectExpandQueryOption,
                    new ODataValidationSettings {
                MaxExpansionDepth = maxExpansionDepth + 1
            }));
        }
        public void Apply_SetsOptionalProperty()
        {
            // Arrange
            Mock <PropertyInfo> property = new Mock <PropertyInfo>();

            property.Setup(p => p.Name).Returns("Property");
            property.Setup(p => p.PropertyType).Returns(typeof(string));
            property.Setup(p => p.GetCustomAttributes(It.IsAny <bool>())).Returns(new[] { new RequiredAttribute() });

            Mock <StructuralTypeConfiguration>     structuralType     = new Mock <StructuralTypeConfiguration>();
            Mock <StructuralPropertyConfiguration> structuralProperty = new Mock <StructuralPropertyConfiguration>(property.Object, structuralType.Object);

            structuralProperty.Object.AddedExplicitly = false;

            // Act
            new RequiredAttributeEdmPropertyConvention().Apply(structuralProperty.Object, structuralType.Object, ODataConventionModelBuilderFactory.Create());

            // Assert
            Assert.False(structuralProperty.Object.NullableProperty);
        }
        public async Task SendAsync_CorrectlyHandlesCookieHeader()
        {
            var batchRef     = $"batch_{Guid.NewGuid()}";
            var changesetRef = $"changeset_{Guid.NewGuid()}";
            var endpoint     = "http://localhost";

            Type[] controllers = new[] { typeof(BatchTestCustomersController), typeof(BatchTestOrdersController), };
            var    server      = TestServerFactory.Create(controllers, (config) =>
            {
                var builder = ODataConventionModelBuilderFactory.Create(config);
                builder.EntitySet <BatchTestOrder>("BatchTestOrders");

                config.MapODataServiceRoute("odata", null, builder.GetEdmModel(), new DefaultODataBatchHandler());
                config.Expand();
                config.EnableDependencyInjection();
            });

            var client = TestServerFactory.CreateClient(server);

            var orderId            = 2;
            var createOrderPayload = $@"{{""@odata.type"":""Microsoft.AspNet.OData.Test.Batch.BatchTestOrder"",""Id"":{orderId},""Amount"":50}}";

            var batchRequest = new HttpRequestMessage(HttpMethod.Post, $"{endpoint}/$batch");

            batchRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/plain"));

            // Add cookie (for example IdentityServer adds antiforgery after login)
            batchRequest.Headers.TryAddWithoutValidation("Cookie", ".AspNetCore.Antiforgery.9TtSrW0hzOs=" + Guid.NewGuid());

            var batchContent = $@"
--{batchRef}
Content-Type: multipart/mixed;boundary={changesetRef}

--{changesetRef}
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

POST {endpoint}/BatchTestOrders HTTP/1.1
Content-Type: application/json;type=entry
Prefer: return=representation

{createOrderPayload}
--{changesetRef}--
--{batchRef}
Content-Type: application/http
Content-Transfer-Encoding: binary

GET {endpoint}/BatchTestOrders({orderId}) HTTP/1.1
Content-Type: application/json;type=entry
Prefer: return=representation

--{batchRef}--
";

            var httpContent = new StringContent(batchContent);

            httpContent.Headers.ContentType   = MediaTypeHeaderValue.Parse($"multipart/mixed;boundary={batchRef}");
            httpContent.Headers.ContentLength = batchContent.Length;
            batchRequest.Content = httpContent;
            var response = await client.SendAsync(batchRequest);

            ExceptionAssert.DoesNotThrow(() => response.EnsureSuccessStatusCode());

            // TODO: assert somehow?
        }
Example #28
0
        public async Task SendAsync_Works_ForBatchRequestWithInsertedEntityReferencedInAnotherRequest()
        {
            const string acceptJsonFullMetadata = "application/json;odata.metadata=minimal";
            const string acceptJson             = "application/json";

            Type[] controllers = new[] { typeof(BatchTestCustomersController), typeof(BatchTestOrdersController), };
            var    server      = TestServerFactory.Create(controllers, (config) =>
            {
                var builder = ODataConventionModelBuilderFactory.Create(config);
                builder.EntitySet <BatchTestCustomer>("BatchTestCustomers");
                builder.EntitySet <BatchTestOrder>("BatchTestOrders");

                config.MapODataServiceRoute("odata", null, builder.GetEdmModel(), new DefaultODataBatchHandler());
                config.Expand();
                config.EnableDependencyInjection();
            });

            var client = TestServerFactory.CreateClient(server);

            var endpoint = "http://localhost";

            var batchRef     = $"batch_{Guid.NewGuid()}";
            var changesetRef = $"changeset_{Guid.NewGuid()}";

            var orderId            = 2;
            var createOrderPayload = $@"{{""@odata.type"":""Microsoft.AspNet.OData.Test.Batch.BatchTestOrder"",""Id"":{orderId},""Amount"":50}}";
            var createRefPayload   = @"{""@odata.id"":""$3""}";

            var batchRequest = new HttpRequestMessage(HttpMethod.Post, $"{endpoint}/$batch");

            batchRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("multipart/mixed"));
            HttpContent httpContent = new StringContent($@"
--{batchRef}
Content-Type: multipart/mixed; boundary={changesetRef}

--{changesetRef}
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

POST {endpoint}/BatchTestOrders HTTP/1.1
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Content-Type: {acceptJsonFullMetadata}
Accept: {acceptJsonFullMetadata}
Accept-Charset: UTF-8

{createOrderPayload}
--{changesetRef}
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 4

POST {endpoint}/BatchTestCustomers(2)/Orders/$ref HTTP/1.1
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Content-Type: {acceptJsonFullMetadata}
Accept: {acceptJsonFullMetadata}
Accept-Charset: UTF-8

{createRefPayload}
--{changesetRef}--
--{batchRef}--
");

            httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse($"multipart/mixed; boundary={batchRef}");
            batchRequest.Content            = httpContent;

            var response = await client.SendAsync(batchRequest);

            ExceptionAssert.DoesNotThrow(() => response.EnsureSuccessStatusCode());

            HttpRequestMessage customerRequest = new HttpRequestMessage(HttpMethod.Get, $"{endpoint}/BatchTestCustomers(2)?$expand=Orders");

            customerRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(acceptJson));

            var customerResponse = client.SendAsync(customerRequest).Result;
            var objAsJsonString  = await customerResponse.Content.ReadAsStringAsync();

            var customer = JsonConvert.DeserializeObject <BatchTestCustomer>(objAsJsonString);

            Assert.NotNull(customer.Orders?.SingleOrDefault(d => d.Id.Equals(orderId)));
        }
        private static IEdmModel GetModel()
        {
            var config = RoutingConfigurationFactory.CreateWithTypes(typeof(Customer));
            ODataModelBuilder builder = ODataConventionModelBuilderFactory.Create(config);

            builder.ContainerName = "C";
            builder.Namespace     = "A.B";
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            // bound actions
            ActionConfiguration primitive = customer.Action("Primitive");

            primitive.Parameter <int>("Quantity");
            primitive.Parameter <string>("ProductCode");
            primitive.Parameter <Date>("Birthday");
            primitive.Parameter <AColor>("BkgColor");
            primitive.Parameter <AColor?>("InnerColor");

            ActionConfiguration complex = customer.Action("Complex");

            complex.Parameter <int>("Quantity");
            complex.Parameter <MyAddress>("Address");

            ActionConfiguration enumType = customer.Action("Enum");

            enumType.Parameter <AColor>("Color");

            ActionConfiguration primitiveCollection = customer.Action("PrimitiveCollection");

            primitiveCollection.Parameter <string>("Name");
            primitiveCollection.CollectionParameter <int>("Ratings");
            primitiveCollection.CollectionParameter <TimeOfDay>("Time");
            primitiveCollection.CollectionParameter <AColor?>("Colors");

            ActionConfiguration complexCollection = customer.Action("ComplexCollection");

            complexCollection.Parameter <string>("Name");
            complexCollection.CollectionParameter <MyAddress>("Addresses");

            ActionConfiguration enumCollection = customer.Action("EnumCollection");

            enumCollection.CollectionParameter <AColor>("Colors");

            ActionConfiguration entity = customer.Action("Entity");

            entity.Parameter <int>("Id");
            entity.EntityParameter <Customer>("Customer");
            entity.EntityParameter <Customer>("NullableCustomer");

            ActionConfiguration entityCollection = customer.Action("EntityCollection");

            entityCollection.Parameter <int>("Id");
            entityCollection.CollectionEntityParameter <Customer>("Customers");

            // unbound actions
            ActionConfiguration unboundPrimitive = builder.Action("UnboundPrimitive");

            unboundPrimitive.Parameter <int>("Quantity");
            unboundPrimitive.Parameter <string>("ProductCode");
            unboundPrimitive.Parameter <Date>("Birthday");
            unboundPrimitive.Parameter <AColor>("BkgColor");
            unboundPrimitive.Parameter <AColor?>("InnerColor");

            ActionConfiguration unboundComplex = builder.Action("UnboundComplex");

            unboundComplex.Parameter <int>("Quantity");
            unboundComplex.Parameter <MyAddress>("Address");

            ActionConfiguration unboundEnum = builder.Action("UnboundEnum");

            unboundEnum.Parameter <AColor>("Color");

            ActionConfiguration unboundPrimitiveCollection = builder.Action("UnboundPrimitiveCollection");

            unboundPrimitiveCollection.Parameter <string>("Name");
            unboundPrimitiveCollection.CollectionParameter <int>("Ratings");
            unboundPrimitiveCollection.CollectionParameter <TimeOfDay>("Time");
            unboundPrimitiveCollection.CollectionParameter <AColor?>("Colors");

            ActionConfiguration unboundComplexCollection = builder.Action("UnboundComplexCollection");

            unboundComplexCollection.Parameter <string>("Name");
            unboundComplexCollection.CollectionParameter <MyAddress>("Addresses");

            ActionConfiguration unboundEnumCollection = builder.Action("UnboundEnumCollection");

            unboundEnumCollection.CollectionParameter <AColor>("Colors");

            ActionConfiguration unboundEntity = builder.Action("UnboundEntity");

            unboundEntity.Parameter <int>("Id");
            unboundEntity.EntityParameter <Customer>("Customer").Nullable = false;
            unboundEntity.EntityParameter <Customer>("NullableCustomer");

            ActionConfiguration unboundEntityCollection = builder.Action("UnboundEntityCollection");

            unboundEntityCollection.Parameter <int>("Id");
            unboundEntityCollection.CollectionEntityParameter <Customer>("Customers");

            return(builder.GetEdmModel());
        }
Example #30
0
        public async Task SendAsync_CorrectlyCopiesHeadersToIndividualRequests(
            IEnumerable <string> batchPreferHeaderValues,
            string getRequest,
            string deleteRequest,
            string postRequest)
        {
            var batchRef               = $"batch_{Guid.NewGuid()}";
            var changesetRef           = $"changeset_{Guid.NewGuid()}";
            var endpoint               = "http://localhost";
            var acceptJsonFullMetadata = "application/json;odata.metadata=minimal";
            var postPayload            = "Bar";

            Type[] controllers = new[] { typeof(BatchTestHeadersCustomersController) };
            var    server      = TestServerFactory.Create(controllers, (config) =>
            {
                var builder = ODataConventionModelBuilderFactory.Create(config);
                builder.EntitySet <BatchTestHeadersCustomer>("BatchTestHeadersCustomers");

                config.MapODataServiceRoute("odata", null, builder.GetEdmModel(), new DefaultODataBatchHandler());
                config.Expand();
                config.EnableDependencyInjection();
            });

            var client = TestServerFactory.CreateClient(server);

            var batchRequest = new HttpRequestMessage(HttpMethod.Post, $"{endpoint}/$batch");

            batchRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("multipart/mixed"));
            batchRequest.Headers.Add("Prefer", batchPreferHeaderValues);

            var batchContent = $@"
--{batchRef}
Content-Type: application/http
Content-Transfer-Encoding: binary

GET {endpoint}/BatchTestHeadersCustomers HTTP/1.1
OData-Version: 4.0
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8


--{batchRef}
Content-Type: application/http
Content-Transfer-Encoding: binary

DELETE {endpoint}/BatchTestHeadersCustomers(1) HTTP/1.1
OData-Version: 4.0
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
Prefer: wait=100,handling=lenient


--{batchRef}
Content-Type: application/http
Content-Transfer-Encoding: binary

POST {endpoint}/BatchTestHeadersCustomers HTTP/1.1
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Content-Type: text/plain; charset=utf-8
Content-Length: {postPayload.Length}
Accept: {acceptJsonFullMetadata}
Accept-Charset: UTF-8

{postPayload}
--{batchRef}--
";

            var httpContent = new StringContent(batchContent);

            httpContent.Headers.ContentType   = MediaTypeHeaderValue.Parse($"multipart/mixed; boundary={batchRef}");
            httpContent.Headers.ContentLength = batchContent.Length;
            batchRequest.Content = httpContent;
            var response = await client.SendAsync(batchRequest);

            ExceptionAssert.DoesNotThrow(() => response.EnsureSuccessStatusCode());
            var responseContent = await response.Content.ReadAsStringAsync();

            Assert.Contains(getRequest, responseContent);
            Assert.Contains(deleteRequest, responseContent);
            Assert.Contains(postRequest, responseContent);
        }