public void AddsStorageOutput_FromReturnType() { FunctionContext context = GetContextWithOutputBindings(nameof(JustStorage.MyQueueOutput), nameof(JustStorage.MyBlobOutput)); JustStorage result = new JustStorage() { MyQueueOutput = "queueStuff", MyBlobOutput = "blobStuff" }; context.GetBindings().InvocationResult = result; Assert.Empty(context.GetBindings().OutputBindingData); OutputBindingsMiddleware.AddOutputBindings(context); object returnedVal = context.GetBindings().InvocationResult; Assert.Null(returnedVal); Assert.Equal(2, context.GetBindings().OutputBindingData.Count); AssertDictionary(context.GetBindings().OutputBindingData, new Dictionary <string, object>() { { "MyQueueOutput", "queueStuff" }, { "MyBlobOutput", "blobStuff" } }); }
public void AddsStorageOutput_AndHttpReturn_FromReturnType() { FunctionContext context = GetContextWithOutputBindings(nameof(HttpAndStorage.MyQueueOutput), nameof(HttpAndStorage.MyBlobOutput), nameof(HttpAndStorage.MyHttpResponseData)); var emptyHttp = new TestHttpResponseData(context, HttpStatusCode.OK); HttpAndStorage result = new HttpAndStorage() { MyQueueOutput = "queueStuff", MyBlobOutput = "blobStuff", MyRandomValue = "ShouldNotAppear", MyHttpResponseData = emptyHttp }; context.GetBindings().InvocationResult = result; Assert.Equal(0, context.GetBindings().OutputBindingData.Count); OutputBindingsMiddleware.AddOutputBindings(context); object returnedVal = context.GetBindings().InvocationResult; Assert.Null(returnedVal); Assert.Equal(3, context.GetBindings().OutputBindingData.Count); AssertDictionary(context.GetBindings().OutputBindingData, new Dictionary <string, object>() { { "MyQueueOutput", "queueStuff" }, { "MyBlobOutput", "blobStuff" }, { "MyHttpResponseData", emptyHttp } }); }
public void SetsResult_NoBinding() { // No binding, should leave invocation result untouched FunctionContext context = GetContextWithOutputBindings(); string myData = "abc"; context.GetBindings().InvocationResult = myData; Assert.Empty(context.GetBindings().OutputBindingData); OutputBindingsMiddleware.AddOutputBindings(context); object returnedVal = context.GetBindings().InvocationResult; Assert.Equal("abc", returnedVal); Assert.Equal(0, context.GetBindings().OutputBindingData.Count); }
public void SetsOutput_FromMethodBinding() { // special binding to indicate the return value is set as an output binding FunctionContext context = GetContextWithOutputBindings("$return"); var emptyHttp = new TestHttpResponseData(context, HttpStatusCode.OK); context.GetBindings().InvocationResult = emptyHttp; Assert.Empty(context.GetBindings().OutputBindingData); OutputBindingsMiddleware.AddOutputBindings(context); object returnedVal = context.GetBindings().InvocationResult; Assert.Equal(returnedVal, emptyHttp); Assert.Empty(context.GetBindings().OutputBindingData); AssertDictionary(context.GetBindings().OutputBindingData, new Dictionary <string, object>()); }
public void AddsSingleOutput_FromMethodReturn() { // Special binding name indiciating return FunctionContext context = GetContextWithOutputBindings("$return"); string result = "MyStorageData"; context.GetBindings().InvocationResult = result; Assert.Empty(context.GetBindings().OutputBindingData); OutputBindingsMiddleware.AddOutputBindings(context); object returnedVal = context.GetBindings().InvocationResult; Assert.Equal(returnedVal, result); Assert.Empty(context.GetBindings().OutputBindingData); AssertDictionary(context.GetBindings().OutputBindingData, new Dictionary <string, object>()); }
internal static void AddOutputBindings(FunctionContext context) { var functionBindings = context.GetBindings(); object?result = functionBindings.InvocationResult; if (result != null) { functionBindings.OutputBindingsInfo.BindOutputInContext(context); } }
public object?[] BindFunctionInput(FunctionContext context) { if (_inputBound) { throw new InvalidOperationException("Duplicate binding call detected. " + $"Input parameters can only be bound to arguments once. Use the {nameof(InputArguments)} property to inspect values."); } _parameterValues = new object?[context.FunctionDefinition.Parameters.Length]; _inputBound = true; List <string>?errors = null; for (int i = 0; i < _parameterValues.Length; i++) { FunctionParameter param = context.FunctionDefinition.Parameters[i]; IFunctionBindingsFeature functionBindings = context.GetBindings(); // Check InputData first, then TriggerMetadata if (!functionBindings.InputData.TryGetValue(param.Name, out object?source)) { functionBindings.TriggerMetadata.TryGetValue(param.Name, out source); } var converterContext = new DefaultConverterContext(param, source, context); if (TryConvert(converterContext, out object?target)) { _parameterValues[i] = target; } else if (source is not null) { // Don't initialize this list unless we have to if (errors is null) { errors = new List <string>(); } errors.Add($"Cannot convert input parameter '{param.Name}' to type '{param.Type.FullName}' from type '{source.GetType().FullName}'."); } } // found errors if (errors is not null) { throw new FunctionInputConverterException($"Error converting {errors.Count} input parameters for Function '{context.FunctionDefinition.Name}': {string.Join(Environment.NewLine, errors)}"); } return(_parameterValues); }
public override void BindOutputInContext(FunctionContext context) { var functionBindings = context.GetBindings(); object?result = functionBindings.InvocationResult; if (result is not null) { AddResultToOutputBindings(functionBindings.OutputBindingData, result); // Because this context had property output bindings, // any invocation result was tranformed to output bindings, so the invocation result // would now be null. functionBindings.InvocationResult = null; } }
public async Task ExecuteAsync(FunctionContext context) { var invoker = _invokerCache.GetOrAdd(context.FunctionId, _ => _invokerFactory.Create(context.FunctionDefinition)); object?instance = invoker.CreateInstance(context.InstanceServices); var modelBindingFeature = context.Features.Get <IModelBindingFeature>(); object?[] inputArguments; if (modelBindingFeature is null) { Log.ModelBindingFeatureUnavailable(_logger, context); inputArguments = new object?[context.FunctionDefinition.Parameters.Length]; } else { inputArguments = modelBindingFeature.BindFunctionInput(context); } context.GetBindings().InvocationResult = await invoker.InvokeAsync(instance, inputArguments); }
public async ValueTask <object?[]> BindFunctionInputAsync(FunctionContext context) { if (_inputBound) { throw new InvalidOperationException("Duplicate binding call detected. " + $"Input parameters can only be bound to arguments once. Use the {nameof(InputArguments)} property to inspect values."); } _parameterValues = new object?[context.FunctionDefinition.Parameters.Length]; _inputBound = true; var inputConversionFeature = context.Features.Get <IInputConversionFeature>(); if (inputConversionFeature == null) { throw new InvalidOperationException("Input conversion feature is missing."); } List <string>?errors = null; for (int i = 0; i < _parameterValues.Length; i++) { FunctionParameter param = context.FunctionDefinition.Parameters[i]; IFunctionBindingsFeature functionBindings = context.GetBindings(); // Check InputData first, then TriggerMetadata if (!functionBindings.InputData.TryGetValue(param.Name, out object?source)) { functionBindings.TriggerMetadata.TryGetValue(param.Name, out source); } IReadOnlyDictionary <string, object> properties = ImmutableDictionary <string, object> .Empty; // Pass info about specific input converter type defined for this parameter, if present. if (param.Properties.TryGetValue(PropertyBagKeys.ConverterType, out var converterTypeAssemblyFullName)) { properties = new Dictionary <string, object>() { { PropertyBagKeys.ConverterType, converterTypeAssemblyFullName } }; } var converterContext = _converterContextFactory.Create(param.Type, source, context, properties); var bindingResult = await inputConversionFeature.ConvertAsync(converterContext); if (bindingResult.Status == ConversionStatus.Succeeded) { _parameterValues[i] = bindingResult.Value; } else if (bindingResult.Status == ConversionStatus.Failed && source is not null) { // Don't initialize this list unless we have to errors ??= new List <string>(); errors.Add( $"Cannot convert input parameter '{param.Name}' to type '{param.Type.FullName}' from type '{source.GetType().FullName}'. Error:{bindingResult.Error}"); } } // found errors if (errors is not null) { throw new FunctionInputConverterException( $"Error converting {errors.Count} input parameters for Function '{context.FunctionDefinition.Name}': {string.Join(Environment.NewLine, errors)}"); } return(_parameterValues); }