How to deploy ASP.NET Core 3.x to Google Compute Engine / IIS

Saverio Terracciano
Google Cloud - Community
12 min readMar 31, 2020
…this is fine.

Lately, I’ve been helping some friends and members of our community getting started with .NET Core and GCP.
Those are two technologies I am very passionate about, so I naturally end up advocating for them, even if they don’t always play nice with each other.

Unlike for old ASP.NET MVC, Google Compute Engine (GCE) is not my favourite choice to deploy my Core applications, but I was surprised by how many small issues were preventing my friends from making progress and how common the same issues were among them.
Given I am currently on lockdown due to COVID-19, I thought it was an excellent time & topic to go back writing articles since this could help many others with similar troubles.

If you’re a (new?) .NET Core developer and are having troubles deploying your web app to GCE I am here to help!

If you don’t have much time, or you may already have some experience and you just want the nugget…

TL;DR

  • Most of the people I have helped were assuming that since they could deploy self-containing applications, they didn’t need to rely on any environment Framework, but IIS requires an “ASP.NET Core Module” to be able to interact with your application.
    The GCP Marketplace ASP.NET Image uses an outdated release of the Bundle (2.1) that has the Version 1 of such module, to run Core 3.x applications, you need Version 2.
    You will have to manually download & update the bundle
    .
  • Many had issues with the Site Name in their deploy configurations. The Site Name has to match an existing application on IIS.
    Unless you configure IIS and Web Deploy to also create your site and application pool, you have to target what is already there.
    When you spin up your ASP.NET Image VM, it will have a “Default Web Site”. You can use that one, or a composite of that “Default Web Site/Something”.

If you’ve got more time and you’re still with me, I will expand on those points & explain how to fix them while guiding you in creating a barebone ASP.NET Core application, spinning up a VM with IIS on GCE & deploying the web app using various ways:

  • Google Cloud Tools for Visual Studio
  • Standard Web Deploy in Visual Studio
  • Dotnet Core CLI Publish

The following steps are based on a Windows machine, but most of the issues encountered are related to IIS and I will mark them with the tag [PAIN POINT] to indicate something that has been a common progress stopper, source of questions or cause of headache.

Disclaimer: A few of the problems encountered will be likely fixed in the future with updates to the current GCP ASP.NET Framework Marketplace Image, in which case I will try to get back to this and make a note of it to avoid confusion, but generally, this article should still be useful on how to get started in deploying an ASP.NET Core App to GCE.

Requirements

Before getting started I assume you have installed on your machine:

and have basic familiarity with GCP & .NET Core, with a GCP account to use.

Let’s get started!

Creating the ASP.NET Core Web Application

First of all, we need an application, a default MVC template can be a good example as that will allow us to have quick visual feedback.

We can either create it through Visual Studio:

Or equivalently, from the command prompt we can use the CLI (https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-new):

dotnet new mvc -n "GCE_Core"

from here onwards we’ll assure our project is named “GCE_Core”.

To check that everything was initialised and restored correctly we can try to build & launch our project in Visual Studio pressing F5 which will also open a browser window, or from the CLI we can navigate to the folder of the project and then execute:

dotnet run
https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-run

as we can see the application is listening on localhost on the port 5001 for HTTPS and 5000 for HTTP, let’s use a browser and navigate to either:

you can choose to customise this page at “ \Views\Home\Index.cshtml”, otherwise, we are good.

Creating our Google Compute Engine IIS VM

Let’s head to https://console.cloud.google.com/ and if needed, let’s create a new Project, in my example, I called it “DotNetTesting”.

We now need our IIS server. We could spin up a custom GCE Windows Server VM, install IIS and configure it, but it would be a lengthy process and probably overkill for someone getting started or that just wants to run their application.

