diff --git a/src/DotNetWorker/Context/Features/DefaultModelBindingFeature.cs b/src/DotNetWorker/Context/Features/DefaultModelBindingFeature.cs index 41dae7a70..e703fdb1e 100644 --- a/src/DotNetWorker/Context/Features/DefaultModelBindingFeature.cs +++ b/src/DotNetWorker/Context/Features/DefaultModelBindingFeature.cs @@ -3,7 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Azure.Functions.Worker.Converters; +using Microsoft.Azure.Functions.Worker.Definition; +using Microsoft.Azure.Functions.Worker.Diagnostics.Exceptions; namespace Microsoft.Azure.Functions.Worker.Context.Features { @@ -31,6 +34,7 @@ public DefaultModelBindingFeature(IEnumerable converters) _parameterValues = new object?[context.FunctionDefinition.Parameters.Length]; _inputBound = true; + List? errors = null; for (int i = 0; i < _parameterValues.Length; i++) { FunctionParameter param = context.FunctionDefinition.Parameters[i]; @@ -48,8 +52,23 @@ public DefaultModelBindingFeature(IEnumerable converters) if (TryConvert(converterContext, out object? target)) { _parameterValues[i] = target; - continue; } + else if (source is not null) + { + // Don't initialize this list unless we have to + if (errors is null) + { + errors = new List(); + } + + 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(" ", errors)}"); } return _parameterValues; diff --git a/src/DotNetWorker/Diagnostics/Exceptions/FunctionInputConverterException.cs b/src/DotNetWorker/Diagnostics/Exceptions/FunctionInputConverterException.cs new file mode 100644 index 000000000..7ec2830b7 --- /dev/null +++ b/src/DotNetWorker/Diagnostics/Exceptions/FunctionInputConverterException.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Functions.Worker.Diagnostics.Exceptions +{ + internal class FunctionInputConverterException : FunctionWorkerException + { + internal FunctionInputConverterException(string message) : base(message) { } + + internal FunctionInputConverterException(string message, Exception innerException) : base(message, innerException) { } + } +} diff --git a/src/DotNetWorker/Diagnostics/Exceptions/FunctionWorkerException.cs b/src/DotNetWorker/Diagnostics/Exceptions/FunctionWorkerException.cs new file mode 100644 index 000000000..cecc42e6f --- /dev/null +++ b/src/DotNetWorker/Diagnostics/Exceptions/FunctionWorkerException.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Functions.Worker.Diagnostics +{ + /// + /// Internal exception that is surfaced to the user + /// + internal class FunctionWorkerException : Exception + { + internal FunctionWorkerException(string message) : base(message) { } + + internal FunctionWorkerException(string message, Exception innerException) : base(message, innerException) { } + } +}