private static void AppendTypeCastIfNeeded(StringBuilder builder, IEdmEntitySet entitySet, IEdmType expectedType) { ExceptionUtilities.CheckArgumentNotNull(builder, "builder"); ExceptionUtilities.CheckArgumentNotNull(entitySet, "entitySet"); IEdmEntityType entityDataType = expectedType as IEdmEntityType; if (entityDataType == null) { return; } if (entitySet.EntityType() == entityDataType) { // same types; nothing to add to the context URI return; } if (entityDataType.InheritsFrom(entitySet.EntityType())) { // derived type; add the type cast segment builder.Append("/"); builder.Append(entityDataType.FullName()); return; } ExceptionUtilities.Assert(false, "Expected entity type has to be compatible with the base entity type of the set."); }
public ODataDeltaFeedSerializerTests() { _model = SerializationTestsHelpers.SimpleCustomerOrderModel(); _customerSet = _model.EntityContainer.FindEntitySet("Customers"); _model.SetAnnotationValue(_customerSet.EntityType(), new ClrTypeAnnotation(typeof(Customer))); _path = new ODataPath(new EntitySetPathSegment(_customerSet)); _customers = new[] { new Customer() { FirstName = "Foo", LastName = "Bar", ID = 10, }, new Customer() { FirstName = "Foo", LastName = "Bar", ID = 42, } }; _deltaFeedCustomers = new EdmChangedObjectCollection(_customerSet.EntityType()); EdmDeltaEntityObject newCustomer = new EdmDeltaEntityObject(_customerSet.EntityType()); newCustomer.TrySetPropertyValue("ID", 10); newCustomer.TrySetPropertyValue("FirstName", "Foo"); _deltaFeedCustomers.Add(newCustomer); _customersType = _model.GetEdmTypeReference(typeof(Customer[])).AsCollection(); _writeContext = new ODataSerializerContext() { NavigationSource = _customerSet, Model = _model, Path = _path }; }
/// <summary> /// Create the collection of <see cref="OpenApiLink"/> object. /// </summary> /// <param name="context">The OData context.</param> /// <param name="entitySet">The Entity Set.</param> /// <returns>The created dictionary of <see cref="OpenApiLink"/> object.</returns> public static IDictionary <string, OpenApiLink> CreateLinks(this ODataContext context, IEdmEntitySet entitySet) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(entitySet, nameof(entitySet)); IDictionary <string, OpenApiLink> links = new Dictionary <string, OpenApiLink>(); IEdmEntityType entityType = entitySet.EntityType(); foreach (var np in entityType.DeclaredNavigationProperties()) { OpenApiLink link = new OpenApiLink(); string typeName = entitySet.EntityType().Name; link.OperationId = entitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(typeName); link.Parameters = new Dictionary <string, RuntimeExpressionAnyWrapper>(); foreach (var key in entityType.Key()) { link.Parameters[key.Name] = new RuntimeExpressionAnyWrapper { Any = new OpenApiString("$request.path." + key.Name) }; } links[np.Name] = link; } return(links); }
public void CreateODataFeed_Ignores_NextPageLink_ForInnerFeeds() { // Arrange ODataFeedSerializer serializer = new ODataFeedSerializer(new DefaultODataSerializerProvider()); Uri nextLink = new Uri("http://somelink"); HttpRequestMessage request = new HttpRequestMessage(); request.ODataProperties().NextLink = nextLink; var result = new object[0]; IEdmNavigationProperty navProp = _customerSet.EntityType().NavigationProperties().First(); SelectExpandClause selectExpandClause = new SelectExpandClause(new SelectItem[0], allSelected: true); EntityInstanceContext entity = new EntityInstanceContext { SerializerContext = new ODataSerializerContext { Request = request, NavigationSource = _customerSet, Model = _model } }; ODataSerializerContext nestedContext = new ODataSerializerContext(entity, selectExpandClause, navProp); // Act ODataFeed feed = serializer.CreateODataFeed(result, _customersType, nestedContext); // Assert Assert.Null(feed.NextPageLink); }
/// <summary> /// Create the Swagger path for the Edm entity. /// </summary> /// <param name="navigationSource">The Edm navigation source.</param> /// <returns>The <see cref="Newtonsoft.Json.Linq.JObject"/> represents the related Edm entity.</returns> public static JObject CreateSwaggerPathForEntity(IEdmNavigationSource navigationSource) { IEdmEntitySet entitySet = navigationSource as IEdmEntitySet; if (entitySet == null) { return(new JObject()); } var keyParameters = new JArray(); foreach (var key in entitySet.EntityType().Key()) { string format; string type = GetPrimitiveTypeAndFormat(key.Type.Definition as IEdmPrimitiveType, out format); keyParameters.Parameter(key.Name, "path", "key: " + key.Name, type, format); } return(new JObject() { { "get", new JObject() .Summary("Get entity from " + entitySet.Name + " by key.") .OperationId(entitySet.Name + "_GetById") .Description("Returns the entity with the key from " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter("$select", "query", "description", "string")) .Responses(new JObject() .Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) .DefaultErrorResponse()) }, { "patch", new JObject() .Summary("Update entity in EntitySet " + entitySet.Name) .OperationId(entitySet.Name + "_PatchById") .Description("Update entity in EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter(entitySet.EntityType().Name, "body", "The entity to patch", entitySet.EntityType())) .Responses(new JObject() .Response("204", "Empty response") .DefaultErrorResponse()) }, { "delete", new JObject() .Summary("Delete entity in EntitySet " + entitySet.Name) .OperationId(entitySet.Name + "_DeleteById") .Description("Delete entity in EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter("If-Match", "header", "If-Match header", "string")) .Responses(new JObject() .Response("204", "Empty response") .DefaultErrorResponse()) } }); }
static JObject CreateSwaggerPathForEntity(IEdmEntitySet entitySet) { var keyParameters = new JArray(); foreach (var key in entitySet.EntityType().Key()) { string format; string type = GetPrimitiveTypeAndFormat(key.Type.Definition as IEdmPrimitiveType, out format); bool required = !key.Type.IsNullable; keyParameters.Parameter(key.Name, "path", "key: " + key.Name, type, format, required); } return(new JObject() { { "get", new JObject() .Summary("Get entity from " + entitySet.Name + " by key.") .Description("Returns the entity with the key from " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter("$select", "query", "description", "string") ) .Responses(new JObject() .Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) .DefaultErrorResponse() ) }, { "patch", new JObject() .Summary("Update entity in EntitySet " + entitySet.Name) .Description("Update entity in EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter(entitySet.EntityType().Name, "body", "The entity to patch", entitySet.EntityType()) ) .Responses(new JObject() .Response("204", "Empty response") .DefaultErrorResponse() ) }, { "delete", new JObject() .Summary("Delete entity in EntitySet " + entitySet.Name) .Description("Delete entity in EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter("If-Match", "header", "If-Match header", "string") ) .Responses(new JObject() .Response("204", "Empty response") .DefaultErrorResponse() ) } }); }
private void WriteProperty(OdcmClass odcmClass, IEdmEntitySet entitySet) { var odcmProperty = new OdcmProperty(entitySet.Name) { Class = odcmClass, Type = ResolveType(entitySet.EntityType().Name, entitySet.EntityType().Namespace, TypeKind.Entity), IsCollection = true, IsLink = true }; odcmClass.Properties.Add(odcmProperty); }
private OdcmField WriteField(OdcmClass odcmClass, IEdmEntitySet entitySet) { OdcmField odcmField = new OdcmField("_" + entitySet.Name); odcmField.Class = odcmClass; odcmClass.Fields.Add(odcmField); odcmField.Type = ResolveType(entitySet.EntityType().Name, entitySet.EntityType().Namespace, TypeKind.Entity); odcmField.IsCollection = true; odcmField.IsLink = true; return(odcmField); }
/// <summary> /// /// </summary> /// <param name="context"></param> public virtual bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } ActionModel action = context.Action; if (context.EntitySet == null || action.Parameters.Count < 1) { // At lease one parameter for the key. return(false); } IEdmEntitySet entitySet = context.EntitySet; var entityType = entitySet.EntityType(); var entityTypeName = entitySet.EntityType().Name; var keys = entitySet.EntityType().Key().ToArray(); string actionName = action.ActionMethod.Name; if ((actionName == "Get" || actionName == $"Get{entityTypeName}" || actionName == "Put" || actionName == $"Put{entityTypeName}" || actionName == "Patch" || actionName == $"Patch{entityTypeName}" || actionName == "Delete" || actionName == $"Delete{entityTypeName}") && keys.Length == action.Parameters.Count) { ODataPathTemplate template = new ODataPathTemplate( new EntitySetSegmentTemplate(entitySet), new KeySegmentTemplate(entityType) ); // support key in parenthesis action.AddSelector(context.Prefix, context.Model, template); // support key as segment ODataPathTemplate newTemplate = template.Clone(); newTemplate.KeyAsSegment = true; action.AddSelector(context.Prefix, context.Model, newTemplate); return(true); } return(false); }
public static OpenApiParameter CreateExpand(this ODataContext context, IEdmEntitySet entitySet) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(entitySet, nameof(entitySet)); return(context.CreateExpand(entitySet, entitySet.EntityType())); }
/// <summary> /// Converts an item from the data store into an ODataEntry. /// </summary> /// <param name="element">The item to convert.</param> /// <param name="entitySet">The entity set that the item belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <returns>The converted ODataEntry.</returns> public static ODataEntry ConvertToODataEntry(object element, IEdmEntitySet entitySet, ODataVersion targetVersion) { IEdmEntityType entityType = entitySet.EntityType(); Uri entryUri = BuildEntryUri(element, entitySet, targetVersion); var entry = new ODataEntry { // writes out the edit link including the service base uri , e.g.: http://<serviceBase>/Customers('ALFKI') EditLink = entryUri, // writes out the self link including the service base uri , e.g.: http://<serviceBase>/Customers('ALFKI') ReadLink = entryUri, // we use the EditLink as the Id for this entity to maintain convention, Id = entryUri, // writes out the <category term='Customer'/> element TypeName = element.GetType().Namespace + "." + entityType.Name, Properties = entityType.StructuralProperties().Select(p => ConvertToODataProperty(element, p.Name)), }; return entry; }
private void VerifyPathItemOperationsForStreamPropertySegment(string annotation, OperationType[] expected) { // Arrange IEdmModel model = GetEdmModel(annotation); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataStreamPropertySegment(sp.Name)); // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); // Assert Assert.NotNull(pathItem); Assert.NotNull(pathItem.Operations); Assert.NotEmpty(pathItem.Operations); Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); }
private MethodCallExpression?GetJoin(Expression outer, MemberExpression navigationProperty) { Type outerType = outer.Type; Type innerType = navigationProperty.Type; IEdmModel?edmModel = _edmModel.GetEdmModel(outerType); if (edmModel == null) { return(null); } Db.OeDataAdapter dataAdapter = edmModel.GetDataAdapter(edmModel.EntityContainer); Db.OeEntitySetAdapter?outerEntitySetAdapter = dataAdapter.EntitySetAdapters.Find(outerType); if (outerEntitySetAdapter == null) { throw new InvalidOperationException("OeEntitySetAdapter not found for type " + outerType.Name); } IEdmEntitySet outerEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, outerEntitySetAdapter.EntitySetName); IEdmNavigationProperty edmNavigationProperty = outerEntitySet.EntityType().NavigationProperties().Single(p => p.Name == navigationProperty.Member.Name); Db.OeEntitySetAdapter?innerEntitySetAdapter = dataAdapter.EntitySetAdapters.Find(innerType); if (innerEntitySetAdapter == null) { throw new InvalidOperationException("OeEntitySetAdapter not found for type " + innerType.Name); } IEdmEntitySet entitySet = edmModel.FindDeclaredEntitySet(innerEntitySetAdapter.EntitySetName); ConstantExpression innerSource = OeEnumerableStub.CreateEnumerableStubExpression(innerType, entitySet); return(GetJoin(outer, innerSource, edmNavigationProperty)); }
private static string AppendSingleColumnKeyTemplate(IEdmEntitySet entitySet, string singleEntityPath) { var key = entitySet.EntityType().Key().Single(); singleEntityPath += "{" + key.Name + "}, "; return(singleEntityPath); }
public async Task ExecuteResultAsync(ActionContext context) { var settings = new ODataMessageWriterSettings() { BaseUri = _odataUri.ServiceRoot, EnableMessageStreamDisposal = false, ODataUri = _odataUri, Validations = ValidationKinds.ThrowIfTypeConflictsWithMetadata | ValidationKinds.ThrowOnDuplicatePropertyNames, Version = ODataVersion.V4 }; var requestHeaders = OeRequestHeaders.Parse(context.HttpContext.Request.Headers["Accept"], context.HttpContext.Request.Headers["Prefer"]); _metadataLevel = requestHeaders.MetadataLevel; if (requestHeaders.MaxPageSize > 0 && PageSize == 0) { PageSize = requestHeaders.MaxPageSize; } IODataResponseMessage responseMessage = new OeInMemoryMessage(context.HttpContext.Response.Body, context.HttpContext.Request.ContentType); using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, _edmModel)) { ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet); IEdmEntitySet edmEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, typeof(T)); IEdmEntityType edmEntityType = edmEntitySet.EntityType(); ODataWriter writer = messageWriter.CreateODataResourceSetWriter(edmEntitySet, edmEntityType); await SerializeAsync(writer); } }
void FillFunctions(IEdmEntitySet entitySetType, string prefix) { var refType = entitySetType.EntityType(); foreach (var functionModel in EdmModel.SchemaElements.OfType <IEdmFunction>() .Where(x => x.IsFunction() && x.IsBound) ) { var bindingParameter = functionModel.Parameters.Where(x => x.Name == "bindingParameter").First(); var bindingTypeDefinition = bindingParameter.Type.Definition as IEdmCollectionType; if (bindingTypeDefinition == null) { continue; } if (bindingTypeDefinition.TypeKind != EdmTypeKind.Collection) { continue; } var entityType = bindingTypeDefinition.ElementType.Definition; if (refType != entityType) { continue; } FillFunction(functionModel, prefix, $"{refType.Name}In{refType.Namespace}OnEntitySet"); } }
public static OpenApiOperation CreateDeleteOperationForEntity(this IEdmEntitySet entitySet) { OpenApiOperation operation = new OpenApiOperation { Summary = "Delete entity from " + entitySet.Name, Tags = new List <string> { entitySet.Name } }; operation.Parameters = CreateKeyParameters(entitySet.EntityType()); operation.Parameters.Add(new OpenApiParameter { Name = "If-Match", In = ParameterLocation.header, Description = "ETag", Schema = new OpenApiSchema { Type = "string" } }); operation.Responses = new OpenApiResponses { "204".GetResponse(), "default".GetResponse() }; return(operation); }
/// <summary> /// Get the Uri Swagger path for the Edm entity set. /// </summary> /// <param name="navigationSource">The Edm navigation source.</param> /// <returns>The <see cref="System.String"/> path represents the related Edm entity set.</returns> public static string GetPathForEntity(IEdmNavigationSource navigationSource) { IEdmEntitySet entitySet = navigationSource as IEdmEntitySet; if (entitySet == null) { return(String.Empty); } string singleEntityPath = "/" + entitySet.Name + "("; foreach (var key in entitySet.EntityType().Key()) { if (key.Type.Definition.TypeKind == EdmTypeKind.Primitive && ((IEdmPrimitiveType)key.Type.Definition).PrimitiveKind == EdmPrimitiveTypeKind.String) { singleEntityPath += "'{" + key.Name + "}', "; } else { singleEntityPath += "{" + key.Name + "}, "; } } singleEntityPath = singleEntityPath.Substring(0, singleEntityPath.Length - 2); singleEntityPath += ")"; return(singleEntityPath); }
public void CreateCollectionNavigationPropertyPathItemReturnsCorrectPathItem(bool containment, bool keySegment, OperationType[] expected) { // Arrange IEdmModel model = GetEdmModel(""); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() .FirstOrDefault(c => c.ContainsTarget == containment && c.TargetMultiplicity() == EdmMultiplicity.Many); Assert.NotNull(property); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataNavigationPropertySegment(property)); if (keySegment) { path.Push(new ODataKeySegment(property.ToEntityType())); } // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); // Assert Assert.NotNull(pathItem); Assert.NotNull(pathItem.Operations); Assert.NotEmpty(pathItem.Operations); Assert.Equal(expected, pathItem.Operations.Select(o => o.Key)); }
public ParameterAliasNodeTranslatorTest() { var builder = new ODataConventionModelBuilder(); builder.EntitySet<ParameterAliasCustomer>("Customers"); builder.EntitySet<ParameterAliasOrder>("Orders"); builder.EntityType<ParameterAliasCustomer>().Function("CollectionFunctionCall") .ReturnsCollection<int>().Parameter<int>("p1"); builder.EntityType<ParameterAliasCustomer>().Function("EntityCollectionFunctionCall") .ReturnsCollectionFromEntitySet<ParameterAliasCustomer>("Customers").Parameter<int>("p1"); builder.EntityType<ParameterAliasCustomer>().Function("SingleEntityFunctionCall") .Returns<ParameterAliasCustomer>().Parameter<int>("p1"); builder.EntityType<ParameterAliasCustomer>().Function("SingleEntityFunctionCallWithoutParameters") .Returns<ParameterAliasCustomer>(); builder.EntityType<ParameterAliasCustomer>().Function("SingleValueFunctionCall") .Returns<int>().Parameter<int>("p1"); _model = builder.GetEdmModel(); _customersEntitySet = _model.FindDeclaredEntitySet("Customers"); _customerEntityType = _customersEntitySet.EntityType(); _parameterAliasMappedNode = new ConstantNode(123); }
/// <summary> /// Converts an item from the data store into an ODataEntry. /// </summary> /// <param name="element">The item to convert.</param> /// <param name="entitySet">The entity set that the item belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <returns>The converted ODataEntry.</returns> public static ODataEntry ConvertToODataEntry(object element, IEdmEntitySet entitySet, ODataVersion targetVersion) { IEdmEntityType entityType = entitySet.EntityType(); Uri entryUri = BuildEntryUri(element, entitySet, targetVersion); var entry = new ODataEntry { // writes out the edit link including the service base uri , e.g.: http://<serviceBase>/Customers('ALFKI') EditLink = entryUri, // writes out the self link including the service base uri , e.g.: http://<serviceBase>/Customers('ALFKI') ReadLink = entryUri, // we use the EditLink as the Id for this entity to maintain convention, Id = entryUri, // writes out the <category term='Customer'/> element TypeName = element.GetType().Namespace + "." + entityType.Name, Properties = entityType.StructuralProperties().Select(p => ConvertToODataProperty(element, p.Name)), }; return(entry); }
public ParameterAliasNodeTranslatorTest() { var builder = new ODataConventionModelBuilder(); builder.EntitySet <ParameterAliasCustomer>("Customers"); builder.EntitySet <ParameterAliasOrder>("Orders"); builder.EntityType <ParameterAliasCustomer>().Function("CollectionFunctionCall") .ReturnsCollection <int>().Parameter <int>("p1"); builder.EntityType <ParameterAliasCustomer>().Function("EntityCollectionFunctionCall") .ReturnsCollectionFromEntitySet <ParameterAliasCustomer>("Customers").Parameter <int>("p1"); builder.EntityType <ParameterAliasCustomer>().Function("SingleEntityFunctionCall") .Returns <ParameterAliasCustomer>().Parameter <int>("p1"); builder.EntityType <ParameterAliasCustomer>().Function("SingleEntityFunctionCallWithoutParameters") .Returns <ParameterAliasCustomer>(); builder.EntityType <ParameterAliasCustomer>().Function("SingleValueFunctionCall") .Returns <int>().Parameter <int>("p1"); _model = builder.GetEdmModel(); _customersEntitySet = _model.FindDeclaredEntitySet("Customers"); _customerEntityType = _customersEntitySet.EntityType(); _parameterAliasMappedNode = new ConstantNode(123); }
public ODataFeedSerializerTests() { _model = SerializationTestsHelpers.SimpleCustomerOrderModel(); _customerSet = _model.EntityContainer.FindEntitySet("Customers"); _model.SetAnnotationValue(_customerSet.EntityType(), new ClrTypeAnnotation(typeof(Customer))); _customers = new[] { new Customer() { FirstName = "Foo", LastName = "Bar", ID = 10, }, new Customer() { FirstName = "Foo", LastName = "Bar", ID = 42, } }; _customersType = _model.GetEdmTypeReference(typeof(Customer[])).AsCollection(); _writeContext = new ODataSerializerContext() { NavigationSource = _customerSet, Model = _model }; }
private ODataResource ReadEntityFromStream(Stream content, Uri requestUrl, String contentType, out IEdmEntitySet entitySet) { ODataUri odataUri = OeParser.ParseUri(_edmModel, _baseUri, requestUrl); entitySet = ((EntitySetSegment)odataUri.Path.FirstSegment).EntitySet; _edmEntityType = entitySet.EntityType(); IEdmModel edmModel = _edmModel.GetEdmModel(entitySet); ODataResource entry = null; IODataRequestMessage requestMessage = new Infrastructure.OeInMemoryMessage(content, contentType, _serviceProvider); var settings = new ODataMessageReaderSettings { ClientCustomTypeResolver = ClientCustomTypeResolver, EnableMessageStreamDisposal = false }; using (var messageReader = new ODataMessageReader(requestMessage, settings, edmModel)) { ODataReader reader = messageReader.CreateODataResourceReader(entitySet, entitySet.EntityType()); while (reader.Read()) { if (reader.State == ODataReaderState.ResourceEnd) { entry = (ODataResource)reader.Item; } } if (entry == null) { throw new InvalidOperationException("operation not contain entry"); } } return(entry); }
public ODataResourceSetSerializerTests() { _model = SerializationTestsHelpers.SimpleCustomerOrderModel(); _customerSet = _model.EntityContainer.FindEntitySet("Customers"); IEdmComplexType addressType = _model.SchemaElements.OfType <IEdmComplexType>() .First(c => c.Name == "Address"); _model.SetAnnotationValue(_customerSet.EntityType(), new ClrTypeAnnotation(typeof(Customer))); _model.SetAnnotationValue(addressType, new ClrTypeAnnotation(typeof(Address))); _customers = new[] { new Customer() { FirstName = "Foo", LastName = "Bar", ID = 10, }, new Customer() { FirstName = "Foo", LastName = "Bar", ID = 42, } }; _customersType = _model.GetEdmTypeReference(typeof(Customer[])).AsCollection(); _addressesType = _model.GetEdmTypeReference(typeof(Address[])).AsCollection(); _writeContext = new ODataSerializerContext() { NavigationSource = _customerSet, Model = _model }; _serializerProvider = ODataSerializerProviderFactory.Create(); }
public static Db.OeBoundFunctionParameter CreateBoundFunctionParameter(OeQueryContext queryContext) { var expressionBuilder = new OeExpressionBuilder(queryContext.JoinBuilder); Type sourceEntityType = queryContext.EntitySetAdapter.EntityType; IEdmEntitySet sourceEntitySet = OeEdmClrHelper.GetEntitySet(queryContext.EdmModel, queryContext.EntitySetAdapter.EntitySetName); Expression source = OeEnumerableStub.CreateEnumerableStubExpression(sourceEntityType, sourceEntitySet); source = expressionBuilder.ApplyNavigation(source, queryContext.ParseNavigationSegments); IEdmEntitySet targetEntitySet = OeOperationHelper.GetEntitySet(queryContext.ODataUri.Path); if (sourceEntitySet != targetEntitySet) { queryContext.ODataUri.Path = new ODataPath(new EntitySetSegment(targetEntitySet)); } expressionBuilder = new OeExpressionBuilder(queryContext.JoinBuilder); Type targetEntityType = queryContext.EdmModel.GetClrType(targetEntitySet.EntityType()); Expression target = OeEnumerableStub.CreateEnumerableStubExpression(targetEntityType, targetEntitySet); target = expressionBuilder.ApplySelect(target, queryContext); var sourceQueryExpression = new OeQueryExpression(queryContext.EdmModel, sourceEntitySet, source); var targetQueryExpression = new OeQueryExpression(queryContext.EdmModel, targetEntitySet, target) { EntryFactory = expressionBuilder.CreateEntryFactory(targetEntitySet) }; Type boundFunctionParameterType = typeof(Db.OeBoundFunctionParameter <,>).MakeGenericType(new[] { sourceEntityType, targetEntityType }); ConstructorInfo ctor = boundFunctionParameterType.GetConstructor(new[] { typeof(OeQueryExpression), typeof(OeQueryExpression) }); return((Db.OeBoundFunctionParameter)ctor.Invoke(new Object[] { sourceQueryExpression, targetQueryExpression })); }
/// <summary> /// Returns the swagger API Operations (Get, Post) associated with an Entity Set (Collection) /// </summary> /// <param name="entitySet"></param> /// <returns></returns> static JObject CreatePathItemObjectForEntitySet(IEdmEntitySet entitySet) { return(new JObject() { { "get", new JObject() .Summary("Get EntitySet " + entitySet.Name) .Description("Returns the EntitySet " + entitySet.Name) .OperationId("Get", entitySet.Name) .Tags(entitySet.Name) .Parameters(new JArray() .Parameter("$search", "query", "Search criteria; name value pair seprate by a colon", "string") .Parameter("$filter", "query", "Filter the response based on one or more criteria", "string") .Parameter("$expand", "query", "Expand navigation property", "string") .Parameter("$select", "query", "select structural property", "string") .Parameter("$orderby", "query", "order by some property", "string") .Parameter("$top", "query", "top elements", "integer") .Parameter("$skip", "query", "skip elements", "integer") .Parameter("$skipToken", "query", "Paging token that is used to get the next or previous set of results", "string") .Parameter("previous-page", "query", "When paging results indicates whether you want the previous page of results", "boolean") .Parameter("$count", "query", "include count in response", "boolean") .DefaultAuthorizationParameter() ) .Responses(new JObject() //.Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) //There's a ResponseArrayRef .ResponseArrayRef("200", "EntitySet " + entitySet.Name, entitySet.EntityType().FullTypeName()) .DefaultErrorResponse() ) }, { "post", new JObject() .Summary("Post a new entity to EntitySet " + entitySet.Name) .Description("Post a new entity to EntitySet " + entitySet.Name) .OperationId("Add", entitySet.Name) .Tags(entitySet.Name) .Parameters(new JArray() .Parameter(entitySet.EntityType().Name, "body", "The entity to post", entitySet.EntityType()) .DefaultAuthorizationParameter() ) .Responses(new JObject() .Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) .DefaultErrorResponse() ) } }); }
/// <summary> /// Returns the path (uri) associated with a collection and/or element /// </summary> /// <param name="entitySet"></param> /// <returns></returns> static string GetPathForEntity(IEdmEntitySet entitySet) { string singleEntityPath = "/" + entitySet.Name; var key = entitySet.EntityType().Key().First(); singleEntityPath += "/{" + key.Name + "}"; return(singleEntityPath); }
public ODataDeltaFeedSerializerTests() { _model = SerializationTestsHelpers.SimpleCustomerOrderModel(); _customerSet = _model.EntityContainer.FindEntitySet("Customers"); _model.SetAnnotationValue(_customerSet.EntityType(), new ClrTypeAnnotation(typeof(Customer))); _path = new ODataPath(new EntitySetSegment(_customerSet)); _customers = new[] { new Customer() { FirstName = "Foo", LastName = "Bar", ID = 10, HomeAddress = new Address() { Street = "Street", ZipCode = null, } }, new Customer() { FirstName = "Foo", LastName = "Bar", ID = 42, } }; _deltaFeedCustomers = new EdmChangedObjectCollection(_customerSet.EntityType()); EdmDeltaEntityObject newCustomer = new EdmDeltaEntityObject(_customerSet.EntityType()); newCustomer.TrySetPropertyValue("ID", 10); newCustomer.TrySetPropertyValue("FirstName", "Foo"); EdmDeltaComplexObject newCustomerAddress = new EdmDeltaComplexObject(_model.FindType("Default.Address") as IEdmComplexType); newCustomerAddress.TrySetPropertyValue("Street", "Street"); newCustomerAddress.TrySetPropertyValue("ZipCode", null); newCustomer.TrySetPropertyValue("HomeAddress", newCustomerAddress); _deltaFeedCustomers.Add(newCustomer); _customersType = _model.GetEdmTypeReference(typeof(Customer[])).AsCollection(); _writeContext = new ODataSerializerContext() { NavigationSource = _customerSet, Model = _model, Path = _path }; _serializerProvider = ODataSerializerProviderFactory.Create(); }
private static string AppendMultiColumnKeyTemplate(IEdmEntitySet entitySet, string singleEntityPath) { foreach (var key in entitySet.EntityType().Key()) { singleEntityPath += key.Name + "={" + key.Name + "}, "; } return(singleEntityPath); }
public void ReadMetadataDocument_WorksForJsonCSDL() { Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""$Version"": ""4.0"", ""$EntityContainer"": ""NS.Container"", ""NS"": { ""Customer"": { ""$Kind"": ""EntityType"", ""$Key"": [ ""Id"" ], ""Id"": { ""$Type"": ""Edm.Int32"" }, ""Name"": {} }, ""Container"": { ""$Kind"": ""EntityContainer"", ""Customers"": { ""$Collection"": true, ""$Type"": ""NS.Customer"" } } } }")); IODataResponseMessage responseMessage = new InMemoryMessage() { StatusCode = 200, Stream = stream }; responseMessage.SetHeader("Content-Type", "application/json"); ODataMessageReader reader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), new EdmModel()); #if NETCOREAPP3_1 || NETCOREAPP2_1 IEdmModel model = reader.ReadMetadataDocument(); IEdmEntityType customerType = model.FindDeclaredType("NS.Customer") as IEdmEntityType; Assert.NotNull(customerType); IEdmProperty idProperty = customerType.FindProperty("Id"); Assert.NotNull(idProperty); Assert.Equal("Edm.Int32", idProperty.Type.FullName()); IEdmProperty nameProperty = customerType.FindProperty("Name"); Assert.NotNull(nameProperty); Assert.Equal("Edm.String", nameProperty.Type.FullName()); IEdmEntitySet customers = Assert.Single(model.EntityContainer.EntitySets()); Assert.Equal("Customers", customers.Name); Assert.Same(customerType, customers.EntityType()); #else Action test = () => reader.ReadMetadataDocument(); ODataException exception = Assert.Throws <ODataException>(test); Assert.Equal("The JSON metadata is not supported at this platform. It's only supported at platform implementing .NETStardard 2.0.", exception.Message); #endif }
private OeEntryFactory(IEdmEntitySet entitySet, OePropertyAccessor[] accessors) { EntitySet = entitySet; Accessors = accessors; EntityType = entitySet.EntityType(); NavigationLinks = Array.Empty <OeEntryFactory>(); _typeName = EntityType.FullName(); }
/// <summary> /// Writes an OData entry. /// </summary> /// <param name="writer">The ODataWriter that will write the entry.</param> /// <param name="element">The item from the data store to write.</param> /// <param name="entitySet">The entity set in the model that the entry belongs to.</param> /// <param name="model">The data store model.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <param name="expandedNavigationProperties">A list of navigation property names to expand.</param> public static void WriteEntry(ODataWriter writer, object element, IEdmEntitySet entitySet, IEdmModel model, ODataVersion targetVersion, IEnumerable<string> expandedNavigationProperties) { var entry = ODataObjectModelConverter.ConvertToODataEntry(element, entitySet, targetVersion); writer.WriteStart(entry); // Here, we write out the links for the navigation properties off of the entity type WriteNavigationLinks(writer, element, entry.ReadLink, entitySet.EntityType(), model, targetVersion, expandedNavigationProperties); writer.WriteEnd(); }
public ODataEntityTypeSerializerTests() { _model = SerializationTestsHelpers.SimpleCustomerOrderModel(); _model.SetAnnotationValue<ClrTypeAnnotation>(_model.FindType("Default.Customer"), new ClrTypeAnnotation(typeof(Customer))); _model.SetAnnotationValue<ClrTypeAnnotation>(_model.FindType("Default.Order"), new ClrTypeAnnotation(typeof(Order))); _customerSet = _model.EntityContainer.FindEntitySet("Customers"); _customer = new Customer() { FirstName = "Foo", LastName = "Bar", ID = 10, }; _serializerProvider = new DefaultODataSerializerProvider(); _customerType = _model.GetEdmTypeReference(typeof(Customer)).AsEntity(); _serializer = new ODataEntityTypeSerializer(_serializerProvider); _path = new ODataPath(new EntitySetPathSegment(_customerSet)); _writeContext = new ODataSerializerContext() { NavigationSource = _customerSet, Model = _model, Path = _path }; _entityInstanceContext = new EntityInstanceContext(_writeContext, _customerSet.EntityType().AsReference(), _customer); }
/// <summary> /// Generates the URI used to reference an entry in the data store. /// </summary> /// <param name="entry">The entry instance to build the URI for.</param> /// <param name="entitySet">The entity set that the entry belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <returns>The generated URI.</returns> public static Uri BuildEntryUri(object entry, IEdmEntitySet entitySet, ODataVersion targetVersion) { string keySegment = BuildKeyString(entry, entitySet.EntityType(), targetVersion); return new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(" + keySegment + ")"); }
private object ProcessPostBody(IncomingRequestMessage message, IEdmEntitySet entitySet) { object lastNewInstance = null; using (var messageReader = new ODataMessageReader(message, this.GetDefaultReaderSettings(), this.Model)) { var odataItemStack = new Stack<ODataItem>(); var entryReader = messageReader.CreateODataEntryReader(entitySet.EntityType()); IEdmEntitySet currentTargetEntitySet = entitySet; while (entryReader.Read()) { switch (entryReader.State) { case ODataReaderState.EntryStart: entryReader.Item.SetAnnotation(new TargetEntitySetAnnotation { TargetEntitySet = currentTargetEntitySet }); odataItemStack.Push(entryReader.Item); break; case ODataReaderState.EntryEnd: { var entry = (ODataEntry)entryReader.Item; var targetEntitySet = entry.GetAnnotation<TargetEntitySetAnnotation>().TargetEntitySet; object newInstance = this.DataContext.CreateNewItem(targetEntitySet); foreach (var property in entry.Properties) { DataContext.UpdatePropertyValue(newInstance, property.Name, property.Value); } var boundNavPropAnnotation = odataItemStack.Pop().GetAnnotation<BoundNavigationPropertyAnnotation>(); if (boundNavPropAnnotation != null) { foreach (var boundProperty in boundNavPropAnnotation.BoundProperties) { bool isCollection = boundProperty.Item1.IsCollection == true; object propertyValue = isCollection ? boundProperty.Item2 : ((IEnumerable<object>)boundProperty.Item2).Single(); DataContext.UpdatePropertyValue(newInstance, boundProperty.Item1.Name, propertyValue); } } var parentItem = odataItemStack.Count > 0 ? odataItemStack.Peek() : null; if (parentItem != null) { // This new entry belongs to a navigation property and/or feed - // propagate it up the tree for further processing. AddChildInstanceAnnotation(parentItem, newInstance); } this.DataContext.AddItem(targetEntitySet, newInstance); lastNewInstance = newInstance; } break; case ODataReaderState.FeedStart: odataItemStack.Push(entryReader.Item); break; case ODataReaderState.FeedEnd: { var childAnnotation = odataItemStack.Pop().GetAnnotation<ChildInstanceAnnotation>(); var parentNavLink = odataItemStack.Count > 0 ? odataItemStack.Peek() as ODataNavigationLink : null; if (parentNavLink != null) { // This feed belongs to a navigation property - // propagate it up the tree for further processing. AddChildInstanceAnnotation(parentNavLink, childAnnotation.ChildInstances ?? new object[0]); } } break; case ODataReaderState.NavigationLinkStart: { odataItemStack.Push(entryReader.Item); var navigationLink = (ODataNavigationLink)entryReader.Item; var navigationProperty = (IEdmNavigationProperty)currentTargetEntitySet.EntityType().FindProperty(navigationLink.Name); // Current model implementation doesn't expose associations otherwise this would be much cleaner. currentTargetEntitySet = this.Model.EntityContainer.EntitySets().Single(s => s.EntityType() == navigationProperty.Type.Definition); } break; case ODataReaderState.NavigationLinkEnd: { var navigationLink = (ODataNavigationLink)entryReader.Item; var childAnnotation = odataItemStack.Pop().GetAnnotation<ChildInstanceAnnotation>(); if (childAnnotation != null) { // Propagate the bound entries to the parent entry. AddBoundNavigationPropertyAnnotation(odataItemStack.Peek(), navigationLink, childAnnotation.ChildInstances); } } break; } } } return lastNewInstance; }
static JObject CreateSwaggerPathForOperationOfEntity(IEdmOperation operation, IEdmEntitySet entitySet) { JArray swaggerParameters = new JArray(); foreach (var key in entitySet.EntityType().Key()) { string format; string type = GetPrimitiveTypeAndFormat(key.Type.Definition as IEdmPrimitiveType, out format); swaggerParameters.Parameter(key.Name, "path", "key: " + key.Name, type, format); } foreach (var parameter in operation.Parameters.Skip(1)) { swaggerParameters.Parameter(parameter.Name, operation is IEdmFunction ? "path" : "body", "parameter: " + parameter.Name, parameter.Type.Definition); } JObject swaggerResponses = new JObject(); if (operation.ReturnType == null) { swaggerResponses.Response("204", "Empty response"); } else { swaggerResponses.Response("200", "Response from " + operation.Name, operation.ReturnType.Definition); } JObject swaggerOperation = new JObject() .Summary("Call operation " + operation.Name) .Description("Call operation " + operation.Name) .Tags(entitySet.Name, operation is IEdmFunction ? "Function" : "Action"); if (swaggerParameters.Count > 0) { swaggerOperation.Parameters(swaggerParameters); } swaggerOperation.Responses(swaggerResponses.DefaultErrorResponse()); return new JObject() { {operation is IEdmFunction ? "get" : "post", swaggerOperation} }; }
static string GetPathForEntity(IEdmEntitySet entitySet) { string singleEntityPath = "/" + entitySet.Name + "("; foreach (var key in entitySet.EntityType().Key()) { if (key.Type.Definition.TypeKind == EdmTypeKind.Primitive && (key.Type.Definition as IEdmPrimitiveType).PrimitiveKind == EdmPrimitiveTypeKind.String) { singleEntityPath += "'{" + key.Name + "}', "; } else { singleEntityPath += "{" + key.Name + "}, "; } } singleEntityPath = singleEntityPath.Substring(0, singleEntityPath.Length - 2); singleEntityPath += ")"; return singleEntityPath; }
private EntitySet ConvertToTaupoEntitySet(IEdmEntitySet edmEntitySet) { var taupoEntitySet = new EntitySet(edmEntitySet.Name); taupoEntitySet.EntityType = new EntityTypeReference(edmEntitySet.EntityType().Namespace, edmEntitySet.EntityType().Name); this.ConvertAnnotationsIntoTaupo(edmEntitySet, taupoEntitySet); return taupoEntitySet; }
private void WriteProperty(OdcmClass odcmClass, IEdmEntitySet entitySet) { var odcmProperty = new OdcmProperty(entitySet.Name) { Class = odcmClass, Type = ResolveType(entitySet.EntityType().Name, entitySet.EntityType().Namespace), IsCollection = true, IsLink = true }; AddVocabularyAnnotations(odcmProperty, entitySet); odcmClass.Properties.Add(odcmProperty); }
private object ProcessPutBody(IncomingRequestMessage message, IEdmEntitySet entitySet, IDictionary<string, object> entityKeys) { using (var messageReader = new ODataMessageReader(message, this.GetDefaultReaderSettings(), this.Model)) { var entryReader = messageReader.CreateODataEntryReader(entitySet.EntityType()); while (entryReader.Read()) { switch(entryReader.State) { case ODataReaderState.EntryEnd: var entry = (ODataEntry)entryReader.Item; foreach (var property in entry.Properties) { this.DataContext.UpdateItem(entitySet, entityKeys, property.Name, property.Value); } break; } } } return this.DataContext.GetItem(entitySet, entityKeys); }
static JObject CreateSwaggerPathForEntity(IEdmEntitySet entitySet) { var keyParameters = new JArray(); foreach (var key in entitySet.EntityType().Key()) { string format; string type = GetPrimitiveTypeAndFormat(key.Type.Definition as IEdmPrimitiveType, out format); keyParameters.Parameter(key.Name, "path", "key: " + key.Name, type, format); } return new JObject() { { "get", new JObject() .Summary("Get entity from " + entitySet.Name + " by key.") .Description("Returns the entity with the key from " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter("$select", "query", "description", "string") ) .Responses(new JObject() .Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) .DefaultErrorResponse() ) }, { "patch", new JObject() .Summary("Update entity in EntitySet " + entitySet.Name) .Description("Update entity in EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter(entitySet.EntityType().Name, "body", "The entity to patch", entitySet.EntityType()) ) .Responses(new JObject() .Response("204", "Empty response") .DefaultErrorResponse() ) }, { "delete", new JObject() .Summary("Delete entity in EntitySet " + entitySet.Name) .Description("Delete entity in EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters((keyParameters.DeepClone() as JArray) .Parameter("If-Match", "header", "If-Match header", "string") ) .Responses(new JObject() .Response("204", "Empty response") .DefaultErrorResponse() ) } }; }
/// <summary>Helper method to add a reference property.</summary> /// <param name="entityType">The entity type to add the property to.</param> /// <param name="name">The name of the property to add.</param> /// <param name="targetEntitySet">The entity set the resource reference property points to.</param> /// <param name="targetEntityType">The entity type the entity set reference property points to.</param> /// <param name="resourceSetReference">true if the property should be a entity set reference, false if it should be an entity reference.</param> private IEdmNavigationProperty AddReferenceProperty(IEdmEntityType entityType, string name, IEdmEntitySet targetEntitySet, IEdmEntityType targetEntityType, bool resourceSetReference, bool containsTarget) { targetEntityType = targetEntityType ?? targetEntitySet.EntityType(); IEdmTypeReference navPropertyTypeReference = resourceSetReference ? new EdmCollectionType(targetEntityType.ToTypeReference(true)).ToTypeReference(true) : targetEntityType.ToTypeReference(true); IEdmNavigationProperty navigationProperty = AddNavigationProperty( entityType, name, EdmOnDeleteAction.None, navPropertyTypeReference, containsTarget); return navigationProperty; }
public static IEnumerable<IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmEntitySet entitySet) { Contract.Assert(model != null); Contract.Assert(entitySet != null); IEnumerable<IEdmStructuralProperty> cachedProperties; if (_concurrencyProperties != null && _concurrencyProperties.TryGetValue(entitySet, out cachedProperties)) { return cachedProperties; } IList<IEdmStructuralProperty> results = new List<IEdmStructuralProperty>(); IEdmEntityType entityType = entitySet.EntityType(); var annotations = model.FindVocabularyAnnotations<IEdmValueAnnotation>(entitySet, CoreVocabularyModel.ConcurrencyTerm); IEdmValueAnnotation annotation = annotations.FirstOrDefault(); if (annotation != null) { IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression; if (properties != null) { foreach (var property in properties.Elements) { IEdmPathExpression pathExpression = property as IEdmPathExpression; if (pathExpression != null) { // So far, we only consider the single path, because only the direct properties from declaring type are used. // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472 string propertyName = pathExpression.Path.Single(); IEdmProperty edmProperty = entityType.FindProperty(propertyName); IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty; if (structuralProperty != null) { results.Add(structuralProperty); } } } } } if (_concurrencyProperties == null) { _concurrencyProperties = new ConcurrentDictionary<IEdmEntitySet, IEnumerable<IEdmStructuralProperty>>(); } _concurrencyProperties[entitySet] = results; return results; }
static JObject CreateSwaggerPathForEntitySet(IEdmEntitySet entitySet) { return new JObject() { { "get", new JObject() .Summary("Get EntitySet " + entitySet.Name) .Description("Returns the EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters(new JArray() .Parameter("$expand", "query", "Expand navigation property", "string") .Parameter("$select", "query", "select structural property", "string") .Parameter("$orderby", "query", "order by some property", "string") .Parameter("$top", "query", "top elements", "integer") .Parameter("$skip", "query", "skip elements", "integer") .Parameter("$count", "query", "inlcude count in response", "boolean") ) .Responses(new JObject() .Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) .DefaultErrorResponse() ) }, { "post", new JObject() .Summary("Post a new entity to EntitySet " + entitySet.Name) .Description("Post a new entity to EntitySet " + entitySet.Name) .Tags(entitySet.Name) .Parameters(new JArray() .Parameter(entitySet.EntityType().Name, "body", "The entity to post", entitySet.EntityType()) ) .Responses(new JObject() .Response("200", "EntitySet " + entitySet.Name, entitySet.EntityType()) .DefaultErrorResponse() ) } }; }