graphql-client
graphql-client copied to clipboard
Invalid Cast Exception when using Subscriptions
I have been running into System.InvalidCastException when trying to set up a GraphQL subscription. I have tracked the error occuring to line 318 of GraphQLHttpWebSocket in the repo:
var certs = ((HttpClientHandler)Options.HttpMessageHandler).ClientCertificates;
I am using .NET Maui and am not entirely sure if I am doing something wrong or if it is a MAUI or repo issue.
We've seen limitations at this point before (in earlier cases with WASM, see https://github.com/graphql-dotnet/graphql-client#blazor-webassembly-limitations).
Could you try to find out what type Options.HttpMessageHandler actually is in your app (because it obviously isn't of type HttpClientHandler or derived from it)?
Ah, I definitely see my issue here now. My MessageHandler is a custom class in order to get around SSL when using the Android emulator for testing. It was the best solution I found for MAUI testing when connecting to localhost: https://github.com/dotnet/maui/discussions/8131 https://gist.github.com/Eilon/49e3c5216abfa3eba81e453d45cba2d4
The code I'm using looks like this:
public GraphQLHttpClient Client { get; set; }
var options = new GraphQLHttpClientOptions { HttpMessageHandler = GetInsecureHandler(), EndPoint = new Uri(endpoint) };
Client = new GraphQLHttpClient(options, new NewtonsoftJsonSerializer());
public HttpMessageHandler GetInsecureHandler()
{
var handler = new CustomAndroidMessageHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
if (cert.Issuer.Equals("CN=localhost")) return true;
return errors == System.Net.Security.SslPolicyErrors.None;
};
return handler;
}
internal sealed class CustomAndroidMessageHandler : Xamarin.Android.Net.AndroidMessageHandler
{
protected override Javax.Net.Ssl.IHostnameVerifier GetSSLHostnameVerifier(Javax.Net.Ssl.HttpsURLConnection connection)
=> new CustomHostnameVerifier();
private sealed class CustomHostnameVerifier : Java.Lang.Object, Javax.Net.Ssl.IHostnameVerifier
{
public bool Verify(string? hostname, Javax.Net.Ssl.ISSLSession? session)
{
return
Javax.Net.Ssl.HttpsURLConnection.DefaultHostnameVerifier.Verify(hostname, session)
|| hostname == "10.0.2.2" && session.PeerPrincipal?.Name == "CN=localhost";
}
}
}
I am honestly not very familiar with SSL connections and backend development in general, could this solution be modified to be compatible? Or would the better option just be to somehow get a valid SSL certificate set up on the Android emulator?
Thank you so much for your patience and help!