Skip to content

Commit b974849

Browse files
committed
Improve error message when binding a command with arguments into normal button
1 parent f79fba4 commit b974849

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

src/Framework/Framework/Compilation/Javascript/ParametrizedCode.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,14 @@ public ParametrizedCode(string code, OperatorPrecedence precedence = default)
5050

5151
// TODO(exyi): add WriteTo(StringBuilder)
5252
/// <summary>
53-
/// Converts this to string and assigns all parameters using `parameterAssignment`. If there is any missing, exception is thrown.
53+
/// Converts this to string and assigns all parameters using `parameterAssignment`.
5454
/// </summary>
55+
/// <exception cref="MissingAssignmentException">Thrown when some parameter is not assigned and has no default value.</exception>
5556
public string ToString(Func<CodeSymbolicParameter, CodeParameterAssignment> parameterAssignment) => ToString(parameterAssignment, out var _);
57+
/// <summary>
58+
/// Converts this to string and assigns all parameters using `parameterAssignment`.
59+
/// </summary>
60+
/// <exception cref="MissingAssignmentException">Thrown when some parameter is not assigned and has no default value.</exception>
5661
public string ToString(Func<CodeSymbolicParameter, CodeParameterAssignment> parameterAssignment, out bool allIsDefault)
5762
{
5863
allIsDefault = true;
@@ -205,7 +210,7 @@ private CodeParameterAssignment[] FindAssignment(Func<CodeSymbolicParameter, Cod
205210
{
206211
pp[i] = parameters[i].DefaultAssignment;
207212
if (pp[i].Code == null)
208-
throw new InvalidOperationException($"Assignment of parameter '{parameters[i].Parameter}' was not found.");
213+
throw new MissingAssignmentException(parameters[i], this);
209214
}
210215
}
211216
else
@@ -229,6 +234,11 @@ public IEnumerable<CodeSymbolicParameter> EnumerateAllParameters()
229234
}
230235
}
231236

237+
public record MissingAssignmentException(CodeParameterInfo Parameter, ParametrizedCode FullCode): RecordExceptions.RecordException
238+
{
239+
public override string Message => $"Assignment of parameter '{Parameter.Parameter}' was not found.";
240+
}
241+
232242
/// <summary>
233243
/// Builder class with reasonably fast Add operation. Use Build method to convert it to immutable ParametrizedCode
234244
/// </summary>

src/Framework/Framework/Controls/KnockoutHelper.cs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using DotVVM.Framework.Compilation.Javascript.Ast;
1010
using DotVVM.Framework.Configuration;
1111
using DotVVM.Framework.Utils;
12+
using FastExpressionCompiler;
1213
using Newtonsoft.Json;
1314

1415
namespace DotVVM.Framework.Controls
@@ -263,18 +264,26 @@ options.KoContext is object ?
263264

264265
string SubstituteArguments(ParametrizedCode parametrizedCode)
265266
{
266-
return parametrizedCode.ToString(p =>
267-
p == JavascriptTranslator.CurrentElementParameter ? options.ElementAccessor :
268-
p == CommandBindingExpression.CurrentPathParameter ? CodeParameterAssignment.FromIdentifier(getContextPath(control)) :
269-
p == CommandBindingExpression.ControlUniqueIdParameter ? uniqueControlId?.GetParametrizedJsExpression(control) ?? CodeParameterAssignment.FromLiteral("") :
270-
p == JavascriptTranslator.KnockoutContextParameter ? knockoutContext :
271-
p == JavascriptTranslator.KnockoutViewModelParameter ? viewModel :
272-
p == CommandBindingExpression.OptionalKnockoutContextParameter ? optionalKnockoutContext :
273-
p == CommandBindingExpression.CommandArgumentsParameter ? options.CommandArgs ?? default :
274-
p == CommandBindingExpression.PostbackHandlersParameter ? CodeParameterAssignment.FromIdentifier(getHandlerScript()) :
275-
p == CommandBindingExpression.AbortSignalParameter ? abortSignal :
276-
default
277-
);
267+
try
268+
{
269+
return parametrizedCode.ToString(p =>
270+
p == JavascriptTranslator.CurrentElementParameter ? options.ElementAccessor :
271+
p == CommandBindingExpression.CurrentPathParameter ? CodeParameterAssignment.FromIdentifier(getContextPath(control)) :
272+
p == CommandBindingExpression.ControlUniqueIdParameter ? uniqueControlId?.GetParametrizedJsExpression(control) ?? CodeParameterAssignment.FromLiteral("") :
273+
p == JavascriptTranslator.KnockoutContextParameter ? knockoutContext :
274+
p == JavascriptTranslator.KnockoutViewModelParameter ? viewModel :
275+
p == CommandBindingExpression.OptionalKnockoutContextParameter ? optionalKnockoutContext :
276+
p == CommandBindingExpression.CommandArgumentsParameter ? options.CommandArgs ?? default :
277+
p == CommandBindingExpression.PostbackHandlersParameter ? CodeParameterAssignment.FromIdentifier(getHandlerScript()) :
278+
p == CommandBindingExpression.AbortSignalParameter ? abortSignal :
279+
default
280+
);
281+
}
282+
catch (ParametrizedCode.MissingAssignmentException e) when (e.Parameter.Parameter == CommandBindingExpression.CommandArgumentsParameter)
283+
{
284+
var returnType = expression.GetProperty<ResultTypeBindingProperty>(ErrorHandlingMode.ReturnNull)?.Type;
285+
throw new DotvvmControlException(control, $"The binding {expression} of type {returnType?.ToCode(stripNamespace: true) ?? "?"} requires arguments, but none were provided to the KnockoutHelper.GenerateClientPostback method.", innerException: e) { RelatedBinding = expression };
286+
}
278287
}
279288
}
280289

0 commit comments

Comments
 (0)