ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.22k stars 742 forks source link

Strawberry Shake's Optional<T> can be problematic #2859

Closed aradalvand closed 3 years ago

aradalvand commented 3 years ago

As far as I understand, the properties of classes that Strawberry Shake generates that represent for instance input objects, are wrapped by a generic struct called Optional<T> (the name can be very misleading, by the way) and what this does is it allows Strawberry Shake to distinguish between properties that are explicitly set to their default value, and fields that are not set at all.

However, this appears to cause problems in many situations, the most significant of which that I've encountered is that those generated classes then can't be used with Blazor's <EditForm> and <InputText>, etc. component, which is a common scenario, consider the following example:

Suppose we have an input object type called SignUpInput, defined in our SDL, like this:

input SignUpInput {
    email: String!
}

Strawberry Shake generates the following class from this input object type:

[System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
public partial class SignUpInput
{
    public Optional<string> Email { get; set; }
}

We also have a Blazor component, called SignUpForm.razor:

<EditForm Model="formModel">
    <InputText @bind-Value="formModel.Email" />
</EditForm>

@code {
    SignUpInput formModel = new SignUpInput();
}

But the part where it's binding the Email property to the InputText component (@bind-Value="formModel.Email") doesn't work, and causes the following errors:

Argument 2: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<StrawberryShake.Optional<string>>' to 'Microsoft.AspNetCore.Components.EventCallback'.
Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type.

This problem wouldn't occur if SignUpInput.Email's type was string, as opposed to Optional<string>. Is there anything I can do about this? Tell me if I'm missing something.

I think it's worth noting that this is not the only case where Optional<T> causes headaches, another case would be if you want to use FluentValidation for these input object types, which I can expand on more if you want to know. Can't there be a different mechanism for detecting set/unset properties?!

Thanks.

michaelstaib commented 3 years ago

We are working on this... with the next preview of strawberry shake this is fixed and you also will have an option to completely opt-put of Optional.

aradalvand commented 3 years ago

@michaelstaib Great to hear. Thanks! Looking forward to the first preview.

michaelstaib commented 3 years ago

The new preview now no longer requires optional.