Publishing and Hosting Apps
Last Updated: December 2023
Overview
SnapDevelop provides the following methods to publish your projects:
- Folder: Publishes to a local folder or a network shared folder.
- Web Server (IIS): Publishes to IIS server.
- Docker Container Registry: Publishes to any container repository that supports Docker images.
- Kubernetes Cluster: Publishes to a Kubernetes cluster.
ASP.NET Core Web API supports the following publish methods:
- Folder
- Web Server (IIS)
- Docker Container Registry
- Kubernetes Cluster
Console Apps, Class Libraries, ASP.NET Core Class Libraries, and xUnit Tests support the following publish methods:
- Folder
- Docker Container Registry
- Kubernetes Cluster
Publishing to a Folder
This section describes how to use SnapDevelop to publish C# projects to a local folder or a network shared folder.
Publishing a C# project
To publish a C# project to a folder:
In Solution Explorer, right-click the project and select Publish.
In the window that appears, select the Folder tab, then click Next.
Select a local or network folder as the publish destination, then click Next.
Configure the publish profile or select an existing configuration file.
Click the Edit publish profile icon to change the folder location and the following options and then click Save.
Settings Description Configuration Selects Debug or Release mode. Target Framework Selects the target framework. Deployment Mode Self-contained -- Publishes as an application that includes the .NET Core runtime and libraries along with your application and its dependencies. Users of the application can run it on machines that have no .NET Core runtime installed. Framework-dependent -- Publishes as an application that contains only your app and its dependencies. Users of the application have to separately install the .NET Core runtime. Target Runtime Selects the target runtime. Delete all existing files prior to publish Deletes all files in target folder before publishing. Use this connection string at runtime When it is checked, the publishing process will change the connection string for this database in the deployed Web.config file to the value you specify in the text box. Click Publish. The publishing process begins. You can view the publishing progress in the Output window.
Publishing to Docker or Kubernetes
SnapDevelop's support for Docker and Kubernetes simplifies development, testing, and deployment of containerized applications. Container Explorer and Kubernetes Explorer provided by SnapDevelop can manage your images and containers in a more efficient and productive way than using Docker and Kubernetes commands.
You can add two levels of container support to your project:
Container Support or Kubernetes Support -- Launches containers or Kubernetes support for a single project.
Container Orchestration Support -- Use Docker Compose or Kubernetes Compose to support multiple containers (e.g. solutions with multiple projects).
See Publishing to Docker for how to publish to Docker and Publishing to Kubernetes for how to publish to Kubernetes.
Publishing to IIS
This topic describes how to publish a project to IIS with SnapDevelop. It also includes troubleshooting information for some common errors.
Prerequisites
Both the server and client side requirements must be met before you publish a project to IIS.
Server Side Requirements
Windows Server 2022, 2019, 2016, or 2012
If your operating system is Windows 10, you can use Folder, rather than Web Server (IIS) publish method, to publish your project to a folder.
Make sure that your Windows is up-to-date and includes KB2999226, otherwise you might see this error when you launch a .NET Core application: The program can't start because api-ms-win-crt-runtime-1-1-0.dll is missing from your computer. Try reinstalling the program to fix this problem.
Web Deploy 3.6 or higher
Download link: https://www.iis.net/downloads/microsoft/web-deploy
When you install Web Deploy, select the Complete setup type to install.
Hosting Bundle
Download link: https://dotnet.microsoft.com/download/dotnet-core
Download and install the ASP.NET Core Hosting Bundle. Make sure that the version of ASP.NET Core Hosting Bundle is the same as the framework version your project targets. For example, if your project targets .NET Core 3.1, install the Hosting Bundle version 3.1.
Client Side Requirements
Windows 10
Make sure that your Windows is up-to-date and includes KB2999226, otherwise you might see this error when you launch a .NET Core application: The program can't start because api-ms-win-crt-runtime-1-1-0.dll is missing from your computer. Try reinstalling the program to fix this problem.
Web Deploy 3.6 or higher
The Web Deploy on the client side is automatically installed when you install SnapDevelop.
Configuring Server Side
Configuring IIS
To configure IIS
Launch the Server Manager.
Use the Add Roles and Features wizard from the Manage menu or the link in Server Manager. On the Server Roles page, select the Web Server (IIS) and Management Tools checkboxes.
On the Features page, select the .NET Framework 3.5 Features and .NET Framework 4.6 Features checkboxes.
Confirm the roles and features you selected, and click Install.
Configuring Web Deploy
You must enable the Web Management Service and Web Deployment Agent Service after installing Web Deploy.
To enable the services
Launch the desktop application Services.
Locate Web Management Service and Web Deployment Agent Service. Right click on each of them, and select Start.
Enabling Remote Connections
To enable remote connections
Launch the IIS Manager.
Select your computer in the Connections panel first, and then double click Management Service on the right.
In the Management Service, click Stop first, then select the Enable remote connections checkbox, and click Apply.
Adding IIS Users
You can add IIS users of IIS Manager type or Windows type.
Adding IIS Manager Users
To add IIS Manager users
In the IIS Manager, select your computer in the Connections panel, and then double click IIS Manager Users.
Click Add User to add a user.
In the IIS Manager, right click the Sites folder in the Connections panel, and select Add Website.
Specify the site name, physical path, and binding information.
Expand the Sites folder. Select the newly created website first, and then double-click IIS Manager Permissions.
Click Allow User first, and then select IIS Manager in the dialog box. Click Select to select a user you added.
Adding Windows Users
To add Windows users
In the IIS Manager, right click on the Sites folder in the Connections panel, and then select Add Website.
Specify the site name, physical path, and binding information.
Expand the Sites folder. Select the newly created website first, and then double click IIS Manager Permissions.
Click Allow User. In the dialog box that appears, select Windows, and click Select.
Specify the object type, location, and enter the user name to select a user.
In the IIS Manager, select your site first, and then click Basic Settings.
Select Connect as > Specific user > Set to set the user name and password.
Click Test Settings in step 7 to test the connection.
Publishing a Project to IIS
To publish a project to IIS:
In the Solution Explorer, right click on the project, and select Publish.
In the window that appears, select the Web Server (IIS) tab, and click Next.
Configure the IIS connection information or click the Import icon to import connection information from a profile, and then click Next.
Server: The domain name or IP address of the web server.
Site Name: The name of the web server site.
User Name: The user name to connect to the web server. Note that the user name can be either the IIS Web Deploy user name or the Windows user name.
Password: The password to connect to the web server.
Destination URL: The URL to view the publishing app.
Verify the settings.
If you want to change the Web server connection settings, you can click the Edit publish profile icon after the Server setting.
If you want to change the publish settings (as shown in the table below), you can click the Edit publish profile icon after the Configuration setting.
Settings Description Configuration Selects Debug or Release mode. Target Framework Selects the target framework. Deployment Mode Self-contained -- Publishes as an application that includes the .NET Core runtime and libraries along with your application and its dependencies. Users of the application can run it on machines that have no .NET Core runtime installed. Framework-dependent -- Publishes as an application that contains only your app and its dependencies. Users of the application have to separately install the .NET Core runtime. Target Runtime Selects the target runtime. Remove additional files at destination Deletes the extra files in target folder before publishing. Use this connection string at runtime When it is checked, the publishing process will change the connection string for this database in the deployed Web.config file to the value you specify in the text box. Click Publish. The publishing process begins. You can view the publishing progress in the Output window.
Troubleshooting
This topic describes the common errors that may occur when you publish projects to IIS.
The site does not exist
This error would occur if you did not select the Complete setup type of Web Deploy to install. The Web deployment agent service will be not enabled for the other setup types of Web Deploy.
Solution:
Uninstall your current version of Web Deploy and then install the Complete version.
The Web server is configured to not list the contents of this directory
Solution:
- Launch the IIS Manager, select your site in the Connections panel, and click Directory Browsing.
- Click Enable.
Error concerning IIS application pool permission
When such an error occurs, no data can be retrieved to your application and the error code 500 is returned. This is because the IIS application pool does not have permissions to log in to the database.
Solution 1:
Change the application pool identifier to a user who has access to the database.
Solution 2:
Change stdoutLogEnabled="false" to stdoutLogEnabled="true" in the web.config file that appears after the publish.
Error indicating that files are locked when an application is published to a remote site where an application has previously been published
Solution 1:
Shut down and relaunch the site after the publish.
Solution 2:
Select the checkbox Remove additional files at destination when you configure the publish profile.
Runtime error 500.30 when publishing .NET Core 2.2 application to IIS
Solution:
In the application configuration file, change "InProcess" to "OutOfProcess" in PropertyGroup, and add the ModelName property.
Error 502.5 might occur after you change the method. If this is the case, change the .NET path of Web API to an absolute path and restart your computer.
If Error 502.5 remains, you can check the event log. If the log indicates that the startup process fails, it might be caused by insufficient permissions. To fix the error, right click the website in the IIS Manager and select Advanced Settings. Choose Identity under Process Model, and select the Custom account to enter the local administrator's user name and password.
Publishing and Hosting an ASP.NET Core Application on Linux
In this topic, we create a Web API application, publish it using the File System method, and then host the app on Linux CentOS7 operating system following these steps:
In SnapDevelop, publish the Web API application with middleware configured to support reverse proxy
Copy over the Web API application from the local published folder to CentOS server
In CentOS, host Web API application on CentOS with reverse proxy (Apache) configured
For more information on how to set up Apache as a reverse proxy on CentOS 7, you can further read the Microsoft article: Host ASP.NET Core on Linux with Apache.
Prerequisites
- SnapDevelop 2022 R3
- Server running CentOS 7 with a standard sudo user account
- .NET Core Runtime is installed on CentOS 7 with the following instructions
Install .NET Core Runtime on CentOS 7
Before installing .NET Runtime, you need to register the Microsoft key, register the product repository, and install required dependencies. These only need to be done once per machine. Open a terminal and run the following commands:
# Install repository configuration
curl https://packages.microsoft.com/config/rhel/7/prod.repo > ./microsoft-prod.repo
sudo cp ./microsoft-prod.repo /etc/yum.repos.d/
# Install Microsoft's GPG public key
curl https://packages.microsoft.com/keys/microsoft.asc > ./microsoft.asc
sudo rpm --import ./microsoft.asc
Install the latest available updates for the product, then install the .NET Runtime.
In your terminal, run the following commands:
# Install the latest available updates for the product
sudo yum update
# Install the ASP.NET Core 3.1 runtime
sudo yum install aspnetcore-runtime-3.1
*The previous command will install the .NET Core Runtime Bundle, which includes the .NET Core runtime and the ASP.NET Core 3.1 runtime. To install just the .NET Core runtime, use the dotnet-runtime-3.1
package.
Please note that, the runtime version must be the same as the version of the .NET Framework that you want your project to target.
Publishing an ASP.NET Core Application to Server
Preparation for the Application
In SnapDevelop, select File from the menu bar and then choose New > Project. In the dialog box, select ASP.NET Core Web API. Then, fill in the project information to create a .NET Core project named WebAPI1 by clicking OK.
Some configurations for reverse proxy and Kestrel server need to be made before publishing.
Configuration for Forwarded Headers Middleware
Because requests are forwarded by reverse proxy, use the Forwarded Headers Middleware from the Microsoft.AspNetCore.HttpOverrides package. The middleware updates the Request.Scheme
, using the X-Forwarded-Proto
header, so that redirect URIs and other security policies work correctly.
Any component that depends on the scheme, such as authentication, link generation, redirects, and geolocation, must be placed after invoking the Forwarded Headers Middleware. As a general rule, Forwarded Headers Middleware should run before other middleware except for diagnostics and error handling middleware. This running order ensures that the middleware relying on forwarded headers information can consume the header values for processing.
Invoke the UseForwardedHeaders method in Startup.Configure
before calling UseAuthentication or similar authentication scheme middleware. Configure the middleware to forward the X-Forwarded-For
and X-Forwarded-Proto
headers:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseAuthentication();
If no ForwardedHeadersOptions are specified to the middleware, the default forwarded headers are None
.
Proxies running on loopback addresses (127.0.0.0/8, [::1]), including the standard localhost address (127.0.0.1), are trusted by default. For other trusted proxies or networks within the organization handling requests between the Internet and the web server, add them to the list of KnownProxies or KnownNetworks as options in ForwardedHeadersOptions. The following example adds a trusted proxy server at IP address 10.0.0.100 to the KnownProxies
of Forwarded Headers Middleware in Startup.ConfigureServices
:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
For more information, see Configure ASP.NET Core to work with proxy servers and load balancers.
Configuration for Secure (HTTPS) Local Connections
It is important for the application to make secure connections (HTTPS), configure the application to use a certificate for your development using one of the following approaches:
- Replace the default certificate from configuration (Recommended)
- KestrelServerOptions.ConfigureHttpsDefaults
The configuration for the application to listen to the URLs is in applicationUrl
property in the Properties/launchSettings.json file, for example, https://localhost:5001;http://localhost:5000
.
The app runs locally, so it is optional to configure the web server (Kestrel) with secure (HTTPS) local connections. You can remove https://localhost:5001
(if present) from the configuration.
Publishing the Application to a Local Folder
In Solution Explorer, right-click the project and choose Publish.
On the popup window, select Folder.
Click Next until the settings overview page display. Click the Edit publish profile icon of Publish Settings.
Set the publish settings according to your actual needs.
Click Save to continue.
Click Publish, then check the publication status in the Output window.
Copying the Application to the Server
Once the Web API application is published, copy the application from the published folder to the CentOS server using a tool that integrates into the organization's workflow (for example, SCP, SFTP). It's common to locate web applications under the var directory (for example, var/www/WebAPI1).
Hosting ASP.NET Core on CentOS with Apache
Configuring a Proxy Server
A reverse proxy is a common setup for serving dynamic web applications. The reverse proxy terminates the HTTP request and forwards it to the Web API application. In this example, Apache is configured as a reverse proxy, and Kestrel serves the Web API application. Apache forwards client requests to the Web API application running on Kestrel instead of fulfilling requests itself.
Installing Apache
Update CentOS packages to the latest stable versions:
sudo yum update -y
Install the Apache web server on CentOS with a single yum
command:
sudo yum -y install httpd mod_ssl
To verify where Apache is installed, run whereis httpd
from a command prompt.
Configuring Apache
Open the /etc/httpd/conf/httpd.conf
file and set the ServerName directive globally:
sudo nano /etc/httpd/conf/httpd.conf
# Set ServerName in this configuration file
ServerName www.example.com:80
The configuration files for Apache are located in the /etc/httpd/conf.d/
directory. Any file with the .conf extension is processed in alphabetical order in addition to the module configuration files in /etc/httpd/conf.modules.d/
, which contains all the necessary configuration files to load modules.
Create a configuration file:
sudo nano /etc/httpd/conf.d/WebAPI1.conf
An example of configuration files for the application:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=$scheme
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ServerName www.example.com
ServerAlias *.example.com
ErrorLog /var/log/httpd/WebAPI1-error.log
CustomLog /var/log/httpd/WebAPI1-access.log common
</VirtualHost>
The VirtualHost
block can appear multiple times in one or more files on a server. In the preceding configuration file, Apache accepts public traffic on port 80. The domain www.example.com
is being served, and the *.example.com
alias resolves to the same domain. See Name-based virtual host support for more information. Requests are proxied at the root to port 5000 of the server at 127.0.0.1. For bi-directional communication, ProxyPass
and ProxyPassReverse
are required. To change Kestrel's IP/port, see Kestrel: Endpoint configuration
Warning: Failure to specify a proper ServerName directive in the VirtualHost block exposes your application to security vulnerabilities. Subdomain wildcard binding (for example, *.example.com
) doesn't pose this security risk if you control the entire parent domain (as opposed to .com
, which is vulnerable). See rfc7230 section-5.4 for more information.
Logging can be configured per VirtualHost
using ErrorLog
and CustomLog
directives. ErrorLog
is the location where the server logs errors, and CustomLog
sets the filename and format of log file. In this case, this is where request information is logged. There's one line for each request.
Save the file and test the configuration. If everything passes, the response should be Syntax [OK]
.
sudo service httpd configtest
Restart Apache:
sudo systemctl restart httpd
sudo systemctl enable httpd
Monitoring the Application
Apache is now set up to forward requests made to http://localhost:80
to the Web API application running on Kestrel at http://127.0.0.1:5000
. However, Apache isn't set up to manage the Kestrel process. Use systemd and create a service file to start and monitor the underlying web application. systemd is an init system that provides many powerful features for starting, stopping, and managing processes.
Creating the Service File
Create the service definition file:
sudo nano /etc/systemd/system/kestrel-webapi1.service
An example of service files for the application:
[Unit]
Description=Example .NET Web API application running on CentOS 7
[Service]
WorkingDirectory=/var/www/WebAPI1
ExecStart=/usr/share/dotnet /var/www/WebAPI1/WebAPI1.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
If the user apache isn't used by the configuration, the user must be created first and given proper ownership of the files.
Use TimeoutStopSec
to configure the duration of time to wait for the application to shut down after it receives the initial interrupt signal. If the application doesn't shut down in this period, SIGKILL is issued to terminate the application. Provide the value as unitless seconds (for example, 150
), a time span value (for example, 2min 30s
), or infinity
to disable the timeout. TimeoutStopSec
defaults to the value of DefaultTimeoutStopSec
in the manager configuration file (systemd-system.conf, system.conf.d, systemd-user.conf, user.conf.d). The default timeout for most distributions is 90 seconds.
# The default value is 90 seconds for most distributions.
TimeoutStopSec=90
Save the file and enable the service:
sudo systemctl enable kestrel-webapi1.service
Start the service and verify that it's running:
# Start the service
sudo systemctl start kestrel-webapi1.service
# Verify the service
sudo systemctl status kestrel-webapi1.service
kestrel-webapi1.service - Example .NET Web API application running on CentOS 7
Loaded: loaded (/etc/systemd/system/kestrel-webapi1.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2019-08-06 13:46:27 CST; 5s ago
Main PID: 46668 (dotnet)
Tasks: 16
CGroup: /system.slice/kestrel-webapi1.service
└─46668 /usr/share/dotnet/dotnet /var/www/WebAPI1/WebAPI1.dll
With the reverse proxy configured and Kestrel managed through systemd, the web application is fully configured and can be accessed from a browser on a local machine at http://localhost/api/sample/load
. Inspecting the response headers, the Server header indicates that the Web API application is served by Kestrel:
HTTP/1.1 200 OK
Date: Tue, 06 Aug 2019 05:52:17 GMT
Server: Kestrel
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Viewing Logs
Since the web application using Kestrel is managed using systemd, events and processes are logged to a centralized journal. However, this journal includes all of the entries for services and processes managed by systemd. View the specific items of kestrel-webapi1.service
with the following command:
sudo journalctl -fu kestrel-webapi1.service
For time filtering, specify time options with the command. For example, use --since today
to filter for the current day or --until 1 hour ago
to see the previous hour's entries. For more information, see man page for journalctl.
sudo journalctl -fu kestrel-webapi1.service --since "2019-08-06" --until "2019-08-06 23:00"
Configuring the Reverse Proxy for Secure (HTTPS) Client Connections
To configure Apache for HTTPS, the mod_ssl module is used. When the httpd module was installed, the mod_ssl module was also installed. If it wasn't installed, use yum
to add it to the configuration.
sudo yum install mod_ssl
To enforce HTTPS, install the mod_rewrite
module to enable URL rewriting:
sudo yum install mod_rewrite
Modify the /etc/httpd/conf.d/WebAPI1.conf
file to enable URL rewriting and secure communication on port 443:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=$scheme
</VirtualHost>
<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>
<VirtualHost *:443>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ErrorLog /var/log/httpd/WebAPI1-error.log
CustomLog /var/log/httpd/WebAPI1-access.log common
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>
This example is using a locally-generated certificate. SSLCertificateFile should be the primary certificate file for the domain name. SSLCertificateKeyFile should be the key file generated when CSR is created. SSLCertificateChainFile should be the intermediate certificate file (if present) that was supplied by the certificate authority.
Save the file and test the configuration:
sudo service httpd configtest
Restart Apache:
sudo systemctl restart httpd
After HTTPS is fully configured, the web application can be accessed from a browser on a local machine at https://localhost/api/sample/load
. Please pay attention here, it's https://....
Attribution
The content of this section incorporates some materials from “Host ASP.NET Core on Linux with Apache“ by Shayne Boyer licensed under CC BY 2.0.