Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Invalid Cast Exception when using Subscriptions #586

Open
adlartuten opened this issue Aug 3, 2023 · 2 comments
Open

Invalid Cast Exception when using Subscriptions #586

adlartuten opened this issue Aug 3, 2023 · 2 comments

Comments

@adlartuten
Copy link

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.

@rose-a
Copy link
Collaborator

rose-a commented Aug 3, 2023

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)?

@adlartuten
Copy link
Author

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:
dotnet/maui#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!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants