/// <summary> /// Create a map of string/<see cref="OpenApiSchema"/> map for a <see cref="IEdmStructuredType"/>'s all properties. /// </summary> /// <param name="context">The OData context.</param> /// <param name="structuredType">The Edm structured type.</param> /// <returns>The created map of <see cref="OpenApiSchema"/>.</returns> public static IDictionary <string, OpenApiSchema> CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(structuredType, nameof(structuredType)); // The name is the property name, the value is a Schema Object describing the allowed values of the property. IDictionary <string, OpenApiSchema> properties = new Dictionary <string, OpenApiSchema>(); // structure properties foreach (var property in structuredType.DeclaredStructuralProperties()) { OpenApiSchema propertySchema = context.CreatePropertySchema(property); propertySchema.Description = context.Model.GetDescriptionAnnotation(property); propertySchema.Extensions.AddCustomAtributesToExtensions(context, property); properties.Add(property.Name, propertySchema); } // navigation properties foreach (var property in structuredType.DeclaredNavigationProperties()) { OpenApiSchema propertySchema = context.CreateEdmTypeSchema(property.Type); propertySchema.Description = context.Model.GetDescriptionAnnotation(property); propertySchema.Extensions.AddCustomAtributesToExtensions(context, property); properties.Add(property.Name, propertySchema); } return(properties); }
/// <summary> /// Create a map of string/<see cref="OpenApiSchema"/> map for a <see cref="IEdmStructuredType"/>'s all properties. /// </summary> /// <param name="context">The OData context.</param> /// <param name="structuredType">The Edm structured type.</param> /// <returns>The created map of <see cref="OpenApiSchema"/>.</returns> public static IDictionary <string, OpenApiSchema> CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(structuredType, nameof(structuredType)); // The name is the property name, the value is a Schema Object describing the allowed values of the property. IDictionary <string, OpenApiSchema> properties = new Dictionary <string, OpenApiSchema>(); // structure properties foreach (var property in structuredType.DeclaredStructuralProperties()) { // OpenApiSchema propertySchema = property.Type.CreateSchema(); // propertySchema.Default = property.DefaultValueString != null ? new OpenApiString(property.DefaultValueString) : null; properties.Add(property.Name, context.CreatePropertySchema(property)); } // navigation properties foreach (var property in structuredType.DeclaredNavigationProperties()) { OpenApiSchema propertySchema = context.CreateEdmTypeSchema(property.Type); properties.Add(property.Name, propertySchema); } return(properties); }
private IDictionary <string, OpenApiSchema> VisitStructuredTypeProperties(IEdmStructuredType structuredType) { IDictionary <string, OpenApiSchema> properties = new Dictionary <string, OpenApiSchema>(); foreach (var property in structuredType.DeclaredStructuralProperties()) { OpenApiSchema propertySchema = VisitTypeReference(property.Type); properties.Add(property.Name, propertySchema); } foreach (var property in structuredType.DeclaredNavigationProperties()) { OpenApiSchema propertySchema = VisitTypeReference(property.Type); properties.Add(property.Name, propertySchema); } return(properties); }
/// <inheritdoc /> public bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } Debug.Assert(context.Action != null); ActionModel action = context.Action; string actionMethodName = action.ActionMethod.Name; // Need to refactor the following // for example: CreateRef( with the navigation property parameter) should for all navigation properties // CreateRefToOrdersFromCustomer, CreateRefToOrders, CreateRef. string method = SplitRefActionName(actionMethodName, out string httpMethod, out string property, out string declaring); if (method == null) { return(false); } // Action parameter should have a (string navigationProperty) parameter if (!action.HasParameter <string>("navigationProperty")) { return(false); } IEdmNavigationSource navigationSource; IEdmEntityType entityType; if (context.EntitySet != null) { entityType = context.EntitySet.EntityType(); navigationSource = context.EntitySet; } else { entityType = context.Singleton.EntityType(); navigationSource = context.Singleton; } // For entity set, we should have the key parameter // For Singleton, we should not have the key parameter bool hasODataKeyParameter = action.HasODataKeyParameter(entityType); if ((context.EntitySet != null && !hasODataKeyParameter) || (context.Singleton != null && hasODataKeyParameter)) { return(false); } // Find the navigation property declaring type IEdmStructuredType declaringType = entityType; if (declaring != null) { declaringType = entityType.FindTypeInInheritance(context.Model, declaring); if (declaringType == null) { return(false); } } // Find the navigation property if have IEdmNavigationProperty navigationProperty = null; if (property != null) { navigationProperty = declaringType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == property); if (navigationProperty == null) { return(false); } } IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); segments.Add(new KeySegmentTemplate(entityType)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (entityType != declaringType) { segments.Add(new CastSegmentTemplate(declaringType, entityType, navigationSource)); } if (navigationProperty != null) { segments.Add(new NavigationSegmentTemplate(navigationProperty)); } else { //TODO: Add the navigation template segment template, // Or add the template for all navigation properties? return(false); } IEdmEntityType navigationPropertyType = navigationProperty.Type.GetElementTypeOrSelf().AsEntity().EntityDefinition(); bool hasNavigationPropertyKeyParameter = action.HasODataKeyParameter(navigationPropertyType, "relatedKey"); if (hasNavigationPropertyKeyParameter) { segments.Add(new KeySegmentTemplate(navigationPropertyType, "relatedKey")); } IEdmNavigationSource targetNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, segments, out _); segments.Add(new RefSegmentTemplate(navigationProperty, targetNavigationSource)); // TODO: support key as segment? ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(httpMethod, context.Prefix, context.Model, template); // processed return(true); }
/// <inheritdoc /> public bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw Error.ArgumentNull(nameof(context)); } Debug.Assert(context.Action != null); ActionModel action = context.Action; string actionMethodName = action.ActionName; // Need to refactor the following // for example: CreateRef( with the navigation property parameter) should for all navigation properties // CreateRefToOrdersFromCustomer, CreateRefToOrders, CreateRef. string method = SplitRefActionName(actionMethodName, out string httpMethod, out string property, out string declaring); if (method == null) { return(false); } IEdmNavigationSource navigationSource = context.NavigationSource; IEdmEntityType entityType = context.EntityType; // For entity set, we should have the key parameter // For Singleton, we should not have the key parameter bool hasODataKeyParameter = action.HasODataKeyParameter(entityType); if ((context.EntitySet != null && !hasODataKeyParameter) || (context.Singleton != null && hasODataKeyParameter)) { return(false); } // Find the navigation property declaring type IEdmStructuredType declaringType = entityType; if (declaring != null) { declaringType = entityType.FindTypeInInheritance(context.Model, declaring); if (declaringType == null) { return(false); } } // Process the generic scenario if (property == null) { return(ProcessNonNavigationProperty(httpMethod, context, action, navigationSource, entityType, declaringType)); } // Find the navigation property if have IEdmNavigationProperty navigationProperty = null; if (property != null) { navigationProperty = declaringType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == property); } if (navigationProperty == null) { return(false); } IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); segments.Add(KeySegmentTemplate.CreateKeySegment(entityType, context.EntitySet)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (entityType != declaringType) { segments.Add(new CastSegmentTemplate(declaringType, entityType, navigationSource)); } IEdmNavigationSource targetNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, segments, out _); NavigationLinkSegmentTemplate linkTemplate = new NavigationLinkSegmentTemplate(navigationProperty, targetNavigationSource); IEdmEntityType navigationPropertyType = navigationProperty.Type.GetElementTypeOrSelf().AsEntity().EntityDefinition(); bool hasNavigationPropertyKeyParameter = action.HasODataKeyParameter(navigationPropertyType, "relatedKey"); if (hasNavigationPropertyKeyParameter) { linkTemplate.Key = KeySegmentTemplate.CreateKeySegment(navigationPropertyType, targetNavigationSource, "relatedKey"); } else { hasNavigationPropertyKeyParameter = action.HasODataKeyParameter(navigationPropertyType, "relatedId"); if (hasNavigationPropertyKeyParameter) { linkTemplate.Key = KeySegmentTemplate.CreateKeySegment(navigationPropertyType, targetNavigationSource, "relatedId"); } } segments.Add(linkTemplate); ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(httpMethod, context.Prefix, context.Model, template, context.Options?.RouteOptions); // processed return(true); }