Example #1
0
        public void BoundAction_ForEnumTypeInODataModelBuilder()
        {
            // Arrange
            ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <EnumModel> entityTypeConfiguration = builder.EntityType <EnumModel>();
            ActionConfiguration actionConfiguration = entityTypeConfiguration.Action("BoundAction");

            actionConfiguration.CollectionParameter <Color>("Colors");
            actionConfiguration.ReturnsCollection <Color?>();
            builder.Add_Color_EnumType();

            // Act & Assert
            IEdmModel  model  = builder.GetEdmModel();
            IEdmAction action = model.FindDeclaredOperations("Default.BoundAction").Single() as IEdmAction;

            IEdmTypeReference colors     = action.Parameters.Single(p => p.Name == "Colors").Type;
            IEdmTypeReference returnType = action.ReturnType;
            IEdmEnumType      colorType  = model.SchemaElements.OfType <IEdmEnumType>().Single(e => e.Name == "Color");

            Assert.True(colors.IsCollection());
            Assert.Same(colorType, colors.AsCollection().ElementType().Definition);
            Assert.True(returnType.IsCollection());
            Assert.True(returnType.AsCollection().ElementType().IsNullable);
            Assert.Same(colorType, returnType.AsCollection().ElementType().Definition);
        }
        public void CanCreateEdmModel_WithDateAndTimeOfDay_AsActionParameter(Type paramType, string expect)
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var actionBuilder = movie.Action("ActionName");

            actionBuilder.Parameter(paramType, "p1");

            MethodInfo method = typeof(OperationConfiguration).GetMethod("CollectionParameter", BindingFlags.Instance | BindingFlags.Public);

            method.MakeGenericMethod(paramType).Invoke(actionBuilder, new[] { "p2" });

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

            //Assert
            IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.Equal("ActionName", action.Name);

            IEdmOperationParameter parameter = action.FindParameter("p1");

            Assert.Equal(expect, parameter.Type.FullName());
            Assert.Equal(paramType.IsNullable(), parameter.Type.IsNullable);

            parameter = action.FindParameter("p2");
            Assert.Equal("Collection(" + expect + ")", parameter.Type.FullName());
            Assert.Equal(paramType.IsNullable(), parameter.Type.IsNullable);
        }
Example #3
0
        public void CanManuallyConfigureActionLinkFactory()
        {
            // Arrange
            string            uriTemplate = "http://server/service/Customers({0})/Reward";
            Uri               expectedUri = new Uri(string.Format(uriTemplate, 1));
            ODataModelBuilder builder     = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.CustomerId);
            customer.Property(c => c.Name);

            // Act
            ActionConfiguration reward = customer.Action("Reward");

            reward.HasActionLink(ctx => new Uri(string.Format(uriTemplate, ctx.GetPropertyValue("CustomerId"))),
                                 followsConventions: false);
            IEdmModel              model             = builder.GetEdmModel();
            IEdmEntityType         customerType      = model.SchemaElements.OfType <IEdmEntityType>().SingleOrDefault();
            ODataSerializerContext serializerContext = new ODataSerializerContext {
                Model = model
            };

            EntityInstanceContext context = new EntityInstanceContext(serializerContext, customerType.AsReference(), new Customer {
                CustomerId = 1
            });
            IEdmAction        rewardAction      = Assert.Single(model.SchemaElements.OfType <IEdmAction>()); // Guard
            ActionLinkBuilder actionLinkBuilder = model.GetAnnotationValue <ActionLinkBuilder>(rewardAction);

            //Assert
            Assert.Equal(expectedUri, reward.GetActionLink()(context));
            Assert.NotNull(actionLinkBuilder);
            Assert.Equal(expectedUri, actionLinkBuilder.BuildActionLink(context));
        }
