A very good question - my goal was to get some sort of .Net core application up and running in Cloud Foundry. As part of my development plans I want to increase my skills in programming in languages like .Net and Java.

While I have started to learn .Net using a number of tutorials (I’m lucky Pivotal give me access to Safaribooks and Pluralsight for my development needs) I started to think how can I quickly demo .Net and Cloud Foundry?

To do this I want to quickly create a web application in front of peoples eyes to reduce the chance they think I am using some kind of smoke and/or mirror. After a little bit of investigation I cam across the ability on my Mac to use the dotnet CLI. The result is a being able to create a boilerplate template;

$ dotnet new -h
Usage: new [options]

Options:
  -h, --help          Displays help for this command.
  -l, --list          Lists templates containing the specified name. If no name is specified, lists all templates.
  -n, --name          The name for the output being created. If no name is specified, the name of the current directory is used.
  -o, --output        Location to place the generated output.
  -i, --install       Installs a source or a template pack.
  -u, --uninstall     Uninstalls a source or a template pack.
  --type              Filters templates based on available types. Predefined values are "project", "item" or "other".
  --force             Forces content to be generated even if it would change existing files.
  -lang, --language   Specifies the language of the template to create.


Usage: new [options]

Options:
  -h, --help          Displays help for this command.
  -l, --list          Lists templates containing the specified name. If no name is specified, lists all templates.
  -n, --name          The name for the output being created. If no name is specified, the name of the current directory is used.
  -o, --output        Location to place the generated output.
  -i, --install       Installs a source or a template pack.
  -u, --uninstall     Uninstalls a source or a template pack.
  --type              Filters templates based on available types. Predefined values are "project", "item" or "other".
  --force             Forces content to be generated even if it would change existing files.
  -lang, --language   Specifies the language of the template to create.


