in src/DotNetWorker.Core/Context/Features/DefaultFunctionInputBindingFeature.cs [28:109]
public async ValueTask<FunctionInputBindingResult> BindFunctionInputAsync(FunctionContext context)
{
ObjectDisposedThrowHelper.ThrowIf(_disposed, this);
// Setting second parameter to CancellationToken.None to prevent a TaskCancelledException if the
// pipeline cancels the code before the function is invoked. This way the customer code will be invoked
// and they can handle the cancellation token.
await _semaphoreSlim.WaitAsync(WaitTimeInMilliSeconds, CancellationToken.None);
try
{
if (_inputBindingResult is not null)
{
// Return the cached value if BindFunctionInputAsync is called a second time during invocation.
return _inputBindingResult!;
}
IFunctionBindingsFeature functionBindings = context.GetBindings();
var inputConversionFeature = context.Features.Get<IInputConversionFeature>()
?? throw new InvalidOperationException("Input conversion feature is missing.");
var parameterValues = new object?[context.FunctionDefinition.Parameters.Length];
List<string>? errors = null;
for (int i = 0; i < parameterValues.Length; i++)
{
FunctionParameter parameter = context.FunctionDefinition.Parameters[i];
TryGetBindingSource(parameter.Name, functionBindings, out object? source);
ConversionResult bindingResult = await ConvertAsync(context, parameter, _converterContextFactory, inputConversionFeature, source);
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 '{parameter.Name}' to type '{parameter.Type.FullName}' from type '{source.GetType().FullName}'. Error:{bindingResult.Error}");
}
else if (bindingResult.Status == ConversionStatus.Unhandled)
{
// If still unhandled after going through all converters,check an explicit default value was provided for the parameter.
if (parameter.HasDefaultValue)
{
parameterValues[i] = parameter.DefaultValue;
}
else if (parameter.IsReferenceOrNullableType)
{
// If the parameter is a reference type or nullable type, set it to null.
parameterValues[i] = null;
}
else
{
// Non nullable value type with no default value.
// We could not find a value for this param. should throw.
errors ??= new List<string>();
errors.Add(
$"Could not populate the value for '{parameter.Name}' parameter. Consider adding a default value or making the parameter nullable.");
}
}
}
// 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)}");
}
_inputBindingResult = new FunctionInputBindingResult(parameterValues);
return _inputBindingResult;
}
finally
{
_semaphoreSlim.Release();
}
}