Developing RESTful API with ASP.NET on Mac
Download .net sdk
https://dotnet.microsoft.com/en-us/download
The following was installed • .NET SDK 8.0.414 • .NET Runtime 8.0.20 • ASP.NET Core Runtime 8.0.20
This product collects usage data • More information and opt-out
Resources • .NET Documentation • SDK Documentation • Release Notes • Tutorials
msd@MSDs-Mac-mini-3 TestAPI % dotnet
Usage: dotnet [options] Usage: dotnet [path-to-application]
Options: -h|–help Display help. –info Display .NET information. –list-sdks Display the installed SDKs. –list-runtimes Display the installed runtimes.
path-to-application: The path to an application .dll file to execute. msd@MSDs-Mac-mini-3 TestAPI % dotnet restore
Welcome to .NET 8.0!
SDK Version: 8.0.414
Telemetry
The .NET tools collect usage data in order to help us improve your experience. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to ‘1’ or ‘true’ using your favorite shell.
Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry
Installed an ASP.NET Core HTTPS development certificate. To trust the certificate, run ‘dotnet dev-certs https –trust’ Learn about HTTPS: https://aka.ms/dotnet-https
Write your first app: https://aka.ms/dotnet-hello-world Find out what’s new: https://aka.ms/dotnet-whats-new Explore documentation: https://aka.ms/dotnet-docs Report issues and find source on GitHub: https://github.com/dotnet/core Use ‘dotnet –help’ to see available commands or visit: https://aka.ms/dotnet-cli ————————————————————————————– An issue was encountered verifying workloads. For more information, run “dotnet workload update”. Determining projects to restore…
msd@MSDs-Mac-mini-3 TestAPI % dotnet run Building… /Users/msd/Code/repos/dot-net/TestAPI/Models/Blood.cs(9,23): warning CS8618: Non-nullable property ‘Name_English’ must contain a non-null value when exiting constructor. Consider adding the ‘required’ modifier or declaring the property as nullable. [/Users/msd/Code/repos/dot-net/TestAPI/TestAPI.csproj] /Users/msd/Code/repos/dot-net/TestAPI/Models/Blood.cs(10,23): warning CS8618: Non-nullable property ‘Name_Myanmar’ must contain a non-null value when exiting constructor. Consider adding the ‘required’ modifier or declaring the property as nullable. [/Users/msd/Code/repos/dot-net/TestAPI/TestAPI.csproj] info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5122 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /Users/msd/Code/repos/dot-net/TestAPI
Open Swagger UI
http://localhost:5122/swagger/index.html
DB Migration
Connect with mysql database
host: localhost port: 3306 db: dotnetapi username: root password: {blank}
ASP.NET Core with MySQL Migration Guide
Task Completion Summary
✅ Task 1: Install MySQL Entity Framework Core Package
Command Executed:
dotnet add package Pomelo.EntityFrameworkCore.MySql
✅ Task 2: Update Connection String in appsettings.json
Changes Made:
- Updated connection string from SQL Server to MySQL format
- Configured MySQL database connection parameters
✅ Task 3: Update Program.cs to Use MySQL
Changes Made:
- Replaced
UseSqlServer()
withUseMySql()
- Updated Entity Framework configuration for MySQL compatibility
✅ Task 4: Create and Run Database Migrations
Commands Executed:
# Install Entity Framework Core tools globally
dotnet tool install --global dotnet-ef
# Add to PATH (macOS/Linux)
export PATH="$PATH:/Users/msd/.dotnet/tools"
# Install design package (required for migrations)
dotnet add package Microsoft.EntityFrameworkCore.Design
# Create initial migration
dotnet ef migrations add InitialCreate
# Apply migration to database
dotnet ef database update
Key Configuration Details
Connection String Format for MySQL
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=YourDatabase;User=root;Password=yourpassword;"
}
}
Program.cs MySQL Configuration
// Replace SQL Server configuration:
// options.UseSqlServer(connectionString);
// With MySQL configuration:
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
Required Packages
Core MySQL Package
- Pomelo.EntityFrameworkCore.MySql - MySQL provider for EF Core
Migration Tools
- Microsoft.EntityFrameworkCore.Design - Required for EF Core migrations
- dotnet-ef - Global tool for migration commands
Migration Files Created
After running dotnet ef migrations add InitialCreate
, the following files are generated:
Migrations/InitialCreate.cs
- Migration classMigrations/[Timestamp]_InitialCreate.cs
- Migration snapshotMigrations/YourDbContextModelSnapshot.cs
- Current model state
Common Issues and Solutions
1. dotnet-ef Command Not Found
# Solution: Add to PATH or reinstall
export PATH="$PATH:/Users/msd/.dotnet/tools"
dotnet tool install --global dotnet-ef
2. Missing Design Package
# Solution: Install design package
dotnet add package Microsoft.EntityFrameworkCore.Design
3. MySQL Version Compatibility
- Use
ServerVersion.AutoDetect()
for automatic version detection - Or specify exact version:
ServerVersion.Parse("8.0.0")
Verification Steps
- Check Migration Status:
dotnet ef migrations list
- Verify Database Creation:
- Check MySQL for new database and tables
- Verify table structure matches your models
- Test Application:
- Run the application
- Test API endpoints that use database operations
Next Steps
- Consider adding seed data in migration
- Set up database connection retry logic
- Configure connection pooling
- Implement database health checks
This migration successfully transitions your ASP.NET Core API from SQL Server to MySQL with proper Entity Framework Core configuration and database schema setup.
Here’s how to deploy an ASP.NET RESTful API on Ubuntu server using Apache instead of Nginx:
Prerequisites
- Ubuntu server (18.04+ recommended)
- Your published ASP.NET API project
- SSH access to the server
Step 1: Install .NET Runtime on Ubuntu
# Update package list
sudo apt update
# Install required dependencies
sudo apt install -y wget
# Add Microsoft package repository
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
# Install .NET runtime
sudo apt update
sudo apt install -y aspnetcore-runtime-6.0
# Or for newer versions:
sudo apt install -y aspnetcore-runtime-7.0
# or
sudo apt install -y aspnetcore-runtime-8.0
Step 2: Install Apache and Required Modules
# Install Apache
sudo apt install -y apache2
# Enable required Apache modules
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite
sudo a2enmod headers
# Restart Apache
sudo systemctl restart apache2
Step 3: Prepare Your Application
Publish your API locally:
dotnet publish -c Release -o ./publish
Ensure your appsettings.json includes:
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
}
}
}
}
Step 4: Transfer Files to Server
# Create directory
sudo mkdir -p /var/www/yourapi
# Copy files (from your local machine)
scp -r ./publish/* username@your-server-ip:/var/www/yourapi/
# Set permissions
sudo chown -R www-data:www-data /var/www/yourapi
sudo chmod -R 755 /var/www/yourapi
Step 5: Configure Apache Virtual Host
# Create virtual host file
sudo nano /etc/apache2/sites-available/yourapi.conf
Apache Virtual Host Configuration:
<VirtualHost *:80>
ServerName your-domain.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/yourapi
# Proxy API requests to Kestrel
ProxyPreserveHost On
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
# WebSocket support (if needed)
ProxyPass /ws/ ws://localhost:5000/ws/
ProxyPassReverse /ws/ ws://localhost:5000/ws/
# Error log
ErrorLog ${APACHE_LOG_DIR}/yourapi_error.log
CustomLog ${APACHE_LOG_DIR}/yourapi_access.log combined
# Additional headers for ASP.NET Core
Header set X-Content-Type-Options nosniff
Header set X-Frame-Options DENY
Header set X-XSS-Protection "1; mode=block"
</VirtualHost>
Alternative configuration for subdirectory or path-based routing:
<VirtualHost *:80>
ServerName your-domain.com
DocumentRoot /var/www/html
# Proxy only specific path to API
ProxyPreserveHost On
ProxyPass /api/ http://localhost:5000/
ProxyPassReverse /api/ http://localhost:5000/
# For SPA applications with API
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/api/
RewriteRule "^(.+)$" "/index.html" [PT]
</VirtualHost>
# Enable the site and disable default site
sudo a2ensite yourapi.conf
sudo a2dissite 000-default.conf
# Test Apache configuration
sudo apache2ctl configtest
# Restart Apache
sudo systemctl restart apache2
Step 6: Create Systemd Service
# Create service file
sudo nano /etc/systemd/system/yourapi.service
Service Configuration:
[Unit]
Description=ASP.NET Core Web API
After=network.target
[Service]
Type=exec
User=www-data
Group=www-data
WorkingDirectory=/var/www/yourapi
ExecStart=/usr/bin/dotnet /var/www/yourapi/yourapi.dll
Restart=always
RestartSec=10
KillSignal=SIGINT
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://localhost:5000
# Optional: Specify custom environment variables
Environment=ConnectionStrings__DefaultConnection="Your_Connection_String"
[Install]
WantedBy=multi-user.target
# Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable yourapi.service
sudo systemctl start yourapi.service
# Check status
sudo systemctl status yourapi.service
Step 7: Configure Firewall
# Enable firewall
sudo ufw enable
# Allow Apache (opens ports 80 and 443)
sudo ufw allow 'Apache Full'
# Allow SSH
sudo ufw allow ssh
# Check status
sudo ufw status
Step 8: SSL Certificate with Apache
# Install Certbot for Apache
sudo apt install -y certbot python3-certbot-apache
# Get SSL certificate
sudo certbot --apache -d your-domain.com -d www.your-domain.com
# Auto-renewal test
sudo certbot renew --dry-run
Step 9: Application Configuration Files
Create appsettings.Production.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
}
}
}
}
Step 10: Advanced Apache Configuration
For better performance and security:
<VirtualHost *:80>
ServerName your-domain.com
# Basic settings
DocumentRoot /var/www/yourapi
ProxyPreserveHost On
# Proxy configuration
ProxyPass / http://localhost:5000/ retry=0 timeout=30
ProxyPassReverse / http://localhost:5000/
# Timeout settings
ProxyTimeout 300
# Buffer settings
ProxyBadHeader Ignore
ProxyIOBufferSize 65536
# Security headers
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Compression
SetOutputFilter DEFLATE
LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/yourapi_error.log
CustomLog ${APACHE_LOG_DIR}/yourapi_access.log combined
</VirtualHost>
Step 11: Monitoring and Maintenance
Useful commands:
# Check application logs
sudo journalctl -u yourapi.service -f
# Check Apache logs
sudo tail -f /var/log/apache2/yourapi_error.log
# Restart services
sudo systemctl restart yourapi.service
sudo systemctl restart apache2
# Check service status
sudo systemctl status yourapi.service
sudo systemctl status apache2
Troubleshooting Common Issues
1. 502 Bad Gateway Error:
# Check if .NET app is running
sudo systemctl status yourapi.service
# Check if port 5000 is listening
sudo netstat -tulpn | grep :5000
# Check Apache error logs
sudo tail -f /var/log/apache2/error.log
2. Permission Issues:
sudo chown -R www-data:www-data /var/www/yourapi
sudo find /var/www/yourapi -type f -exec chmod 644 {} \;
sudo find /var/www/yourapi -type d -exec chmod 755 {} \;
3. SELinux Issues (if enabled):
# Install SELinux utilities
sudo apt install -y policycoreutils-python-utils
# Allow Apache to make network connections
sudo setsebool -P httpd_can_network_connect 1
4. Static Files Not Serving:
Ensure your Startup.cs
or Program.cs
has:
app.UseStaticFiles();
This Apache configuration provides a robust production environment for your ASP.NET RESTful API with proper reverse proxy setup, SSL support, and service management.