/// <inheritdoc/> protected override void SetResponses(OpenApiOperation operation) { if (EdmOperation.IsAction() && EdmOperation.ReturnType == null) { operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse()); } else { // function should have a return type. OpenApiResponse response = new OpenApiResponse { Description = "Success", Content = new Dictionary <string, OpenApiMediaType> { { Constants.ApplicationJsonMediaType, new OpenApiMediaType { Schema = Context.CreateEdmTypeSchema(EdmOperation.ReturnType) } } } }; operation.Responses.Add(Constants.StatusCode200, response); } // both action & function has the default response. operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse()); base.SetResponses(operation); }
/// <inheritdoc/> protected override void SetParameters(OpenApiOperation operation) { base.SetParameters(operation); if (EdmOperation.IsFunction()) { IEdmFunction function = (IEdmFunction)EdmOperation; if (OperationSegment.ParameterMappings != null) { IList <OpenApiParameter> parameters = Context.CreateParameters(function, OperationSegment.ParameterMappings); foreach (var parameter in parameters) { AppendParameter(operation, parameter); } } else { IDictionary <string, string> mappings = ParameterMappings[OperationSegment]; IList <OpenApiParameter> parameters = Context.CreateParameters(function, mappings); if (operation.Parameters == null) { operation.Parameters = parameters; } else { foreach (var parameter in parameters) { AppendParameter(operation, parameter); } } } } }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name; // OperationId if (Context.Settings.EnableOperationId) { string operationId = String.Join(".", Path.Segments.Where(s => !(s is ODataKeySegment)).Select(s => s.Identifier)); if (EdmOperation.IsAction()) { operation.OperationId = operationId; } else { ODataOperationSegment operationSegment = Path.LastSegment as ODataOperationSegment; string pathItemName = operationSegment.GetPathItemName(Context.Settings, new HashSet <string>()); if (Context.Model.IsOperationOverload(operationSegment.Operation)) { string hash = pathItemName.GetHashSHA256(); operation.OperationId = operationId + "-" + hash.Substring(0, 4); } else { operation.OperationId = operationId; } } } base.SetBasicInfo(operation); }
private static void AddProcedures(this EdmModel model, IEnumerable <ProcedureConfiguration> configurations, EdmEntityContainer container, Dictionary <Type, IEdmType> edmTypeMap, IDictionary <string, EdmNavigationSource> edmNavigationSourceMap) { Contract.Assert(model != null, "Model can't be null"); ValidateActionOverload(configurations.OfType <ActionConfiguration>()); foreach (ProcedureConfiguration procedure in configurations) { IEdmTypeReference returnReference = GetEdmTypeReference( edmTypeMap, procedure.ReturnType, procedure.ReturnType != null && EdmLibHelpers.IsNullable(procedure.ReturnType.ClrType)); IEdmExpression expression = GetEdmEntitySetExpression(edmNavigationSourceMap, procedure); IEdmPathExpression pathExpression = procedure.EntitySetPath != null ? new EdmPathExpression(procedure.EntitySetPath) : null; EdmOperationImport operationImport; switch (procedure.Kind) { case ProcedureKind.Action: operationImport = CreateActionImport(procedure, container, returnReference, expression, pathExpression); break; case ProcedureKind.Function: operationImport = CreateFunctionImport((FunctionConfiguration)procedure, container, returnReference, expression, pathExpression); break; case ProcedureKind.ServiceOperation: Contract.Assert(false, "ServiceOperations are not supported."); goto default; default: Contract.Assert(false, "Unsupported ProcedureKind"); return; } EdmOperation operation = (EdmOperation)operationImport.Operation; if (procedure.IsBindable && procedure.Title != null & procedure.Title != procedure.Name) { model.SetOperationTitleAnnotation(operation, new OperationTitleAnnotation(procedure.Title)); } AddProcedureParameters(operation, procedure, edmTypeMap); if (procedure.IsBindable) { AddProcedureLinkBuilder(model, operation, procedure); ValidateProcedureEntitySetPath(model, operationImport, procedure); } else { container.AddElement(operationImport); } model.AddElement(operation); } }
private static void BuildOperationParameters(EdmOperation operation, MethodInfo method, IEdmModel model) { foreach (var parameter in method.GetParameters()) { var parameterTypeReference = parameter.ParameterType.GetTypeReference(model); var operationParam = new EdmOperationParameter(operation, parameter.Name, parameterTypeReference); operation.AddParameter(operationParam); } }
private void BuildOperations(EdmModel model, string modelNamespace) { foreach (var operationMethodInfo in operationInfos) { // With this method, if return type is nullable type,it will get underlying type var returnType = TypeHelper.GetUnderlyingTypeOrSelf(operationMethodInfo.Method.ReturnType); var returnTypeReference = returnType.GetReturnTypeReference(model); var isBound = operationMethodInfo.IsBound; var bindingParameter = operationMethodInfo.Method.GetParameters().FirstOrDefault(); if (bindingParameter == null && isBound) { // Ignore the method which is marked as bounded but no parameters continue; } var namespaceName = GetNamespaceName(operationMethodInfo, modelNamespace); EdmOperation operation = null; EdmPathExpression path = null; if (isBound) { // Unbound actions or functions should not have EntitySetPath attribute path = BuildBoundOperationReturnTypePathExpression(returnTypeReference, bindingParameter); } if (operationMethodInfo.HasSideEffects) { operation = new EdmAction(namespaceName, operationMethodInfo.Name, returnTypeReference, isBound, path); } else { operation = new EdmFunction(namespaceName, operationMethodInfo.Name, returnTypeReference, isBound, path, operationMethodInfo.IsComposable); } BuildOperationParameters(operation, operationMethodInfo.Method, model); model.AddElement(operation); if (!isBound) { // entitySetReferenceExpression refer to an entity set containing entities returned // by this function/action import. var entitySetExpression = BuildEntitySetExpression( model, operationMethodInfo.EntitySet, returnTypeReference); var entityContainer = model.EnsureEntityContainer(targetType); if (operationMethodInfo.HasSideEffects) { entityContainer.AddActionImport(operation.Name, (EdmAction)operation, entitySetExpression); } else { entityContainer.AddFunctionImport( operation.Name, (EdmFunction)operation, entitySetExpression); } } } }
private static void AddProcedureParameters(EdmOperation operation, ProcedureConfiguration procedure, Dictionary <Type, IEdmType> edmTypeMap) { foreach (ParameterConfiguration parameter in procedure.Parameters) { bool isParameterOptional = parameter.OptionalParameter; IEdmTypeReference parameterTypeReference = GetEdmTypeReference(edmTypeMap, parameter.TypeConfiguration, nullable: isParameterOptional); IEdmOperationParameter operationParameter = new EdmOperationParameter(operation, parameter.Name, parameterTypeReference); operation.AddParameter(operationParameter); } }
private static void AddOperationParameters(EdmOperation operation, OperationConfiguration operationConfiguration, Dictionary <Type, IEdmType> edmTypeMap) { foreach (ParameterConfiguration parameter in operationConfiguration.Parameters) { bool isParameterNullable = parameter.Nullable; IEdmTypeReference parameterTypeReference = GetEdmTypeReference(edmTypeMap, parameter.TypeConfiguration, nullable: isParameterNullable); IEdmOperationParameter operationParameter = new EdmOperationParameter(operation, parameter.Name, parameterTypeReference); operation.AddParameter(operationParameter); } }
private static void AddProcedureParameters(EdmOperation operation, ProcedureConfiguration procedure, Dictionary <Type, IEdmType> edmTypeMap) { foreach (ParameterConfiguration parameter in procedure.Parameters) { // TODO: http://aspnetwebstack.codeplex.com/workitem/417 bool isParameterOptional = EdmLibHelpers.IsNullable(parameter.TypeConfiguration.ClrType); IEdmTypeReference parameterTypeReference = GetEdmTypeReference(edmTypeMap, parameter.TypeConfiguration, nullable: isParameterOptional); IEdmOperationParameter operationParameter = new EdmOperationParameter(operation, parameter.Name, parameterTypeReference); operation.AddParameter(operationParameter); } }
private static void BuildOperationParameters(EdmOperation operation, MethodInfo method, IEdmModel model) { foreach (ParameterInfo parameter in method.GetParameters()) { var parameterTypeReference = parameter.ParameterType.GetTypeReference(model); var operationParam = new EdmOperationParameter( operation, parameter.Name, parameterTypeReference); operation.AddParameter(operationParam); } }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name; // OperationId if (Context.Settings.EnableOperationId) { // When the key segment is available, // its EntityType name will be used // in the operationId to avoid potential // duplicates in entity vs entityset functions/actions List <string> identifiers = new(); foreach (ODataSegment segment in Path.Segments) { if (segment is not ODataKeySegment) { identifiers.Add(segment.Identifier); } else { identifiers.Add(segment.EntityType.Name); } } string operationId = string.Join(".", identifiers); if (EdmOperation.IsAction()) { operation.OperationId = operationId; } else { ODataOperationSegment operationSegment = Path.LastSegment as ODataOperationSegment; string pathItemName = operationSegment.GetPathItemName(Context.Settings, new HashSet <string>()); if (Context.Model.IsOperationOverload(operationSegment.Operation)) { string hash = pathItemName.GetHashSHA256(); operation.OperationId = operationId + "-" + hash.Substring(0, 4); } else { operation.OperationId = operationId; } } } base.SetBasicInfo(operation); }
public void ResolveFunctionsOverloadsByParameterNameShouldNotThrowIfMultipleResolve() { var function = new EdmFunction("d.s", "function1", EdmCoreModel.Instance.GetSingle(false)); function.AddParameter("param1", EdmCoreModel.Instance.GetString(true)); var function1 = new EdmFunction("d.s", "function1", EdmCoreModel.Instance.GetSingle(false)); function1.AddParameter("param1", EdmCoreModel.Instance.GetString(true)); var functions = new EdmOperation[] { function, function1 }; var selectedFunctions = functions.FilterOperationsByParameterNames(new string[] { "param1" }, false); selectedFunctions.Count().Should().Be(2); }
/// <inheritdoc/> protected override void SetTags(OpenApiOperation operation) { string value = EdmOperation.IsAction() ? "Actions" : "Functions"; OpenApiTag tag = new OpenApiTag { Name = NavigationSource.Name + "." + value, }; tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("container")); operation.Tags.Add(tag); Context.AppendTag(tag); base.SetTags(operation); }
public void ResolveFunctionsOverloadsByParameterNameShouldResolve() { var function = new EdmFunction("d.s", "function1", EdmCoreModel.Instance.GetSingle(false)); var functionOverload1 = new EdmFunction("d.s", "function1", EdmCoreModel.Instance.GetSingle(false)); functionOverload1.AddParameter("foo", EdmCoreModel.Instance.GetSingle(false)); var functionOverload2 = new EdmFunction("d.s", "function1", EdmCoreModel.Instance.GetSingle(false)); functionOverload2.AddParameter("foo", EdmCoreModel.Instance.GetSingle(false)); functionOverload2.AddParameter("foo2", EdmCoreModel.Instance.GetSingle(false)); var functions = new EdmOperation[] { function, functionOverload1, functionOverload2 }; var resolvedFunction = functions.FilterOperationsByParameterNames(new string[] { "foo" }, false); resolvedFunction.First().Should().BeSameAs(functionOverload1); }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name; // Description operation.Description = Context.Model.GetDescriptionAnnotation(EdmOperation); // OperationId if (Context.Settings.EnableOperationId) { // When the key segment is available, // its EntityType name will be used // in the operationId to avoid potential // duplicates in entity vs entityset functions/actions List <string> identifiers = new(); foreach (ODataSegment segment in Path.Segments) { if (segment is not ODataKeySegment) { identifiers.Add(segment.Identifier); } else { identifiers.Add(segment.EntityType.Name); } } string operationId = string.Join(".", identifiers); if (EdmOperation.IsAction()) { operation.OperationId = operationId; } else { if (Path.LastSegment is ODataOperationSegment operationSegment && Context.Model.IsOperationOverload(operationSegment.Operation)) { operation.OperationId = operationId + "-" + Path.LastSegment.GetPathHash(Context.Settings); } else { operation.OperationId = operationId; } }
/// <inheritdoc/> protected override void SetParameters(OpenApiOperation operation) { base.SetParameters(operation); if (EdmOperation.IsFunction()) { IEdmFunction function = (IEdmFunction)EdmOperation; IList <OpenApiParameter> parameters = Context.CreateParameters(function); if (operation.Parameters == null) { operation.Parameters = parameters; } else { foreach (var parameter in parameters) { operation.Parameters.Add(parameter); } } } }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name; // OperationId if (Context.Settings.EnableOperationId) { StringBuilder operationId = new StringBuilder(NavigationSource.Name); if (HasTypeCast) { ODataTypeCastSegment typeCast = Path.Segments.FirstOrDefault(s => s is ODataTypeCastSegment) as ODataTypeCastSegment; operationId.Append("."); operationId.Append(typeCast.EntityType.Name); } else { operationId.Append("."); operationId.Append(NavigationSource.EntityType().Name); } operationId.Append("."); operationId.Append(EdmOperation.Name); if (EdmOperation.IsAction()) { operation.OperationId = operationId.ToString(); } else { ODataOperationSegment operationSegment = Path.LastSegment as ODataOperationSegment; string pathItemName = operationSegment.GetPathItemName(Context.Settings); string md5 = pathItemName.GetHashMd5(); operation.OperationId = operationId.Append(".").Append(md5.Substring(8)).ToString(); } } base.SetBasicInfo(operation); }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name; // OperationId if (Context.Settings.EnableOperationId) { string operationId = String.Join(".", Path.Segments.Where(s => !(s is ODataKeySegment)).Select(s => s.Name)); if (EdmOperation.IsAction()) { operation.OperationId = operationId; } else { ODataOperationSegment operationSegment = Path.LastSegment as ODataOperationSegment; string pathItemName = operationSegment.GetPathItemName(Context.Settings); string md5 = pathItemName.GetHashMd5(); operation.OperationId = operationId + "." + md5.Substring(0, 4); } } base.SetBasicInfo(operation); }
private void CreateAndFillStockContentsForOperations(IEdmModel edmModel, EdmModel stockModel) { foreach (var edmOperation in edmModel.SchemaElements.OfType <IEdmOperation>()) { EdmOperation stockOperation = null; var edmAction = edmOperation as IEdmAction; if (edmAction != null) { stockOperation = new EdmAction( edmAction.Namespace, edmAction.Name, edmAction.ReturnType == null ? edmOperation.ReturnType : ConvertToStockTypeReference(edmOperation.ReturnType, stockModel), edmAction.IsBound, edmAction.EntitySetPath); } else { IEdmFunction edmFunction = edmOperation as IEdmFunction; ExceptionUtilities.CheckObjectNotNull(edmFunction, "edmFunction"); stockOperation = new EdmFunction( edmFunction.Namespace, edmFunction.Name, edmFunction.ReturnType == null ? edmFunction.ReturnType : ConvertToStockTypeReference(edmFunction.ReturnType, stockModel), edmFunction.IsBound, edmFunction.EntitySetPath, edmFunction.IsComposable); } foreach (var edmParameter in edmOperation.Parameters) { stockOperation.AddParameter(new EdmOperationParameter(edmOperation, edmParameter.Name, ConvertToStockTypeReference(edmParameter.Type, stockModel))); } stockModel.AddElement(stockOperation); } }
private static void AddOperationParameters(EdmOperation operation, OperationConfiguration operationConfiguration, Dictionary <Type, IEdmType> edmTypeMap) { foreach (ParameterConfiguration parameter in operationConfiguration.Parameters) { bool isParameterNullable = parameter.Nullable; IEdmTypeReference parameterTypeReference = GetEdmTypeReference(edmTypeMap, parameter.TypeConfiguration, nullable: isParameterNullable); if (parameter.IsOptional) { if (parameter.DefaultValue != null) { operation.AddOptionalParameter(parameter.Name, parameterTypeReference, parameter.DefaultValue); } else { operation.AddOptionalParameter(parameter.Name, parameterTypeReference); } } else { IEdmOperationParameter operationParameter = new EdmOperationParameter(operation, parameter.Name, parameterTypeReference); operation.AddParameter(operationParameter); } } }
/// <summary> /// Add vocabulary annotations to a model target. /// </summary> /// <param name="model"><see cref="EdmModel"/> to add annotations to</param> /// <param name="target"><see cref="EdmOperation"/> to annotate</param> /// <param name="operationConfiguration"><see cref="OperationConfiguration"/> containing the collection of <see cref="VocabularyTermConfiguration"/> annotation configurations</param> public static void SetVocabularyConfigurationAnnotations(this EdmModel model, EdmOperation target, OperationConfiguration operationConfiguration) => model.SetVocabularyConfigurationAnnotations(target as IEdmVocabularyAnnotatable, operationConfiguration?.VocabularyTermConfigurations.Values);
/// <summary> /// Builds a complex instance from the given payloadElements to represent a parameters payload. /// </summary> /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param> /// <param name="model">EdmModel instance.</param> /// <param name="functionImportName">Name of the function import to add to the model.</param> /// <returns></returns> private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName) { EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault(); EdmOperation operation = (EdmOperation)operationImport.Operation; var parameterPayload = new ComplexInstance(null, false); for (int idx = 0; idx < payloadElements.Length; idx++) { ODataPayloadElement p = payloadElements[idx]; string parameterName = "p" + idx; PropertyInstance parameter; IEdmTypeReference entityModelType = p.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType; switch (p.ElementType) { case ODataPayloadElementType.PrimitiveValue: object clrValue = ((PrimitiveValue)p).ClrValue; PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue); primitiveValue.CopyAnnotation <PrimitiveValue, EntityModelTypeAnnotation>(p); parameter = new PrimitiveProperty(parameterName, primitiveValue); operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType())); break; case ODataPayloadElementType.ComplexInstance: parameter = new ComplexProperty(parameterName, (ComplexInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.PrimitiveMultiValue: PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p; if (primitiveMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.ComplexMultiValue: ComplexMultiValue complexMultiValue = (ComplexMultiValue)p; if (complexMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntityInstance: parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntitySetInstance: parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p); operation.AddParameter(parameterName, entityModelType); break; default: throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType); } parameterPayload.Add(parameter); } parameterPayload.ExpectedFunctionImport(operationImport); return(parameterPayload); }
private static void AddOperations(this EdmModel model, IEnumerable <OperationConfiguration> configurations, EdmEntityContainer container, Dictionary <Type, IEdmType> edmTypeMap, IDictionary <string, EdmNavigationSource> edmNavigationSourceMap) { Contract.Assert(model != null, "Model can't be null"); ValidateActionOverload(configurations.OfType <ActionConfiguration>()); foreach (OperationConfiguration operationConfiguration in configurations) { IEdmTypeReference returnReference = GetEdmTypeReference(edmTypeMap, operationConfiguration.ReturnType, operationConfiguration.ReturnType != null && operationConfiguration.OptionalReturn); IEdmExpression expression = GetEdmEntitySetExpression(edmNavigationSourceMap, operationConfiguration); IEdmPathExpression pathExpression = operationConfiguration.EntitySetPath != null ? new EdmPathExpression(operationConfiguration.EntitySetPath) : null; EdmOperationImport operationImport; switch (operationConfiguration.Kind) { case OperationKind.Action: operationImport = CreateActionImport(operationConfiguration, container, returnReference, expression, pathExpression); break; case OperationKind.Function: operationImport = CreateFunctionImport((FunctionConfiguration)operationConfiguration, container, returnReference, expression, pathExpression); break; case OperationKind.ServiceOperation: Contract.Assert(false, "ServiceOperations are not supported."); goto default; default: Contract.Assert(false, "Unsupported OperationKind"); return; } EdmOperation operation = (EdmOperation)operationImport.Operation; if (operationConfiguration.IsBindable && operationConfiguration.Title != null && operationConfiguration.Title != operationConfiguration.Name) { model.SetOperationTitleAnnotation(operation, new OperationTitleAnnotation(operationConfiguration.Title)); } if (operationConfiguration.IsBindable && operationConfiguration.NavigationSource != null && edmNavigationSourceMap.ContainsKey(operationConfiguration.NavigationSource.Name)) { model.SetAnnotationValue(operation, new ReturnedEntitySetAnnotation(operationConfiguration.NavigationSource.Name)); } AddOperationParameters(operation, operationConfiguration, edmTypeMap); if (operationConfiguration.IsBindable) { AddOperationLinkBuilder(model, operation, operationConfiguration); ValidateOperationEntitySetPath(model, operationImport, operationConfiguration); } else { container.AddElement(operationImport); } model.AddElement(operation); } }