Blazor WASM GraphQL Client

Introduction

I have been working with GraphQL for a while now and really like the value proposition. I was asked a question on this blog if I had looked at Blazor WASM yet. I had not had an opportunity to work with Blazor since December of 2019, so I decide to tackle using GraphQL with Blazor WASM.

Requirements

If you are not familiar with GraphQL, how to query GraphQL, or how GraphQL servers return data, this blog post is not a good starting point.

Please learn these topics and return if still interested.

Source Code

https://github.com/Oceanware/BlazorWASMGraphQLClient

GraphQL Client Space

There are GraphQL clients for Angular, React, .NET, .Net Core, etc.  However, I was not able to get GraphQL.Client to work with Blazor WASM. There was some conflict with HttpClient TCP/IC communications.  Blazor has its own prescribed technique for using HttpClient that you can read about here and need to follow.

GraphQLService

When creating this service, I wanted it to behave like other GraphQL clients and always return predictable results to the caller.

The Root class provides the shape for the predictable return value from the GraphQLService SendRequest method. GraphQL servers return the requested payload in the data property.  If GraphQL has any errors, they will be returned in the errors property.

The Exception property will contain any exceptions caught by the service.

public class Root<T> where T : class, new() {

    [JsonProperty("data")]
    public T Data { get; set; }

    [JsonProperty("errors")]
    public IList<GraphQLError> Errors { get; set; }

    [JsonIgnore]
    public Exception Exception { get; set; }

    [JsonIgnore]
    public Boolean HasData { get { return this.Data != null; } }

    [JsonIgnore]
    public Boolean HasErrors { get { return this.Errors != null; } }

    [JsonIgnore]
    public Boolean HasException { get { return this.Exception != null; } }

    public Root() {
    }
}

To call the service, craft your query or mutation, and invoke SendRequest.  The generic parameter represents the shape of your data that will be returned by the GraphQL server. In the below example, the Data class represents the root element of the GraphQL results; in this case, a List of Country objects will be returned.

Hint: Use graphiql, GraphQL Playground, or PostMan to craft your queries; these tools really help, especially with variables.

Your data shape will always mimic the GraphQL query.

var queryObject = new {
    query = @"query Country($alpha3Code: String!) {
        Country(alpha3Code: $alpha3Code) {
            name
            capital
            flag {
                svgFile
            }
        }
    }",
    variables = $@"{{ ""alpha3Code"": ""{this.SelectedCountryAlpha3Code}"" }}"
};

Root<Data> result = await this.GraphQLService.SendRequest<Data>(GraphQLEndPoint, queryObject);

if (result.HasData) {
    this.Country = result.Data.Country.Single();
} else if (result.HasErrors) {
    this.GraphQLErrors = result.Errors;
} else if (result.HasException) {
    this.ExceptionMessage = result.Exception.Message;
}
await InvokeAsync(StateHasChanged);

The Root class Has[*] methods keep the caller’s code clean.

GraphQLService Limitations

I have not implemented the authorization code yet, since I was calling a public API.  It is very easy to add the required headers to the request.

Close

GraphQL offers incredible flexibility for client applications.  The ability to change queries without having to change the server is an invaluable benefit.

I hope you find this demo useful in your Blazor projects.

Just a grain of sand on the world’s beaches.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s