Tutorials ASP.NET Core MVC Mastery

Deployment

On this page

Deployment — From Localhost to Production

"It works on my machine" is not a deployment strategy. Modern ASP.NET Core applications are designed to be cross-platform, meaning they can be deployed to Windows Server (IIS), Linux (Nginx/Apache), or containerized in Docker and orchestrated by Kubernetes. Choosing your hosting model correctly dictates your app's scalability and maintenance costs.

1. Hosting Models: In-Process vs. Out-of-Process

ASP.NET Core applications run on a web server called Kestrel. Kestrel is lightweight, insanely fast, and cross-platform. However, by itself, it lacks advanced features like process management or port sharing. Thus, we usually place a "Reverse Proxy" (like IIS or Nginx) in front of Kestrel.

In-Process (IIS Only)

The ASP.NET Core app is hosted directly inside the IIS worker process (w3wp.exe). There is only one web server running. This provides the highest performance for Windows deployments because it avoids the overhead of internal HTTP loopback routing.

Out-of-Process (Kestrel + Proxy)

IIS or Nginx acts as a Reverse Proxy. It listens on Port 80/443, handles SSL termination and security, and then forwards the raw request to Kestrel running as a separate background process on Port 5000. Required for Linux deployments.

2. REAL-WORLD PRODUCTION DEPLOYMENTS

Option A: Deploying to Windows IIS (Traditional Enterprise)

To run ASP.NET Core on a Windows Server, you must install the ASP.NET Core Hosting Bundle. This installs the .NET Runtime and the ASP.NET Core IIS Module.

# 1. Publish the application locally via CLI
dotnet publish --configuration Release --output ./publish_folder

# 2. Copy the contents of ./publish_folder to Windows Server (e.g., C:\inetpub\wwwroot\MyApp)
# 3. Create a Website in IIS Manager pointing to that path.
# 4. Set the Application Pool to "No Managed Code" (CRITICAL, because .NET Core manages itself).

Option B: Deploying to Linux (Nginx Reverse Proxy)

Linux does not have IIS. You must run the compiled DLL as a system service (using `systemd`) and use Nginx to route traffic strictly to that service.

# 1. Install .NET runtime on the Linux Server (Ubuntu example)
sudo apt-get install -y aspnetcore-runtime-8.0

# 2. Create a systemd service file (/etc/systemd/system/myapp.service)
[Unit]
Description=ASP.NET Core MVC Application

[Service]
WorkingDirectory=/var/www/myapp
# EXECUTING THE APP
ExecStart=/usr/bin/dotnet /var/www/myapp/MyApp.dll
Restart=always
RestartSec=10
Environment=ASPNETCORE_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target
# 3. Nginx Server Block (/etc/nginx/sites-available/default)
server {
    listen 80;
    server_name www.myapp.com;

    location / {
        # Forward external traffic exactly to Kestrel's internal port
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Option C: Azure App Services (Modern Platform-as-a-Service)

PaaS solutions completely abstract away the server configuration. You focus strictly on code.

  • Deploy directly from Visual Studio (Right-Click -> Publish).
  • Or configure a CI/CD pipeline (GitHub Actions / Azure DevOps) that automatically builds the .zip deployment package and pushes it to Azure upon every merge to the main branch.

3. Framework-Dependent vs Self-Contained

When you run dotnet publish, you have a crucial choice:

Deployment ModeRequirements on Target ServerFile SizeUse Case
Framework Dependent (Default)Must have .NET Runtime exactly installed.Very Small (~5MB)PaaS (Azure) or closely managed internal servers.
Self-ContainedNothing.Huge (~100MB+)Deploying to client environments where you cannot install software.

4. Best Practices

  • Never use "Development" environment in Production: Ensure the server's environment variable `ASPNETCORE_ENVIRONMENT` is strictly set to `Production`. Otherwise, your app will leak physical stack traces on error pages via `UseDeveloperExceptionPage`.
  • Protect appsettings.json: Never check production secrets (DB passwords, API keys) into GitHub (even inside appsettings.Production.json). Use Azure Key Vault, AWS Secrets Manager, or OS-level environment variables to inject them at runtime.

5. Interview Mastery

Q: "Why do we still use IIS or Nginx if Kestrel is a fully functional web server?"

Architect Answer: "While Kestrel's raw HTTP serving speed outperforms almost any other web server globally, it is intentionally designed to be highly focused. It historically lacked advanced edge-server features. Placing IIS or Nginx in front of Kestrel provides a robust 'Reverse Proxy' to handle SSL/TLS termination, port sharing (allowing Node.js and .NET apps to both respond on Port 443), static file caching, load balancing, and process management (restarting the Kestrel process if it crashes recursively)."

Questions on this lesson 0

Sign in to ask a question or upvote helpful answers.

No questions yet — be the first to ask!

ASP.NET Core MVC Mastery
Course syllabus
1. Core Framework
MODULE 1: INTRODUCTION & ENVIRONMENT SETUP
2. View Engine
MODULE 2: .NET CORE FUNDAMENTALS
MODULE 3: ASP.NET CORE BASICS
MODULE 4: MVC FUNDAMENTALS
MODULE 5: DATA PASSING TECHNIQUES
MODULE 6: ROUTING
MODULE 7: VIEWS & UI
MODULE 8: ACTION RESULTS
MODULE 9: HTML HELPERS
MODULE 10: TAG HELPERS
MODULE 11: MODEL BINDING
MODULE 12: VALIDATION
MODULE 13: STATE MANAGEMENT
MODULE 14: FILTERS & SECURITY
MODULE 15: ENTITY FRAMEWORK CORE (DEEP DIVE)
MODULE 16: DESIGN PATTERNS
MODULE 17: FILE HANDLING
MODULE 18: ADVANCED ASP.NET CORE
MODULE 19: PERFORMANCE & BEST PRACTICES
MODULE 20: RAZOR PAGES (BONUS)
MODULE 21: REAL-WORLD PROJECTS (🔥 MUST DO)
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details