Templates                                         Short Name       Language          Tags
--------------------------------------------------------------------------------------------------------
Console Application                               console          [C#], F#, VB      Common/Console
Class library                                     classlib         [C#], F#, VB      Common/Library
Unit Test Project                                 mstest           [C#], F#, VB      Test/MSTest
xUnit Test Project                                xunit            [C#], F#, VB      Test/xUnit
ASP.NET Core Empty                                web              [C#], F#          Web/Empty
ASP.NET Core Web App (Model-View-Controller)      mvc              [C#], F#          Web/MVC
ASP.NET Core Web App                              razor            [C#]              Web/MVC/Razor Pages
ASP.NET Core with Angular                         angular          [C#]              Web/MVC/SPA
ASP.NET Core with React.js                        react            [C#]              Web/MVC/SPA
ASP.NET Core with React.js and Redux              reactredux       [C#]              Web/MVC/SPA
ASP.NET Core Web API                              webapi           [C#], F#          Web/WebAPI
global.json file                                  globaljson                         Config
NuGet Config                                      nugetconfig                        Config
Web Config                                        webconfig                          Config
Solution File                                     sln                                Solution
Razor Page                                        page                               Web/ASP.NET
MVC ViewImports                                   viewimports                        Web/ASP.NET
MVC ViewStart                                     viewstart                          Web/ASP.NET

Examples:
    dotnet new mvc --auth Individual
    dotnet new web
    dotnet new --help

Looking at the output from the help flag we can see templates like MVC/web/razor/angular etc. As a result we can very quickly get a angular web application example created.

$ dotnet new razor
The template "ASP.NET Core Web App" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/template-3pn for details.

Processing post-creation actions...
Running 'dotnet restore' on /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj...
  Restoring packages for /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj...
  Restore completed in 60.93 ms for /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj.
  Generating MSBuild file /Users/redwards/workspace/customers/demo-zone/razor-demo/obj/razor-demo.csproj.nuget.g.props.
  Generating MSBuild file /Users/redwards/workspace/customers/demo-zone/razor-demo/obj/razor-demo.csproj.nuget.g.targets.
  Restore completed in 983.69 ms for /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj.

Restore succeeded.

This generates a number of files and directories;

$ tree -L 2
.
├── Pages
│   ├── About.cshtml
│   ├── About.cshtml.cs
│   ├── Contact.cshtml
│   ├── Contact.cshtml.cs
│   ├── Error.cshtml
│   ├── Error.cshtml.cs
│   ├── Index.cshtml
│   ├── Index.cshtml.cs
│   ├── _Layout.cshtml
│   ├── _ValidationScriptsPartial.cshtml
│   ├── _ViewImports.cshtml
│   └── _ViewStart.cshtml
├── Program.cs
├── Startup.cs
├── appsettings.Development.json
├── appsettings.json
├── bundleconfig.json
├── obj
│   ├── project.assets.json
│   ├── razor-demo.csproj.nuget.cache
│   ├── razor-demo.csproj.nuget.g.props
│   └── razor-demo.csproj.nuget.g.targets
├── razor-demo.csproj
└── wwwroot
    ├── css
    ├── favicon.ico
    ├── images
    ├── js
    └── lib

7 directories, 23 files

We now have a basic razor web application that will run with .Net Core.

Up and running locally

What does this template look like? You can quickly get it up and running locally on your machine;

$ dotnet run
Hosting environment: Production
Content root path: /Users/redwards/workspace/customers/demo-zone/razor-demo
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Screenshot

This is all well and good for local testing however what I wanted to do was get this working in Cloud Foundry.

Up and running on PCF

The good news is to get the code running in Cloud Foundry all I need to do is a cf push.

$ cf push razor-demo
Creating app razor-demo in org redwards / space redwards as redwards...
OK

Creating route razor-demo.<domain>...
OK

Binding razor-demo.<domain> to razor-demo...
OK

Uploading razor-demo...
Uploading app files from: /Users/redwards/workspace/customers/demo-zone/razor-demo
Uploading 232.5K, 67 files
Done uploading
OK

Starting app razor-demo in org redwards / space redwards as redwards...
Downloading binary_buildpack...
Downloading php_buildpack...
Downloading dotnet_core_buildpack...
Downloading ruby_buildpack...
Downloading staticfile_buildpack...
Downloaded php_buildpack
Downloading hwc_buildpack...
Downloaded binary_buildpack
Downloading java_buildpack_offline...
Downloaded dotnet_core_buildpack
Downloading nodejs_buildpack...
Downloaded staticfile_buildpack
Downloading go_buildpack...
Downloaded ruby_buildpack
Downloading python_buildpack...
Downloaded python_buildpack
Downloaded java_buildpack_offline
Downloaded hwc_buildpack
Downloaded nodejs_buildpack
Downloaded go_buildpack
Creating container
Successfully created container
Downloading app package...
Downloaded app package (589.4K)
-----> Dotnet-Core Buildpack version 2.0.2
-----> Supplying Dotnet Core
-----> Installing libunwind 1.2.1
       Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/35a6b4e9cad7a7fe8f8990e063509f7b/libunwind-1.2.1-linux-x64-80af276a.tgz]
-----> Installing dotnet 2.0.3
       Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/a36740596ac4c9b8b9a0fb84a6e303bf/dotnet.2.0.3.linux-amd64-b56d13fc.tar.xz]
-----> Finalizing Dotnet Core
-----> Restore dotnet dependencies
         Restoring packages for /tmp/app/razor-demo.csproj...
         Restoring packages for /tmp/app/razor-demo.csproj...
         Installing System.Xml.XmlSerializer 4.0.11.

#<........Removed for brevaty.......>

         Installing System.Runtime.InteropServices.Runtimr.m.3sdd talling Sysm         Generating MSBuild file /tmp/app/obj/razor-demo.csproj.nuget.g.props.
         Generating MSBuild file /tmp/app/obj/razor-demo.csproj.nuget.g.targets.
         Restore completed in 7.8 sec for /tmp/app/razor-demo.csproj.
       Required dotnetframework versions: [2.0.0 2.0.5]
-----> Installing dotnet-framework 2.0.0
       Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/c8e245c37838e1b497606c9125af2132/dotnet-framework.2.0.0.linux-amd64-13cb2a76.tar.xz]
       **WARNING** A newer version of dotnet-framework is available in this buildpack. Please adjust your app to use version 2.0.5 instead of version 2.0.0 as soon as possible. Old versions of dotnet-framework are only provided to assist in migrating to newer versions.
-----> Installing dotnet-framework 2.0.5
       Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/07d1c50ee2f84a1f4a5a43e741e4a25f/dotnet-framework.2.0.5.linux-amd64-62cc2fb0.tar.xz]
-----> Publish dotnet
       Microsoft (R) Build Engine version 15.4.8.50001 for .NET Core
       Copyright (C) Microsoft Corporation. All rights reserved.

         razor-demo -> /tmp/app/bin/Debug/netcoreapp2.0/ubuntu.14.04-x64/razor-demo.dll
         razor-demo -> /tmp/contents177473746/deps/0/dotnet_publish/
-----> Cleaning staging area
       Removing .nuget
       Removing .local
       Removing dotnet
Exit status 0
Uploading droplet, build artifacts cache...
Uploading build artifacts cache...
Uploading droplet...
Uploaded build artifacts cache (223B)
Uploaded droplet (39.1M)
Uploading complete
Stopping instance b9279880-2745-4d1d-ad94-b9ef73590d0b
Destroying container
Successfully destroyed container

1 of 1 instances running

App started


OK

App razor-demo was started using this command `cd ${DEPS_DIR}/0/dotnet_publish && ./razor-demo --server.urls http://0.0.0.0:${PORT}`

Showing health and status for app razor-demo in org redwards / space redwards as redwards...
OK

requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: razor-demo.<domain>
last uploaded: Thu Feb 15 21:20:06 UTC 2018
stack: cflinuxfs2
buildpack: dotnet-core

     state     since                    cpu    memory        disk           details
#0   running   2018-02-15 09:21:05 PM   0.0%   36.2M of 1G   106.6M of 1G

Voila we have something running; Screenshot

My Cloud Foundry deployment made use of the OOTB .Net, dotnet_core_buildpack buildpack to get the app running. The cf push of the source code did the following;

  • Installs .NET Core runtime – version specify via global.json, else the build pack chooses
  • Restores application dependencies
  • Generates the command to run the application which builds the application before it runs it

To list the buildpacks use the following command;

cf buildpacks
Getting buildpacks...

buildpack                position   enabled   locked   filename
hwc_buildpack            1          true      false    hwc_buildpack-cached-v2.3.11.zip
staticfile_buildpack     2          true      false    staticfile_buildpack-cached-v1.4.18.zip
java_buildpack_offline   3          true      false    java-buildpack-offline-v4.7.1.zip
ruby_buildpack           4          true      false    ruby_buildpack-cached-v1.7.5.zip
nodejs_buildpack         5          true      false    nodejs_buildpack-cached-v1.6.10.zip
go_buildpack             6          true      false    go_buildpack-cached-v1.8.13.zip
python_buildpack         7          true      false    python_buildpack-cached-v1.6.1.zip
php_buildpack            8          true      false    php_buildpack-cached-v4.3.43.zip
dotnet_core_buildpack    9          true      false    dotnet-core_buildpack-cached-v2.0.2+1518187691.zip
binary_buildpack         10         true      false    binary_buildpack-cached-v1.0.15.zip

Answer

It turns out the answer to the question can be very quickly, in fact it takes about 5 minutes to create and deploy the application template. Obviously it is a pretty useless app and if you want it to actually do anything some time will need to be invested focusing on developing functionality.