Overview
This article walks through a real-world debugging scenario involving an ASP.NET Core API deployed on an Azure VM behind IIS. The issue initially appeared to be a connectivity or deployment problem but ultimately turned out to be related to IIS hostname bindings and SNI (Server Name Indication).
The goal was to validate API availability directly on the VM and isolate issues between Azure routing, IIS configuration, and application behavior.
Step 1: Initial Problem
The API endpoint:
https://foo-vm.example.com/service/ProcessRequest
was returning:
404 Not Found
This raised several possible concerns:
- Deployment failure
- IIS misconfiguration
- Routing issues
- Network or SSL problems
Step 2: SSL / Certificate Validation
While testing direct HTTPS calls, the following error appeared:
Could not establish trust relationship for the SSL/TLS secure channel
Action Taken
- Exported the server certificate (
.cer) - Installed it on the local machine (Trusted Root / Intermediate store)
- Alternatively, used curl with
-kto bypass SSL validation:
curl -k https://foo-vm.example.com
Outcome
- SSL issues were eliminated as a blocker
- Able to reach the server over HTTPS
Step 3: Direct API Testing with curl
Multiple endpoints were tested:
curl -k https://foo-vm.example.com/
curl -k https://foo-vm.example.com/service/health
curl -k https://foo-vm.example.com/api/health
Result
All returned:
404 Not Found (Microsoft-IIS/10.0)
Insight
- Requests were reaching IIS
- But no matching route/application was found
Step 4: Validate Application Deployment
A simple health check endpoint was introduced:
/service/health
Expected response:
Healthy
However, even this endpoint returned 404 when accessed via the VM hostname.
Step 5: IIS Investigation
Upon inspecting IIS:
- The API was not hosted under Default Web Site
- Instead, it was hosted under a separate site:
Foo.ApiSvc
Key Finding
Requests to:
https://foo-vm.example.com
were hitting:
Default Web Site ❌
—not the actual API site.
Step 6: Binding and SNI Discovery (Root Cause)
IIS bindings for the API site showed:
Host Name: foo.example.com
Port: 443
SNI: Enabled
Critical Insight
With SNI enabled, IIS routes requests based on the Host header.
So:
https://foo-vm.example.com → Default Web Site → 404
https://foo.example.com → Foo.ApiSvc → API
Step 7: Validate Using Host Header Override
Since DNS for foo.example.com was not directly usable from the VM, the Host header was manually injected:
curl -k https://foo-vm.example.com/service/health \
-H "Host: foo.example.com"
Result
Healthy
Conclusion
- API was functioning correctly
- IIS routing was working as designed
- Issue was purely hostname-based routing
Step 8: Azure Layer Insight
The /service/... route seen earlier was part of the Azure routing layer, not IIS.
Architecture:
Azure Front Door / Gateway
↓
foo.example.com
↓
Azure VM (IIS with SNI)
↓
ASP.NET Core API
Key Takeaway:
When bypassing Azure and hitting the VM directly, you must:
- Use the correct hostname
OR - Override the Host header
Application Pool Configuration Update
The IIS application pool was updated from .NET CLR v4.0 to No Managed Code to align with ASP.NET Core hosting best practices.
ASP.NET Core applications run on the CoreCLR in a separate process and do not depend on the IIS-managed CLR. While the previous setting did not prevent the application from running, updating it improves clarity and avoids confusion in future maintenance.
Step 9: Final Resolution
✅ Correct endpoint:
https://foo.example.com/service/health
✅ Or direct VM access with Host override:
curl -k https://foo-vm.example.com/service/health \
-H "Host: foo.example.com"
Key Learnings
1. IIS with SNI routes based on hostname, not IP
Incorrect hostname results in routing to the wrong site and returns 404.
2. Default Web Site is not always your application
Always verify IIS site bindings and application mapping.
3. Azure routing can mask backend behavior
The /service path was part of the Azure layer, not IIS configuration.
4. curl is a powerful debugging tool
-kbypasses SSL issues-vshows detailed request/response-Hallows header injection
5. ASP.NET Core hosting configuration
- App pool should be set to No Managed Code
- Runtime and hosting bundle were already functioning correctly
Final Summary
What initially appeared to be a deployment or API issue was ultimately traced to a hostname binding mismatch caused by IIS SNI configuration.
Once the correct hostname was used—or injected via the Host header—the API routed correctly and responded as expected.
Root cause: Incorrect Host header when bypassing Azure routing
Resolution: Use the correct hostname or override the Host header

Add to favorites
