-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] SSL Connection refused when calling ASP.NET Core API endpoints from .NET MAUI App on Android #62966
Comments
Hi @TanvirArjel can you share more info about this setup? Is it all on Windows, with .NET MAUI targeting WinUI, and the ASP.NET Core server is running locally on the same Windows machine? |
@Eilon Here is the complete repo: https://github.com/TanvirArjel/CleanArchitecture
Yes! It's on Windows. Both servers are running on Windows local machine. |
BTW CORS shouldn't matter here because CORS applies only to browsers making calls to a remote server. In this case it's a .NET Core app making a call, so CORS isn't a factor one way or another. |
The first thing that I can think of is some issue related to HTTP vs. HTTPS. Is everything consistently using HTTPS in this scenario? |
I think so. It would be great if you run the repository on your machine and test. |
@TanvirArjel in that case it will likely take a while for me to get to this because it could involve a lot of investigation. Ideally we have minimal repro projects for this so there are fewer possible problems. |
@Eilon Okay! I shall provide a minimal repo soon. |
@Eilon Here is the minimal repo to reproduce the issue: https://github.com/TanvirArjel/MauiDemo. After running both API and MAUI Blazor app in debug mode, please click on the FetchData menu and see the debug output. This has been an irritating issue as this blocked my MAUI learning. Please let me know the update. Thanks in advance. |
@Eilon Could you please give me an update on this issue? Thank you. |
Hi @TanvirArjel I updated your project to be compatible with preview7/RC1 and it seems to work just fine for me. First I started the ASP.NET Core server so that the API would run on port 44393 (using HTTPS), then I deployed the WinUI project and ran it from the Start Menu (there's a bug right now in VS where you can't run the WinUI app directly), and it was able to do the HttpClient call to get the weather forecast. You can see the changes I made to the app here: TanvirArjel/MauiDemo#1 (I only changed things that changed in MAUI/Blazor/WinUI, I didn't change any app code.) |
@Eilon Great to hear that. I shall test the same project and get back to you. Thank you again. |
Do you know if you have the ASP.NET Core HTTPS developer certificate installed? Check out this post from Scott Hanselman: https://www.hanselman.com/blog/developing-locally-with-aspnet-core-under-https-ssl-and-selfsigned-certs You might need to run this command line tool: |
@Eilon I see, you have only tested with MAUI Blazor Windows UI and you did not check with MAUI Blazor Android app. For windows UI its working fine but for the MAUI Blazor Android it's not working and throwing the same error: |
@Eilon Please keep me updated after testing on your machine. This is a very crucial issue which blocked my MAUI development. |
Oh, I see. There's probably something that needs to be done in Android to make the cert trusted. The cert trust is done on the client, so when you run the command line tool, that makes Windows trust it. But Android is using a different cert store. |
OK I found the doc that discusses how to do this: https://docs.microsoft.com/xamarin/cross-platform/deploy-test/connect-to-local-web-services#bypass-the-certificate-security-check You can do one of these:
|
@Eilon Thank you so much. Could you please update the demo project with option-2. Thanks in advance. |
@Eilon Is there any documentation on how to use LetsEncrypt in MAUI? |
The docs I pointed to include code samples for how to do option 2. If that doesn't work, please let me know. I'm not sure of docs for LetsEncrypt, but it's a matter of using a LetsEncrypt cert in the ASP.NET Core app for SSL. Then the Android app I think would automatically trust it, because the CA for LetsEncrypt is I think already trusted in Android. (This is far outside my area of expertise, so I'm not 100% on this.) |
@Eilon Here is the test result:
I have tried. Only works for Windows Ui but does not work for mobile apps and shows the same error.
I have tried as follows: services.AddHttpClient("WeatherApi", c =>
{
c.BaseAddress = new Uri("https://localhost:44393/");
c.DefaultRequestHeaders.Add("Accept", "application/json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
}).ConfigurePrimaryHttpMessageHandler(x => new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
if (cert.Issuer.Equals("CN=localhost"))
{
return true;
}
return errors == System.Net.Security.SslPolicyErrors.None;
}
}); only works for Windows Ui but does not work for mobile apps and shows the following error: [chromium] [INFO:CONSOLE(1)] "Operation is not supported on this platform.
[chromium] at System.Net.Http.HttpClientHandler.set_ServerCertificateCustomValidationCallback(Func`5 value) in System.Net.Http.dll:token 0x6000252+0x0
[chromium] at MauiBlazorApp.Startup.<>c.<Configure>b__0_3(IServiceProvider x) in D:\MauiDemo\MauiBlazorApp\MauiBlazorApp\Startup.cs:line 37
[chromium] at Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.<>c__DisplayClass6_0.<ConfigurePrimaryHttpMessageHandler>b__1(HttpMessageHandlerBuilder b) in Microsoft.Extensions.Http.dll:token 0x60000e6+0xd
[chromium] at Microsoft.Extensions.Http.DefaultHttpClientFactory.<>c__DisplayClass17_0.<CreateHandlerEntry>g__Configure|0(HttpMessageHandlerBuilder b) in Microsoft.Extensions.Http.dll:token 0x6000110+0x15
[chromium] at Microsoft.Extensions.Http.LoggingHttpMessageHandlerBuilderFilter.<>c__DisplayClass3_0.<Configure>b__0(HttpMessageHandlerBuilder builder) in Microsoft.Extensions.Http.dll:token 0x600011b+0x0
[chromium] at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandlerEntry(String name) in Microsoft.Extensions.Http.dll:token 0x6000088+0xc0
[chromium] at Microsoft.Extensions.Http.DefaultHttpClientFactory.<>c__DisplayClass14_0.<.ctor>b__1() in Microsoft.Extensions.Http.dll:token 0x600010e+0x0
[chromium] at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ViaFactory(LazyThreadSafetyMode mode) in System.Private.CoreLib.dll:token 0x600125c+0x43
[chromium] at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) in System.Private.CoreLib.dll:token 0x600125d+0x22
[chromium] at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].CreateValue() in System.Private.CoreLib.dll:token 0x6001262+0x74
[chromium] at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].get_Value() in System.Private.CoreLib.dll:token 0x6001268+0xa
[chromium] at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandler(String name) in Microsoft.Extensions.Http.dll:token 0x6000087+0x20
[chromium] at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateClient(String name) in Microsoft.Extensions.Http.dll:token 0x6000086+0xe
[chromium] at MauiBlazorApp.Data.WeatherForecastService..ctor(IHttpClientFactory httpClientFactory) in D:\MauiDemo\MauiBlazorApp\MauiBlazorApp\Data\WeatherForecastService.cs:line 14
[chromium] at System.Reflection.RuntimeConstructorInfo.InternalInvoke(Object obj, Object[] parameters, Boolean wrapExceptions) in System.Private.CoreLib.dll:token 0x6004f5b+0x20
[chromium] at System.Reflection.RuntimeConstructorInfo.DoInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in System.Private.CoreLib.dll:token 0x6004f5a+0x86
[chromium] at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in System.Private.CoreLib.dll:token 0x6004f5c+0x0
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) in Microsoft.Extensions.DependencyInjection.dll:token 0x600008d+0x45
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite, RuntimeResolverContext argument) in Microsoft.Extensions.DependencyInjection.dll:token 0x60000a6+0x3f
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) in Microsoft.Extensions.DependencyInjection.dll:token 0x600008e+0x61
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, RuntimeResolverContext argument) in Microsoft.Extensions.DependencyInjection.dll:token 0x60000a5+0x4e
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) in Microsoft.Extensions.DependencyInjection.dll:token 0x600008b+0x26
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) in Microsoft.Extensions.DependencyInjection.dll:token 0x6000068+0x4b
[chromium] at System.Collections.Concurrent.ConcurrentDictionary`2[[System.Type, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Func`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope, Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAdd(Type key, Func`2 valueFactory) in System.Collections.Concurrent.dll:token 0x60000d2+0x4f
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) in Microsoft.Extensions.DependencyInjection.dll:token 0x6000066+0xd
[chromium] at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) in Microsoft.Extensions.DependencyInjection.dll:token 0x600010b+0x13
[chromium] at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass7_0.<CreateInitializer>g__Initialize|1(IServiceProvider serviceProvider, IComponent component) in Microsoft.AspNetCore.Components.dll:token 0x60003c5+0x18
[chromium] at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance) in Microsoft.AspNetCore.Components.dll:token 0x60000ac+0x2d
[chromium] at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType) in Microsoft.AspNetCore.Components.dll:token 0x60000ab+0x2b
[chromium] at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type componentType) in Microsoft.AspNetCore.Components.dll:token 0x6000268+0x0
[chromium] at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, Int32 parentComponentId) in Microsoft.AspNetCore.Components.dll:token 0x6000274+0x69
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex) in Microsoft.AspNetCore.Components.dll:token 0x60002a3+0x29
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex) in Microsoft.AspNetCore.Components.dll:token 0x60002a2+0x49
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex) in Microsoft.AspNetCore.Components.dll:token 0x600029e+0x74
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex) in Microsoft.AspNetCore.Components.dll:token 0x600029c+0x21c
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl) in Microsoft.AspNetCore.Components.dll:token 0x6000294+0x22b
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex) in Microsoft.AspNetCore.Components.dll:token 0x600029c+0x1d1
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl) in Microsoft.AspNetCore.Components.dll:token 0x6000294+0x22b
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex) in Microsoft.AspNetCore.Components.dll:token 0x600029c+0x197
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl) in Microsoft.AspNetCore.Components.dll:token 0x6000294+0x22b
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex) in Microsoft.AspNetCore.Components.dll:token 0x600029c+0x197
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl) in Microsoft.AspNetCore.Components.dll:token 0x6000294+0x22b
[chromium] at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree) in Microsoft.AspNetCore.Components.dll:token 0x6000292+0x25
[chromium] at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException) in Microsoft.AspNetCore.Components.dll:token 0x600030a+0x7e
[chromium] at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry) in Microsoft.AspNetCore.Components.dll:token 0x6000282+0x13
[chromium] at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue() in Microsoft.AspNetCore.Components.dll:token 0x600027e+0x6d", source: https://0.0.0.0/_framework/blazor.webview.js (1) |
@Eilon Hope you are doing fine. I am waiting to hear from you as my development struck here. |
For HTTP did you follow the Android instructions to allow HTTP per https://docs.microsoft.com/en-us/xamarin/cross-platform/deploy-test/connect-to-local-web-services#android-network-security-configuration ? |
@Eilon Now it's showing the following error: [INFO:CONSOLE(1)] "Response status code does not indicate success: 400 (Bad Request).
[chromium] at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() in System.Net.Http.dll:token 0x6000358+0x39
[chromium] at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[MauiBlazorApp.Data.WeatherForecast[], MauiBlazorApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext() in System.Net.Http.Json.dll:token 0x6000030+0x80
[chromium] at MauiBlazorApp.Data.WeatherForecastService.GetForecastAsync(DateTime startDate) in D:\MauiDemo\MauiBlazorApp\MauiBlazorApp\Data\WeatherForecastService.cs:line 19
[chromium] at MauiBlazorApp.Pages.FetchData.OnInitializedAsync() in D:\MauiDemo\MauiBlazorApp\MauiBlazorApp\Pages\FetchData.razor.cs:line 17
[chromium] at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() in Microsoft.AspNetCore.Components.dll:token 0x60000a3+0xbe
[chromium] at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState) in Microsoft.AspNetCore.Components.dll:token 0x6000285+0x65", source: https://0.0.0.0/_framework/blazor.webview.js (1) Although it is working fine for windows UI. I am done and dusted. Could you please run the demo app and make it workable: https://github.com/TanvirArjel/MauiDemo |
Well, the above error is simply an HTTP Bad Request(400) which either means you are calling the HTTP endpoint wrongly or something is messed up on your server. Not really a MAUI issue anymore at this point.
Concerning this, I'd like to point out that Let's Encrypt is a Certificate Authority that helps sign TLS (popularly called SSL) certificates so that your HTTPS connection can be trusted. That being said Let's Encrypt interfaces with the ASP.NET Core part of the app and not MAUI. For development scenarios, If however, you want to deploy your ASP.NET Core web app to production, Digital Ocean has a very nice blog on using Let's Encrypt with ASP.NET Core and Nginx as a reverse proxy. If you want to deploy directly to Kestrel, you can follow guides from this dev.to blog. I hope all of these helps you understand the whole thing better. I think you should close the issue as well, as the initial error wasn't a bug but a feature. Happy Coding! |
I know this is a simple HTTP 400 error but this is not the case here. The same code work MAUI Windows UI. It requires an extra bit of configuration for MAUI Android. If you think is plain and simple HTTP 400 then please get the code from here (https://github.com/TanvirArjel/MauiDemo) and run and find the issue, please. |
I don't have the VS2022 preview installed and I don't plan to install it soon, hence I can't really run MAUI apps yet. Since you're getting a 400, I'd advise you to debug it on the Server Side (Weather App), find out the content of the request that was sent from the Android app that led to a server-side error. That'll give more clarity to discovering the bug. Happy Coding! |
@TanvirArjel if you set up verbose logging on the ASP.NET Core app, can you see the request coming in from the Android emulator? As @AmSmart says, the fact that it's an HTTP 400 implies that the server is receiving the HTTP request, but thinks that the client sent a bad request. If you can see from the server what it thinks the request is or what's wrong with it, that could lead us to the answer. |
@Eilon I shall give try once .NET 6.0 RC-1 is released. .NET 6.0 preview 7 has so many issues. |
Sounds good, it should be out very soon! |
@Eilon, I have tested again after updating to .NET 6.0 RC 1. The same old error. I have enabled log level to I am requesting you run this (https://github.com/TanvirArjel/MauiDemo) minimal repo on your machine and identify the issue. Note: Request to the API app from every other source like POSTMAN, Fiddler, Windows App works perfectly fine but don't work from the MAUI android app. I am pretty sure this is related to the IIS Express and android emulator config issue. |
Tagging subscribers to this area: @dotnet/ncl Issue DetailsThe ASP.NET Core Web API app is up and running. Making requests to the API endpoints from Blazor Web Assembly works perfectly fine. Whenever making request from the .NET MAUI Blazor App it's throwing the following exception: [DOTNET] System.Net.Http.HttpRequestException: Connection refused (localhost:44363)
[DOTNET] ---> System.Net.Sockets.SocketException (111): Connection refused
[DOTNET] at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken
[DOTNET] cancellationToken) in System.Net.Sockets.dll:token 0x60002b9+0x1f
[DOTNET] at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token) in System.Net.Sockets.dll:token 0x60002b3+0x26
[DOTNET] at Syst
[DOTNET] em.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|277_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken) in System.Net.Sockets.dll:token 0x600029c+0xa4
[DOTNET] at System.Net.Http.HttpConnectionP
[DOTNET] ool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x6000700+0x1b4
[DOTNET] --- End of inner exception stack trace ---
[DOTNET] at System.Net.Http.HttpC
[DOTNET] onnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x6000700+0x298
[DOTNET] at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpReque
[DOTNET] stMessage request, Boolean async, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006ff+0x14d
[DOTNET] at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellati
[DOTNET] onToken) in System.Net.Http.dll:token 0x6000701+0x8f
[DOTNET] at System.Net.Http.HttpConnectionPool.SendUsingHttp11Async(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f1
[DOTNET] +0x15d
[DOTNET] at System.Net.Http.HttpConnectionPool.DetermineVersionAndSendAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f2+0x224
[DOTNET] at System.Net.Http.HttpConne
[DOTNET] ctionPool.SendAndProcessAltSvcAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f3+0x8e
[DOTNET] ssage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f4+0x99
[DOTNET] at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequ07-16 12:39:49.024 I/DOTNET (16085): at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationT
[DOTNET] oken) in System.Net.Http.dll:token 0x6000787+0x94
[DOTNET] at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in Microsoft.Extensions.Http.dll:token 0x60000c3+0xd7
[DOTNET] at MauiB
[DOTNET] lazor.Shared.Common.AuthorizationDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Common\AuthorizationDelegatingHandler.cs:line 43
[DOTNET] at Microsoft.E
[DOTNET] xtensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in Microsoft.Extensions.Http.dll:token 0x60000c8+0xef
[DOTNET] ge request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) in System.Net.Http.dll:token 0x600022f+0x1b7
[DOTNET] lazor.Shared.Common.AuthorizationDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Common\Authoriz07-16 12:39:49.025 I/DOTNET (16085): at MauiBlazor.Share
[DOTNET] d.Services.UserService.LoginAsync(LoginModel loginModel) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Services\UserService.cs:line 132
[DOTNET] at MauiBlazorApp.Components.IdentityComponents.LoginComponent.HandleValidSubmitAsync() in D:\GitHub
[DOTNET] \CleanArchitecture\src\ClientApps\MauiBlazorApp\MauiBlazorApp\Components\IdentityComponents\LoginComponent.razor.cs:line 51 There is no CORS issue because the API app is allowing any origin as follows: services.AddCors(options =>
{
options.AddPolicy(myAllowSpecificOrigins, builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed(_ => true);
});
}); Please help me how can I overcome the issue so that I can make requests to the ASP.NET Core REST endpoints from .NET MAUI Blazor app successfully. Thanks in advance.
|
Moved to dotnet/runtime. TL;DR: The documented method for calling untrusted local SSL endpoint from the Android emulator does not appear to work in .NET MAUI apps in the Android emulator. It works from a Xamarin Android app. It also works from Windows. |
Tagging subscribers to 'arch-android': @steveisok, @akoeplinger Issue DetailsThe ASP.NET Core Web API app is up and running. Making requests to the API endpoints from Blazor Web Assembly works perfectly fine. Whenever making request from the .NET MAUI Blazor App it's throwing the following exception: [DOTNET] System.Net.Http.HttpRequestException: Connection refused (localhost:44363)
[DOTNET] ---> System.Net.Sockets.SocketException (111): Connection refused
[DOTNET] at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken
[DOTNET] cancellationToken) in System.Net.Sockets.dll:token 0x60002b9+0x1f
[DOTNET] at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token) in System.Net.Sockets.dll:token 0x60002b3+0x26
[DOTNET] at Syst
[DOTNET] em.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|277_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken) in System.Net.Sockets.dll:token 0x600029c+0xa4
[DOTNET] at System.Net.Http.HttpConnectionP
[DOTNET] ool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x6000700+0x1b4
[DOTNET] --- End of inner exception stack trace ---
[DOTNET] at System.Net.Http.HttpC
[DOTNET] onnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x6000700+0x298
[DOTNET] at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpReque
[DOTNET] stMessage request, Boolean async, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006ff+0x14d
[DOTNET] at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellati
[DOTNET] onToken) in System.Net.Http.dll:token 0x6000701+0x8f
[DOTNET] at System.Net.Http.HttpConnectionPool.SendUsingHttp11Async(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f1
[DOTNET] +0x15d
[DOTNET] at System.Net.Http.HttpConnectionPool.DetermineVersionAndSendAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f2+0x224
[DOTNET] at System.Net.Http.HttpConne
[DOTNET] ctionPool.SendAndProcessAltSvcAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f3+0x8e
[DOTNET] ssage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) in System.Net.Http.dll:token 0x60006f4+0x99
[DOTNET] at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequ07-16 12:39:49.024 I/DOTNET (16085): at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationT
[DOTNET] oken) in System.Net.Http.dll:token 0x6000787+0x94
[DOTNET] at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in Microsoft.Extensions.Http.dll:token 0x60000c3+0xd7
[DOTNET] at MauiB
[DOTNET] lazor.Shared.Common.AuthorizationDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Common\AuthorizationDelegatingHandler.cs:line 43
[DOTNET] at Microsoft.E
[DOTNET] xtensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in Microsoft.Extensions.Http.dll:token 0x60000c8+0xef
[DOTNET] ge request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) in System.Net.Http.dll:token 0x600022f+0x1b7
[DOTNET] lazor.Shared.Common.AuthorizationDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Common\Authoriz07-16 12:39:49.025 I/DOTNET (16085): at MauiBlazor.Share
[DOTNET] d.Services.UserService.LoginAsync(LoginModel loginModel) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Services\UserService.cs:line 132
[DOTNET] at MauiBlazorApp.Components.IdentityComponents.LoginComponent.HandleValidSubmitAsync() in D:\GitHub
[DOTNET] \CleanArchitecture\src\ClientApps\MauiBlazorApp\MauiBlazorApp\Components\IdentityComponents\LoginComponent.razor.cs:line 51 There is no CORS issue because the API app is allowing any origin as follows: services.AddCors(options =>
{
options.AddPolicy(myAllowSpecificOrigins, builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed(_ => true);
});
}); Please help me how can I overcome the issue so that I can make requests to the ASP.NET Core REST endpoints from .NET MAUI Blazor app successfully. Thanks in advance.
|
Once it goes in, this should be fixed by dotnet/android#6665 |
…HTTP handlers (#6665) Context: dotnet/runtime#62966 The `AndroidClientHandler` and `AndroidMessageHandler` classes both have the `ServerCertificateCustomValidationCallback` property, which should be useful e.g. to allow running the Android app against a server with a self-signed SSL certificate during development, but the callback is never used. Unfortunatelly since .NET 6 the `System.Net.Http.SocketsHttpHandler` for Android doesn't support the use case anymore. That means that [the recommended way of connecting to local web server][0] won't work in MAUI. This PR introduces an implementation of `IX509TrustManger` which wraps the default Java X509 trust manager and calls the user's callback on top of the default validation. It turns out that `X509Chain` `Build` function doesn't work on Android, so I'm not calling it and I'm passing the chain to the callback directly. Additionally, we need a default proguard rule due to: https://github.com/xamarin/xamarin-android/blob/46002b49d8c0b7b1a17532a8e104b4d31afee7a6/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/GenerateProguardConfiguration.cs#L50-L57 -keep class xamarin.android.net.X509TrustManagerWithValidationCallback { *; <init>(...); } `Mono.Android.dll` is skipped during the `GenerateProguardConfiguration` linker step. It might be worth addressing this in a future PR. [0]: https://docs.microsoft.com/en-us/xamarin/cross-platform/deploy-test/connect-to-local-web-services
…HTTP handlers (dotnet#6665) Backport of: dotnet#6665 Context: dotnet/runtime#62966 The `AndroidClientHandler` and `AndroidMessageHandler` classes both have the `ServerCertificateCustomValidationCallback` property, which should be useful e.g. to allow running the Android app against a server with a self-signed SSL certificate during development, but the callback is never used. Unfortunatelly since .NET 6 the `System.Net.Http.SocketsHttpHandler` for Android doesn't support the use case anymore. That means that [the recommended way of connecting to local web server][0] won't work in MAUI. This PR introduces an implementation of `IX509TrustManger` which wraps the default Java X509 trust manager and calls the user's callback on top of the default validation. It turns out that `X509Chain` `Build` function doesn't work on Android, so I'm not calling it and I'm passing the chain to the callback directly. Additionally, we need a default proguard rule due to: https://github.com/xamarin/xamarin-android/blob/46002b49d8c0b7b1a17532a8e104b4d31afee7a6/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/GenerateProguardConfiguration.cs#L50-L57 -keep class xamarin.android.net.X509TrustManagerWithValidationCallback { *; <init>(...); } `Mono.Android.dll` is skipped during the `GenerateProguardConfiguration` linker step. It might be worth addressing this in a future PR. [0]: https://docs.microsoft.com/en-us/xamarin/cross-platform/deploy-test/connect-to-local-web-services
…HTTP handlers (#6972) * [Mono.Android] custom validation callback for server certificates in HTTP handlers (#6665) Backport of: #6665 Context: dotnet/runtime#62966 The `AndroidClientHandler` and `AndroidMessageHandler` classes both have the `ServerCertificateCustomValidationCallback` property, which should be useful e.g. to allow running the Android app against a server with a self-signed SSL certificate during development, but the callback is never used. Unfortunatelly since .NET 6 the `System.Net.Http.SocketsHttpHandler` for Android doesn't support the use case anymore. That means that [the recommended way of connecting to local web server][0] won't work in MAUI. This PR introduces an implementation of `IX509TrustManger` which wraps the default Java X509 trust manager and calls the user's callback on top of the default validation. It turns out that `X509Chain` `Build` function doesn't work on Android, so I'm not calling it and I'm passing the chain to the callback directly. Additionally, we need a default proguard rule due to: https://github.com/xamarin/xamarin-android/blob/46002b49d8c0b7b1a17532a8e104b4d31afee7a6/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/GenerateProguardConfiguration.cs#L50-L57 -keep class xamarin.android.net.X509TrustManagerWithValidationCallback { *; <init>(...); } `Mono.Android.dll` is skipped during the `GenerateProguardConfiguration` linker step. It might be worth addressing this in a future PR. [0]: https://docs.microsoft.com/en-us/xamarin/cross-platform/deploy-test/connect-to-local-web-services * Update .apkdesc (probably merge issue) Co-authored-by: Simon Rozsival <simon@rozsival.com>
A fix for this issue has been shipped with MAUI GA. |
@simonrozsival Just to clarify things for MAUI (Blazor) consumers like me: Doing ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
"CN=localhost".Equals(certificate?.Issuer, StringComparison.OrdinalIgnoreCase)
|| errors == System.Net.Security.SslPolicyErrors.None inside my
as is pointed out over at Bypass the certificate security check where it states: // This method must be in a class in a platform project, even if
// the HttpClient object is constructed in a shared project. , right? If so, why do the aforementioned docs then state I should do Moreover, since you stated in #68898 that
I'm totally confused how to set/overwrite the callback for debug purposes according to "current best practices". Up to your comment, I was using this SO answer's solution to circumvent the Android Emulator failing the certificate validation. Therefore, any help, i. e. clarification on proper |
@Eagle3386 hi! You shouldn't get any NRE exception. The I tried reproducing it locally in a new MAUI Blazor project and I didn't get any NRE. Can you send me a minimum reproducible example based on a new MAUI Blazor app project? |
@simonrozsival I use Microsoft.AspNetCore.SignalR.Client.HubConnection and the DangerousTrustProvider and DangerousAndroidMessageHandlerEmitter Class, which can be started normally on Android 11, but the same code cannot be started on Android 7.1.2. (Windows Machine is OK too.) private HubConnection Connect(string urls, CookieCollection authCookie)
{
return new HubConnectionBuilder().WithUrl(urls,
options =>
{
options.Cookies.Add(authCookie);
options.WebSocketConfiguration = conf =>
{
conf.RemoteCertificateValidationCallback = (message, cert, chain, errors) => { return true; };
};
})
.WithAutomaticReconnect()
.Build();
} <PropertyGroup>
<AndroidHttpClientHandlerType Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">DangerousAndroidMessageHandler, DangerousAndroidMessageHandler</AndroidHttpClientHandlerType>
</PropertyGroup> The ServerCertificateCustomValidationCallback seems to have no practical effect on Android System. By the way, the httpClient.PostAsync can be started on Android 7.1.2 and 11 if I use the DangerousTrustProvider and DangerousAndroidMessageHandlerEmitter Class. But the HubConnection cannot be started in Android 71.2, I got the Exception:
My Example code see here: https://github.com/danch15/MauiAndDevDemo/blob/main/MauiHubConnDemo.rar ================================================================================ |
@simonrozsival Alright, that's how I thought it ought to work. Thanks for the clarification! 👍🏻
Of course, but I'm having a really hard time producing such a POC: instead of the NRE, I'm constantly getting Can you help me yet again? |
Hi everyone, I created a little helper class that I started using that works on Android and Windows to connect to "local" SSL: https://gist.github.com/Eilon/49e3c5216abfa3eba81e453d45cba2d4 And here's how you can use it to call from an Android emulator to a Windows-hosted ASP.NET Core app: var devSslHelper = new DevHttpsConnectionHelper(sslPort: 7155);
var http = devSslHelper.HttpClient;
var responseText = await http.GetStringAsync(devSslHelper.DevServerRootUrl + "/someApi"); And to use SignalR client in .NET MAUI, here's how I use the helper: var devSslHelper = new DevHttpsConnectionHelper(sslPort: 7155);
var hubConnection = new HubConnectionBuilder()
#if ANDROID
.WithUrl(devSslHelper.DevServerRootUrl + "/myhub"
, configureHttpConnection: o =>
{
o.HttpMessageHandlerFactory = m => devSslHelper.GetPlatformMessageHandler();
}
)
#else
.WithUrl(devSslHelper.DevServerRootUrl + "/myhub")
#endif
.Build();
hubConnection.On<SomeThing>("SomeApi", ...);
await hubConnection.StartAsync(); It seems that to make it work on Android, there are two places in the handler that need to make the SSL checks go through:
|
@Eilon while that's an awesome helper for local debugging purposes, my scenario differs in that my service, i. e. And according to (Inline code preview seems to be prevented for cross-linked repos…) that error is only set if the internal |
@Eagle3386 ah alright that might very well be different. My helper is only for locally hosted sites (e.g. ASP.NET Core running on your Windows machine). |
I started a discussion topic on how to connect from Android emulators to a local ASP.NET Web API running on Windows: dotnet/maui#8131 Please check that out and let us know if you have any feedback on any of the solutions presented. |
@Eilon & @simonrozsival I still implemented Eilon's snippet nonetheless, but its Also, I did notice these debug output lines in VS (
Is my Furthermore, Lastly, please let me know if I should post this over at the mentioned discussion instead of this issue. I'd almost do anything just to get this chain error resolved… 😅 |
Just for the sake of completeness: using @Eilon's helper helped (pun intended! 😎) solve the NRE issue & also enabled me to discover that ASP.NET Core's dev cert was included in the chain - although "invisible" as anyone can see in my screenshot above (showing 3 instead of 4 certs). Everything else was/is discussed over at dotnet/maui/discussions/8131. |
The ASP.NET Core Web API app is up and running. Making requests to the API endpoints from Blazor Web Assembly works perfectly fine. Whenever making request from the .NET MAUI Blazor App it's throwing the following exception:
There is no CORS issue because the API app is allowing any origin as follows:
Please help me how can I overcome the issue so that I can make requests to the ASP.NET Core REST endpoints from .NET MAUI Blazor app successfully. Thanks in advance.
The text was updated successfully, but these errors were encountered: