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()); }
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()); }
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); }
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()); }
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); }
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."); }
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); }
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."); }
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); }
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(); }
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(); }
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()); }
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()); }
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? }
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()); }
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); }