Handlebars-Net / Handlebars.Net.Helpers

Handlebars.Net helpers in the categories: 'Boolean', 'Constants', 'Enumerable', 'Environment', 'Math', 'Regex', 'String', 'DateTime' and 'Url'.
MIT License
38 stars 14 forks source link

UndefinedBindingResult Throws exception when using #String.Equal #94

Closed Vfleitao closed 1 month ago

Vfleitao commented 1 month ago

Heya

I have a small template that contains lines like this

<a href="/" class="plain text-black {{#String.Equal viewData.page "home" }}active{{/String.Equal}}">Home</a>

When I use the ThrowOnUnresolvedBindingExpression = false HandleBarsConfiguration, the String.Equal still throws an exception with

Object of type 'HandlebarsDotNet.UndefinedBindingResult' cannot be converted to type 'System.String'.

if the viewData.page is an UndefinedBindingResult.

Just doing this works as expected

<a href="/" class="plain text-black {{viewData.page}}">Home</a>

Is this an expected behaviour or am I missing some configuration on the Helpers?

Vfleitao commented 1 month ago

Looking a bit deeper into the ArgumentsParser, I wonder if something like this would not make sense so that if the argument ends up being a an UndefinedBindingResult we return the default value or throw an exception?

public static List<object?> Parse(IHandlebars context, ParameterInfo[] parameters, Arguments arguments)
{
    var result = new List<object?>();
    for (int i = 0; i < parameters.Length; i++)
    {
        if (parameters[i].IsParam())
        {
            result.Add(arguments.Skip(i).ToArray());
        }
        else if (i < arguments.Length)
        {
            result.Add(arguments[i]);
        }
    }

    return result.Select(argument => Parse(context, argument)).ToList();
}

public static object? Parse(IHandlebars context, object? argument, bool convertObjectArrayToStringList = false)
{
    if (argument is UndefinedBindingResult valueAsUndefinedBindingResult)
    {
        if (TryParseUndefinedBindingResult(valueAsUndefinedBindingResult, out var parsedAsObjectList) && convertObjectArrayToStringList)
        {
            return parsedAsObjectList.Cast<string?>().ToList();
        }

        if(context.Configuration.ThrowOnUnresolvedBindingExpression)
        {
            throw new HandlebarsRuntimeException($"The value '{valueAsUndefinedBindingResult.Value}' cannot be converted to a valid type.");
        }

        return valueAsUndefinedBindingResult.Value;
    }

    return argument;
}
StefH commented 1 month ago

I guess the viewData is null or does not have a property named page? What is rendered for this? <a href="/" class="plain text-black {{viewData.page}}">Home</a>

StefH commented 1 month ago

https://github.com/Handlebars-Net/Handlebars.Net.Helpers/pull/95

Vfleitao commented 1 month ago

I guess the viewData is null or does not have a property named page? What is rendered for this? <a href="/" class="plain text-black {{viewData.page}}">Home</a>

In my case, the viewData is literally just set with the null value. It renders <a href="/" class="plain text-black viewData.page">Home</a> since my UnresolvedBindingFormatter is set to "{0}"

Vfleitao commented 1 month ago

95

now this is a quick fix. Thank you very much @StefH