The suggested way on the official documentation is to use a blueprint image ready to deploy on GCP Marketplace, the ASP.NET Framework Marketplace Image (https://console.cloud.google.com/marketplace/details/click-to-deploy-images/aspnet), which will create a VM for you with IIS, .NET, .NET Core & SQL Express preinstalled and configured:

…and here is the cause of the first pain point of the process.
As you can see from the screenshot, the image comes with .NET Core 2.1 and it hasn’t been updated yet to .NET Core 3.x., let’s keep that in mind and proceed.

Pressing “Launch”, we will be shown a classic VM config screen:

I only changed the name of the VM and selected the Zone in the region closer to me.

Since we will be using RDP to access the server, while it’s not needed, you may want to select a slightly bigger “Machine Type” for your instance, so that you will have a smoother experience when remoting to it.

Let’s press “Deploy” and wait for the machine to be created and initialised.
It should take less than a minute, but it’s a good idea to wait for it to be properly booted before proceeding to create a Windows Account.

It will then ask you to choose a Username

and give you a password:

take note of it, as you will not be able to retrieve it, and may have to reset it if you lose it.

We finally have our working machine and credentials!

We will need them to RDP to our new VM with either the Chrome RDP for Google Cloud Platform extension (https://chrome.google.com/webstore/detail/chrome-rdp-for-google-clo/mpbbnannobiobpnfblimoapbephgifkm/related) or any other RDP client like Windows Remote Desktop Connection.

[PAIN POINT] Pay attention to the self-signed SSL certificate, if you have previous ones for other accounts, you may need to remove them from your RDP client.

Deploying the Web Application

We now want to push our web app to the server’s IIS instance.

We will see 3 ways to do that, even if you’re not interested in how to deploy with GC Tools, read at least the part marked with [PAIN POINT] as that is relevant also for the other alternatives.

Deploying with Google Cloud Tools for Visual Studio

Assuming you’re using Visual Studio, you need to install “Google Cloud Tools for Visual Studio” from “Extensions > Manage Extensions”:

Once the extension is installed, we will find a new plugin in the upper right part of Visual Studio, let’s click on it and start by logging in with our GCP account.

Pressing Change Account will trigger an OAuth process that will allow the plugin to connect to GCP.

After authenticating, we will want to also select the Project on which we have created our VM.

Once that is set up, you can proceed to right-click on the project from the Solution Explorer and select “Publish to Google Cloud…” and then “Google Compute Engine”.

We will be notified that App Engine or GKE are preferred ways to deploy the project, but that just in case we should use the ASP.NET Marketplace Image (the same one we have used in our previous step).

We need to fill in the details for the instance and credentials on which to deploy. It’s a straightforward process but a few clarifications are in order:

  • You can use the account credentials you set up in the previous step, but you could also create or reset them from the “Manage Windows Credentials” option.
  • [PAIN POINT] Site Name is probably the trickiest bit as it’s not explained anywhere and you would be led to think that is just a name you want to give to your application, but this has to be the name of an application already created in IIS.
    The ASP.NET Image will initialise IIS with one called “Default Web Site”. Unless you RDP first to your VM and create a new one, you will have to settle for “Default Web Site”, or use that as root to have something like “Default Web Site/GCP_Core”.
  • If you created your project via CLI, you may be prompted to create a Solution file in which to include your project.

Upon pressing “Publish” your project will be compiled and pushed to GCE.
By default, a browser instance should be launched pointing at the newly deployed application.

Deploying with the Web Deploy included in Visual Studio

If you don’t want to use Google Cloud Tools, you have the option to use the Standard Web Deploy (MSDeploy) that comes built-in with Visual Studio.

In this case, you will have a few more details to fill in.

  • Right-click on your project and select “Publish…
  • The first time you access it you will have to create a Profile.
    Select “IIS, FTP, etc.” and then “Create Profile”.
Please keep in mind the [PAIN POINT] previously discussed in the GCP Tools section
  • Press “Next”, you shouldn’t be required to change anything for the Settings. You can then press “Save”.
  • You should now be ready to deploy, so just press “Publish”.

[PAIN POINT]: If you want to use the Preview action, you will need to Allow untrusted certificates (like our self-signed one). There are various ways to do this, the quickest one will be to manually edit the profile file:

adding

<AllowUntrustedCertificate>True</AllowUntrustedCertificate>
  • Save it, so you can finally use the Preview option:
Web Deploy is smart enough to only have you upload the files that have changed since the previous release

Deploy from .NET Core CLI

It’s possible to deploy your application also using .NET Core CLI.

However, you need a Publish Profile, just like the one we created for the Web Deploy in Visual Studio (previous section).

Assuming you have to create one by hand, you can use this template:

<?xml version="1.0" encoding="utf-8"?><Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><PropertyGroup><WebPublishMethod>MSDeploy</WebPublishMethod><LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration><LastUsedPlatform>Any CPU</LastUsedPlatform><SiteUrlToLaunchAfterPublish>34.89.14.135</SiteUrlToLaunchAfterPublish><LaunchSiteAfterPublish>True</LaunchSiteAfterPublish><ExcludeApp_Data>False</ExcludeApp_Data><TargetFramework>netcoreapp3.1</TargetFramework><ProjectGuid>9f0c7188-a6be-4bc5-ab5a-d0878b97c0b0</ProjectGuid><SelfContained>false</SelfContained><MSDeployServiceURL>34.89.14.135</MSDeployServiceURL><DeployIisAppPath>Default Web Site</DeployIisAppPath><RemoteSitePhysicalPath /><SkipExtraFilesOnServer>True</SkipExtraFilesOnServer><MSDeployPublishMethod>WMSVC</MSDeployPublishMethod><EnableMSDeployBackup>True</EnableMSDeployBackup><UserName>terraccianosaverio</UserName><_SavePWD>True</_SavePWD><AllowUntrustedCertificate>True</AllowUntrustedCertificate></PropertyGroup></Project>

customising the fields that differ in your application, VM and credentials. (Keep always in mind the issue with the Site Name / DeployIisAppPath highlighted in the previous section)

You can then proceed to use the dotnet publish command (https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish):

dotnet publish -c Release /p:PublishProfile=<YOUR_PUBLISH_PROFILE_PATH> "/p:Password=<YOUR_PASSWORD>"

Deployed but…

To your dismay, despite the method you chose to deploy your application you will find out that navigating to the URL, the page displays a dreadful Error Code 500!

This is not really informative, so let’s RDP to our instance and try to access the web application URL from there.

As we are able to see detailed errors, we will then be able to gain some more insight:

[PAIN POINT] Most of my friends assumed that if they deployed a self-contained .NET Core application they would not need to be reliant on the framework present on the machine.

This assumption generally holds if it wasn’t for the fact that the ASP.NET Core application will have to work as a reverse proxy with IIS, and for this to happen, IIS needs to know how to interact with your web app.

It’s important to know the difference between IIS in-process and out-of-process handling of Core applications, but this is outside the scope of this article, for more details, check this link https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1

It should suffice to know that IIS uses an “ASP.NET Core Module” (https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module?view=aspnetcore-3.1) to do that.

This module has two main versions:

  • Version 1 allows you to run any Core 2.x application
  • Version 2 allows you to also run Core 3.x

Version 2 was bundled-in starting with Core 2.2, unfortunately, as of now, the image on the marketplace comes with Core 2.1 (and Version 1 of the module).

It falls on us to update the VM’s DotNet Core bundled framework version.

Updating the DotNetCore Runtime Bundle

Let’s RDP to the machine and download the latest version of the Framework Bundle: https://dotnet.microsoft.com/permalink/dotnetcore-current-windows-runtime-bundle-installer

  • [PAIN POINT] If you want to download it through the browser, please keep note you will first need to Enable the Files download in
    Internet Explorer’s Options > Internet Options > Security > Custom Level… > Downloads > File Download > Enable”
  • Alternatively, you can open a command prompt, launch PowerShell and use this command to download the file:
curl https://download.visualstudio.microsoft.com/download/pr/ff658e5a-c017-4a63-9ffe-e53865963848/15875eef1f0b8e25974846e4a4518135/dotnet-hosting-3.1.3-win.exe -o installer.exe

TRIVIA: that is not the real curl command-line tool, but a wrapper around Invoke-WebRequest.

Once you have the file, launch the installer and follow the instructions.

At the end of the process you might be prompted or advised to restart the server, but that should not be necessary.

If you try to reload now the URL of your application…

Yes, I made some minor alteration to the MVC template…

Congratulations! We finally have a working application!

Since you’re on the server, take a minute to launch and review Internet Information Services (IIS) Manager, here you will be able to tweak the configuration of your application and eventually create new websites to target through the WebDeploy protocol.

Parting words

WebDeploy is an excellent tool to interact with IIS but it requires more setup than what is offered out of the box to achieve its full potential (Create Applications on deploy, create Application Pools).

Compared to other methods that you might use to just copy the content of your project (FTP or Manually) even in its basic configuration it’s faster, safer and more flexible.
Take some time to explore its capabilities:
https://www.iis.net/downloads/microsoft/web-deploy

Regarding the ASP.NET Image on the Marketplace, hopefully, it will soon be updated so you won’t be required to manually update the instance.

As I was saying in the opening of this text, GCE is not my favourite way to host DotNet Core applications, in fact, I look forward in showing you how to deploy to AppEngine, GKE & Cloud Run in my future posts, so stay tuned.

I hope I was able to help you with this article, but if you have further doubts or feedback, I’ll be glad to chat with you on Twitter, DMs are open (https://twitter.com/TetsuoRyuu)

--

--

Saverio Terracciano
Google Cloud - Community

Lead Organiser of @GDGCloud Software Engineer @TIWGroup, Gamer, Voracious consumer of Tv shows, Movies, Gunpla, Mangas…oh & food! Contact me at @tetsuoryuu