Example #4
0
        public void GetEdmModel_ThrowsException_WhenBoundActionOverloaded()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntityType <Customer>();

            customer.HasKey(c => c.CustomerId);
            customer.Property(c => c.Name);
            customer.Action("ActionOnCustomer");
            customer.Action("ActionOnCustomer").Returns <string>();

            // Act & Assert
            Assert.Throws <InvalidOperationException>(() => builder.GetEdmModel(),
                                                      "Found more than one action with name 'ActionOnCustomer' " +
                                                      "bound to the same type 'System.Web.OData.Builder.TestModels.Customer'. " +
                                                      "Each bound action must have a different binding type or name.");
        }
Example #5
0
        public void DollarMetadata_Works_WithActionParameterNullable_ReturnTypeNullable()
        {
            // Arrange
            const string expectMetadata =
                @"<Schema Namespace='Default' xmlns='http://docs.oasis-open.org/odata/ns/edm'>
      <Action Name='NullableAction' IsBound='true'>
        <Parameter Name='bindingParameter' Type='System.Web.OData.Formatter.FormatterPerson' />
        <Parameter Name='param' Type='Edm.String' Unicode='false' />
        <ReturnType Type='System.Web.OData.Formatter.FormatterAddress' />
      </Action>
      <Action Name='NonNullableAction' IsBound='true'>
        <Parameter Name='bindingParameter' Type='System.Web.OData.Formatter.FormatterPerson' />
        <Parameter Name='param' Type='Edm.String' Nullable='false' Unicode='false' />
        <ReturnType Type='System.Web.OData.Formatter.FormatterAddress' Nullable='false' />
      </Action>
      <EntityContainer Name='Container' />
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>";

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            EntityTypeConfiguration <FormatterPerson> person = builder.EntityType <FormatterPerson>();

            ActionConfiguration action = person.Action("NullableAction").Returns <FormatterAddress>();

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

            action = person.Action("NonNullableAction").Returns <FormatterAddress>();
            action.OptionalReturn = false;
            action.Parameter <string>("param").OptionalParameter = false;
            IEdmModel model = builder.GetEdmModel();

            var config = new[] { typeof(MetadataController) }.GetHttpConfiguration();

            config.MapODataServiceRoute(model);
            HttpServer server = new HttpServer(config);
            HttpClient client = new HttpClient(server);

            // Act
            var response = client.GetAsync("http://localhost/$metadata").Result;

            // Assert
            Assert.True(response.IsSuccessStatusCode);
            Assert.Equal("application/xml", response.Content.Headers.ContentType.MediaType);
            Assert.Contains(expectMetadata.Replace("'", "\""), response.Content.ReadAsStringAsync().Result);
        }
Example #6
0
        private static void AddBoundActionsAndFunctions(EntityTypeConfiguration<Employee> employee)
        {
            var actionConfiguration = employee.Action("AddSkill");
            actionConfiguration.Parameter<Skill>("skill");
            actionConfiguration.ReturnsCollection<Skill>();

            var functionConfiguration = employee.Function("GetAccessLevel");
            functionConfiguration.Returns<AccessLevel>();
        }
        public void GetEdmModel_SetReturnTypeAsNullable()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;

            movie.Action("Watch1").Returns <Address>();
            movie.Action("Watch2").Returns <Address>().OptionalReturn = false;

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

            //Assert
            IEdmOperation action = model.SchemaElements.OfType <IEdmAction>().First(e => e.Name == "Watch1");

            Assert.True(action.ReturnType.IsNullable);

            action = model.SchemaElements.OfType <IEdmAction>().First(e => e.Name == "Watch2");
            Assert.False(action.ReturnType.IsNullable);
        }
        public void HasFeedActionLink_ThrowsException_OnNoBoundToCollectionEntityActions()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntityType <Customer>();
            ActionConfiguration action = customer.Action("NonCollectionAction");

            // Act & Assert
            Assert.Throws <InvalidOperationException>(
                () => action.HasFeedActionLink(ctx => new Uri("http://any"), followsConventions: false),
                "To register an action link factory, actions must be bindable to the collection of entity. " +
                "Action 'NonCollectionAction' does not meet this requirement.");
        }
        public void CanCreateActionThatBindsToEntity()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntityType <Customer>();
            ActionConfiguration sendEmail = customer.Action("SendEmail");

            // Assert
            Assert.True(sendEmail.IsBindable);
            Assert.NotNull(sendEmail.Parameters);
            Assert.Equal(1, sendEmail.Parameters.Count());
            Assert.Equal(BindingParameterConfiguration.DefaultBindingParameterName, sendEmail.Parameters.Single().Name);
            Assert.Equal(typeof(Customer).FullName, sendEmail.Parameters.Single().TypeConfiguration.FullName);
        }
        public void GetEdmModel_SetsNullableIfParameterTypeIsReferenceType()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var actionBuilder = movie.Action("Watch");

            actionBuilder.Parameter <string>("string").OptionalParameter = false;
            actionBuilder.Parameter <string>("nullaleString");

            actionBuilder.Parameter <Address>("address").OptionalParameter = false;
            actionBuilder.Parameter <Address>("nullableAddress");

            actionBuilder.EntityParameter <Customer>("customer").OptionalParameter = false;
            actionBuilder.EntityParameter <Customer>("nullableCustomer");

            actionBuilder.CollectionParameter <Address>("addresses").OptionalParameter = false;
            actionBuilder.CollectionParameter <Address>("nullableAddresses");

            actionBuilder.CollectionEntityParameter <Customer>("customers").OptionalParameter = false;
            actionBuilder.CollectionEntityParameter <Customer>("nullableCustomers");

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

            //Assert
            IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.False(action.FindParameter("string").Type.IsNullable);
            Assert.True(action.FindParameter("nullaleString").Type.IsNullable);

            Assert.False(action.FindParameter("address").Type.IsNullable);
            Assert.True(action.FindParameter("nullableAddress").Type.IsNullable);

            Assert.False(action.FindParameter("customer").Type.IsNullable);
            Assert.True(action.FindParameter("nullableCustomer").Type.IsNullable);

            Assert.False(action.FindParameter("addresses").Type.IsNullable);
            Assert.True(action.FindParameter("nullableAddresses").Type.IsNullable);

            // Follow up: https://github.com/OData/odata.net/issues/98
            // Assert.False(action.FindParameter("customers").Type.IsNullable);
            Assert.True(action.FindParameter("nullableCustomers").Type.IsNullable);
        }
        public void BuilderIncludesMapFromEntityTypeToBindableOperations()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.Id);
            customer.Property(c => c.Name);
            customer.Action("Reward");
            IEdmModel      model        = builder.GetEdmModel();
            IEdmEntityType customerType = model.SchemaElements.OfType <IEdmEntityType>().SingleOrDefault();

            // Act
            BindableOperationFinder finder = model.GetAnnotationValue <BindableOperationFinder>(model);

            // Assert
            Assert.NotNull(finder);
            Assert.NotNull(finder.FindOperations(customerType).SingleOrDefault());
            Assert.Equal("Reward", finder.FindOperations(customerType).SingleOrDefault().Name);
        }
Example #12
0
        public void GetEdmModel_SetsNullableIffParameterTypeIsNullable()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var actionBuilder = movie.Action("Watch");

            actionBuilder.Parameter <int>("int");
            actionBuilder.Parameter <Nullable <int> >("nullableOfInt");
            actionBuilder.Parameter <string>("string");

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

            //Assert
            IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.False(action.FindParameter("int").Type.IsNullable);
            Assert.True(action.FindParameter("nullableOfInt").Type.IsNullable);
            Assert.True(action.FindParameter("string").Type.IsNullable);
        }
