byme8 / ZeroQL

C# GraphQL client with Linq-like syntax
MIT License
278 stars 13 forks source link

Unable to use Hot Chocolate sorting #16

Closed DaveRMaltby closed 2 years ago

DaveRMaltby commented 2 years ago

Not sure if this is the same issue that I mentioned in #11 as being obscured, but it seems like it. In the first case, it was calling a mutation with a complex parameter and the same is in this case. All both of these issues could very well be syntax errors on my part, but I can't figure it out after much review of your documentation.

So, I'm simplified this problem down as much as possible and created a repo that reproduces the issue. I've made a GraphQL test server that just exposes a simple Author class and has a query to get a list of authors. I added Hot Chocolate's sorting attribute on it. Anyhow, I cannot get the ZeroQL client to compile when trying to provide a sorting criteria.

var sortResponse = await qlClient.Query(static query => query.Authors(new AuthorSortInput[] { new AuthorSortInput { Name = SortEnumType.Asc } }, o => o.Name));

REF: https://github.com/Servant-Software-LLC/ZeroQL_Can_Not_Sort_Hot_Chocolate/blob/master/Integration.Tests/UnitTest1.cs#L29

If I don't provide a sorting argument, then it compiles and runs in the Test Explorer just fine:

var noSortResponse = await qlClient.Query(static query => query.Authors(null, o => o.Name));

If you clone the repo at https://github.com/Servant-Software-LLC/ZeroQL_Can_Not_Sort_Hot_Chocolate, it has the GraphQL server, generator and XUnit test which doesn't compile in the latest commit.

byme8 commented 2 years ago

To pass complex objects, you have to use the input variables. It is essential to do it like that because there is no direct mapping from complex object to graphql literal.

var variables = new { Sorting = new AuthorSortInput[] { new AuthorSortInput { Name = SortEnumType.Asc } } };
var sortResponse = await qlClient.Query(variables, static (input, query) => query.Authors(input.Sorting, o => o.Name));
byme8 commented 2 years ago

Hmm... Now when I thought about it again I remembered that in GraphQL you can pass objects with hard-coded values. So, it is a potential place for future improvements.

DaveRMaltby commented 2 years ago

Great. Thank you for the quick response.

DaveRMaltby commented 2 years ago

I've tried your approach and am getting...

 Integration.Tests.UnitTest1.Test1
   Source: UnitTest1.cs line 11
   Duration: 7 min

  Message: 
Assert.Null() Failure
Expected: (null)
Actual:   GraphQueryError[] [GraphQueryError { Extensions = [...], Message = "Variable `sorting` is required.", Path = null }]

  Stack Trace: 
UnitTest1.Test1() line 31
--- End of stack trace from previous location ---

I'm not clear why it isn't working.. I've pushed the changes in https://github.com/Servant-Software-LLC/ZeroQL_Can_Not_Sort_Hot_Chocolate/commit/40616051a70a9603ac1a6701b12eee1cfb7e474b

Does this unit test run for you? Thanks.

byme8 commented 2 years ago

If you are using variables in query, then inside the HotChocolateClientHandler, you need to handle them too...

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken)
{
    var requestJson = await httpRequest.Content!.ReadAsStringAsync(cancellationToken);
    var request = JsonConvert.DeserializeObject<GraphQLRequest>(requestJson);
    var jobject = request.Variables as JObject;
    var variables = new Dictionary<string, object>(); // convert jobject to Dictionary<string, object>
    var executionResult = await executor.ExecuteAsync(request.Query, variables, cancellationToken);
    var json = await executionResult.ToJsonAsync();

    return new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ReadOnlyMemoryContent(Encoding.UTF8.GetBytes(json))
    };
}
DaveRMaltby commented 2 years ago

@byme8, Wonderful! I now have a working solution whose unit tests pass. Converting the variable json strings values were a blocker for a long while, but I found that Hot Chocolate provides an IHttpRequestParser service that I could make use of to get the proper variables dictionary instance.

Anyhow, I've push the latest commit https://github.com/Servant-Software-LLC/ZeroQL_Can_Not_Sort_Hot_Chocolate/commit/ef366f7b709ad8bd435d3853ddf0ed97d56bb073 to the repo in case anyone else comes across this and needs an example of integration tests that don't need an HTTP endpoint stood up in order for them to execute against their GraphQL server.

Thanks again, David