I recently have been creating a lot of ASP.NET Web APIs with VS Code to serve as backends for my mobile apps.
Of course I want to debug both the Web API and the mobile app at the same time during development.
This should be an easy task. Unfortunately on iOS, there are some hoops to jump through.
In this post I'm going to show you how to do it. Both the steps I tried, and the reasons why. Read through it and you won't have to suffer like I did to debug ASP.NET Web APIs from Xamarin.iOS apps.
(Check out how to do it on Android here.)
To recreate the situation, open up VS Code in a blank folder and enter the following in the terminal:
dotnet new webapi -n NoSSL.API
That will create a basic template for an ASP.NET Web API. With a project name of
From the same terminal window, type:
That will start everything up. And notice it'll be running on
Go into your favorite web browser and type:
Continue on if it warms about security. After it loads, you'll see a JSON string returned.
Invoking From a Xamarin App
The code used to invoke the Web API will be the following:
HttpClient that uses the
GetStringAsync function. Nothing too fancy.
The First Attempt
First, I tried running the code above with everything as is. I got an error with the message:
The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk.
OK. Sounds like iOS doesn't trust the certificate that Kestrel is using. The
dotnet tooling comes with an extension that installs certificates. So let's try that.
Run the following in the terminal:
dotnet dev-certs https -t
This will install a development certificate. And browsers will stop complaining about untrusted certificates.
But run the iOS app again and nothing changes, the same error appears.
The Second Attempt
Knowing that I could not get iOS to trust the certificate, I decided to use the non-SSL version of the service.
The service starts at both
https://localhost:5001. So why not try the non-SSL version?
I added the following key to the
NSAllowsLocalNetworking key tells iOS to not enforce its SSL rules on localhost.
Run it again. Get the same error.
The Third Attempt
At this point I noticed the output window in VS Code was showing the request was trying to connect through SSL yet.
Only one thing left to do now. Change the
launchSettings.json file to only launch on HTTP.
Upon opening it, I found a line that said:
I got rid of the
https://localhost:5001 part of it. Started up the Web API again. Then tried the mobile app again.
The Moral of the Story
I got stuck between attempt 2 and attempt 3 for quite a while. It didn't make sense that the Kestrel web server would try to route that non-SSL request to SSL. (Still doesn't make sense, let me know if you know why.)
But the moral here is to enable
NSAllowsLocalNetworking and make sure you're only running a non-SSL version of the Web API. Then you'll be good to go.
Oh, and should you ship and app with
NSAllowsLocalNetworking allowed? No. Use
PListBuddy in a custom build script to swap it out during your DevOps production build pipeline. See the Azure DevOps or Visual Studio App Center docs for more info.