Example #13
0
        public void ODataConventionModelBuilder_HasCorrectEnumMember_AddBoundActionAfterEntitySet()
        {
            // Arrange
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            EntityTypeConfiguration <EntityTypeWithEnumTypePropertyTestModel> entity =
                builder.EntitySet <EntityTypeWithEnumTypePropertyTestModel>("Entities").EntityType;

            entity.Action("BoundAction").Parameter <Color?>("Color");
            builder.EnumTypes.Single(e => e.Name == "Color").RemoveMember(Color.Green);

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

            // Assert
            Assert.NotNull(model);
            IEnumerable <IEdmEnumType> colors = model.SchemaElements.OfType <IEdmEnumType>().Where(e => e.Name == "Color");
            IEdmEnumType color = Assert.Single(colors);

            Assert.Equal(2, color.Members.Count());
            Assert.Single(color.Members.Where(m => m.Name == "Red"));
            Assert.Single(color.Members.Where(m => m.Name == "Blue"));
        }
Example #14
0
        public void WhenActionLinksNotManuallyConfigured_ConventionBasedBuilderUsesConventions()
        {
            // Arrange
            string            uriTemplate         = "http://server/Movies({0})/Default.Watch";
            Uri               expectedUri         = new Uri(string.Format(uriTemplate, 1));
            ODataModelBuilder builder             = new ODataConventionModelBuilder();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            ActionConfiguration             watch = movie.Action("Watch");
            IEdmModel model = builder.GetEdmModel();

            HttpRequestMessage request       = new HttpRequestMessage(HttpMethod.Get, "http://server/Movies");
            HttpConfiguration  configuration = new HttpConfiguration();
            string             routeName     = "Route";

            configuration.MapODataServiceRoute(routeName, null, model);
            request.SetConfiguration(configuration);
            request.ODataProperties().RouteName = routeName;
            UrlHelper urlHelper = new UrlHelper(request);

            // Act
            IEdmEntityType         movieType         = model.SchemaElements.OfType <IEdmEntityType>().SingleOrDefault();
            IEdmEntityContainer    container         = model.SchemaElements.OfType <IEdmEntityContainer>().SingleOrDefault();
            IEdmAction             watchAction       = Assert.Single(model.SchemaElements.OfType <IEdmAction>()); // Guard
            IEdmEntitySet          entitySet         = container.EntitySets().SingleOrDefault();
            ODataSerializerContext serializerContext = new ODataSerializerContext {
                Model = model, NavigationSource = entitySet, Url = urlHelper
            };

            EntityInstanceContext context = new EntityInstanceContext(serializerContext, movieType.AsReference(), new Movie {
                ID = 1, Name = "Avatar"
            });
            ActionLinkBuilder actionLinkBuilder = model.GetAnnotationValue <ActionLinkBuilder>(watchAction);

            //Assert
            Assert.Equal(expectedUri, watch.GetActionLink()(context));
            Assert.NotNull(actionLinkBuilder);
            Assert.Equal(expectedUri, actionLinkBuilder.BuildActionLink(context));
        }
Example #15
0
        public void CanCreateEdmModel_WithBindableAction()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntityType <Customer>();

            customer.HasKey(c => c.CustomerId);
            customer.Property(c => c.Name);

            // Act
            ActionConfiguration sendEmail = customer.Action("ActionName");
            IEdmModel           model     = builder.GetEdmModel();

            // Assert
            IEdmAction action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.True(action.IsBound);
            Assert.Equal("ActionName", action.Name);
            Assert.Null(action.ReturnType);
            Assert.Equal(1, action.Parameters.Count());
            Assert.Equal(BindingParameterConfiguration.DefaultBindingParameterName, action.Parameters.Single().Name);
            Assert.Equal(typeof(Customer).FullName, action.Parameters.Single().Type.FullName());
        }
        public void GetEdmModel_SetsDateTimeAsParameterType()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var actionBuilder = movie.Action("DateTimeAction");

            actionBuilder.Parameter <DateTime>("dateTime");
            actionBuilder.Parameter <DateTime?>("nullableDateTime");
            actionBuilder.CollectionParameter <DateTime>("collectionDateTime");
            actionBuilder.CollectionParameter <DateTime?>("nullableCollectionDateTime");

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

            //Assert
            IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.Equal("DateTimeAction", action.Name);

            IEdmOperationParameter parameter = action.FindParameter("dateTime");

            Assert.Equal("Edm.DateTimeOffset", parameter.Type.FullName());
            Assert.False(parameter.Type.IsNullable);

            parameter = action.FindParameter("nullableDateTime");
            Assert.Equal("Edm.DateTimeOffset", parameter.Type.FullName());
            Assert.True(parameter.Type.IsNullable);

            parameter = action.FindParameter("collectionDateTime");
            Assert.Equal("Collection(Edm.DateTimeOffset)", parameter.Type.FullName());
            Assert.False(parameter.Type.IsNullable);

            parameter = action.FindParameter("nullableCollectionDateTime");
            Assert.Equal("Collection(Edm.DateTimeOffset)", parameter.Type.FullName());
            Assert.True(parameter.Type.IsNullable);
        }
Example #17
0
        private static void AddBoundActionsAndFunctions(EntityTypeConfiguration<Account> account)
        {
            account.Function("GetAddressFunction").Returns<Address>();

            account.Function("GetShipAddresses").ReturnsCollection<Address>();
            account.Action("IncreaseAgeAction").Returns<AccountInfo>();

            ActionConfiguration addShipAddress = account.Action("AddShipAddress");
            addShipAddress.Parameter<Address>("address");
            addShipAddress.Returns<int>();// Total ship addresses count.
        }
Example #18
0
        public void CanBuildBoundOperationCacheForIEdmModel()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.ID);
            customer.Property(c => c.Name);
            customer.ComplexProperty(c => c.Address);

            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;

            movie.HasKey(m => m.ID);
            movie.HasKey(m => m.Name);
            EntityTypeConfiguration <Blockbuster> blockBuster = builder.EntityType <Blockbuster>().DerivesFrom <Movie>();
            EntityTypeConfiguration movieConfiguration        = builder.StructuralTypes.OfType <EntityTypeConfiguration>().Single(t => t.Name == "Movie");

            // build actions that are bindable to a single entity
            customer.Action("InCache1_CustomerAction");
            customer.Action("InCache2_CustomerAction");
            movie.Action("InCache3_MovieAction");
            ActionConfiguration incache4_MovieAction = builder.Action("InCache4_MovieAction");

            incache4_MovieAction.SetBindingParameter("bindingParameter", movieConfiguration);
            blockBuster.Action("InCache5_BlockbusterAction");

            // build actions that are either: bindable to a collection of entities, have no parameter, have only complex parameter
            customer.Collection.Action("NotInCache1_CustomersAction");
            movie.Collection.Action("NotInCache2_MoviesAction");
            ActionConfiguration notInCache3_NoParameters     = builder.Action("NotInCache3_NoParameters");
            ActionConfiguration notInCache4_AddressParameter = builder.Action("NotInCache4_AddressParameter");

            notInCache4_AddressParameter.Parameter <Address>("address");

            IEdmModel      model           = builder.GetEdmModel();
            IEdmEntityType customerType    = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Customer");
            IEdmEntityType movieType       = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Movie");
            IEdmEntityType blockBusterType = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Blockbuster");

            // Act
            BindableOperationFinder annotation = new BindableOperationFinder(model);

            IEdmAction[] movieActions = annotation.FindOperations(movieType)
                                        .OfType <IEdmAction>()
                                        .ToArray();
            IEdmAction[] customerActions = annotation.FindOperations(customerType)
                                           .OfType <IEdmAction>()
                                           .ToArray();
            IEdmAction[] blockBusterActions = annotation.FindOperations(blockBusterType)
                                              .OfType <IEdmAction>()
                                              .ToArray();

            // Assert
            Assert.Equal(2, customerActions.Length);
            Assert.NotNull(customerActions.SingleOrDefault(a => a.Name == "InCache1_CustomerAction"));
            Assert.NotNull(customerActions.SingleOrDefault(a => a.Name == "InCache2_CustomerAction"));
            Assert.Equal(2, movieActions.Length);
            Assert.NotNull(movieActions.SingleOrDefault(a => a.Name == "InCache3_MovieAction"));
            Assert.NotNull(movieActions.SingleOrDefault(a => a.Name == "InCache4_MovieAction"));
            Assert.Equal(3, blockBusterActions.Length);
            Assert.NotNull(blockBusterActions.SingleOrDefault(a => a.Name == "InCache3_MovieAction"));
            Assert.NotNull(blockBusterActions.SingleOrDefault(a => a.Name == "InCache4_MovieAction"));
            Assert.NotNull(blockBusterActions.SingleOrDefault(a => a.Name == "InCache5_BlockbusterAction"));
        }
Example #19
0
        public void CanBuildOperationBoundToCollectionCacheForIEdmModel()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.ID);
            customer.Property(c => c.Name);
            customer.ComplexProperty(c => c.Address);

            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;

            movie.HasKey(m => m.ID);
            movie.HasKey(m => m.Name);
            EntityTypeConfiguration <Blockbuster> blockBuster = builder.EntityType <Blockbuster>().DerivesFrom <Movie>();
            EntityTypeConfiguration movieConfiguration        = builder.StructuralTypes.OfType <EntityTypeConfiguration>().Single(t => t.Name == "Movie");

            // build actions that are bindable to the collection of entity
            customer.Collection.Action("CollectionCustomerActionInCache1");
            customer.Collection.Action("CollectionCustomerActionInCache2");
            movie.Collection.Action("CollectionMovieActionInCache3");

            ActionConfiguration         movieActionIncache4     = builder.Action("CollectionMovieActionInCache4");
            CollectionTypeConfiguration collectionConfiguration = new CollectionTypeConfiguration(movieConfiguration, typeof(Movie));

            movieActionIncache4.SetBindingParameter("bindingParameter", collectionConfiguration);

            blockBuster.Collection.Action("CollectionBlockbusterActionInCache5");

            // build functions that are bindable to the collection of entity
            customer.Collection.Function("CollectionCustomerFunctionInCache1").Returns <int>();
            customer.Collection.Function("CollectionCustomerFunctionInCache2").Returns <int>();
            movie.Collection.Function("CollectionMovieFunctionInCache3").Returns <int>();
            blockBuster.Collection.Function("CollectionBlockbusterFunctionInCache5").Returns <int>();

            // build actions that are either: bindable to an entity, have no parameter, have only complex parameter
            customer.Action("CustomersActionNotInCache1");
            customer.Function("CustomersFunctionNotInCache1").Returns <int>();
            movie.Action("MoviesActionNotInCache2");
            builder.Action("NoParametersNotInCache3");

            ActionConfiguration addressParameterNotInCache4 = builder.Action("AddressParameterNotInCache4");

            addressParameterNotInCache4.Parameter <Address>("address");

            IEdmModel model = builder.GetEdmModel();

            IEdmEntityType customerType    = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Customer");
            IEdmEntityType movieType       = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Movie");
            IEdmEntityType blockBusterType = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Blockbuster");

            // Act
            BindableOperationFinder annotation = new BindableOperationFinder(model);
            var movieOperations       = annotation.FindOperationsBoundToCollection(movieType).ToArray();
            var customerOperations    = annotation.FindOperationsBoundToCollection(customerType).ToArray();
            var blockBusterOperations = annotation.FindOperationsBoundToCollection(blockBusterType).ToArray();

            // Assert
            Assert.Equal(3, movieOperations.Length);
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieActionInCache3"));
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieActionInCache4"));
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieFunctionInCache3"));

            Assert.Equal(4, customerOperations.Length);
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerActionInCache1"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerActionInCache2"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerFunctionInCache1"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerFunctionInCache2"));

            Assert.Equal(5, blockBusterOperations.Length);
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionBlockbusterActionInCache5"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionBlockbusterFunctionInCache5"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieActionInCache3"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieActionInCache4"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieFunctionInCache3"));
        }