.NET Core

Including / Excluding files from build with VS2017 and .NET Core

I have a project where the wwwroot for an ASP.NET Core application is an SPA managed entirely by a node build chain. This means VS is completely hands-off with regards to the development of the UI, but it does have to somewhat be aware of it to debug and publish.

VS2015 / project.json Build

The project.json file looked as follows:

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true,
    "compile": {
      "exclude": ["wwwroot"]
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot/dist/prod",
      "appsettings.json",
      "web.config"
    ]
  }

This would result in the wwwroot not getting compiled whatsoever, but the files within ‘dist’ would get published along with the .NET code. The node_modules folder was hidden within the VS Solution Explorer.

VS2017 / CSProj build

The auto-migration with VS2017 will attempt to follow the changes in the project.json, but the end result won’t work. VS will be super slow due to the node_modules folder, while also trying to compile the Typescript. You can wholesale block the compilation of Typescript, but I prefer to be a bit more explicit about what I want VS to do. Edit the .csproj for your project, and use the following ItemGroup to do ensure it does the same as the project.json from earlier:

<ItemGroup>
  <Compile Remove="wwwroot\**" />
  <Content Remove="wwwroot\**" />
  <EmbeddedResource Remove="wwwroot\**" />
  <None Remove="wwwroot\**" />
  <Content Include="wwwroot\dist\prod\**\*" />
  <Content Update="wwwroot\dist\prod\**\*;appsettings.json;web.config">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
  </Content>
</ItemGroup>

This has the additional advantage in that the files we don’t care about in wwwroot are automatically hidden for all users of the solution – no manually hiding from Solution Explorer.

Posted by Dan in Programming, 2 comments

Building an ASP.NET Core Docker Image on Linux

ASP.NET Core is super awesome, especially since it plays really well with the latest deployment methods. Microsoft has even gone as far as to pre-package an optimised .NET Core Docker image with the core libraries pre-compiled for a super-fast startup. So let’s get started, but first you’ll need to install Docker and the .NET Tools on your Linux machine if you haven’t already.

Add a Dockerfile

Add a new text file called ‘Dockerfile’ (case sensitive) to the root of your project, make sure it doesn’t have any extension (such as .txt). In the Dockerfile add the following code:

FROM microsoft/aspnetcore:1.1.0
WORKDIR /app
COPY ./output .
ENTRYPOINT ["dotnet", "MySite.dll"]

Update the ‘MySite.dll’ reference to the name of your project with a .dll extension. Also while you’re at it, change the version number of .NET Core if you’re not using 1.1 like I am. I highly recommend 1.1 or later with Linux due to much better performance.

Build from command line

Run the following commands in the project directory:

dotnet restore
dotnet publish -o output -c release

This will get all dependencies, compile a release build, and put the result into the ‘output’ directory. The reason we’re using a sub-directory is due to a bug in the tooling, if we use a parent relative path (../) the ‘publishOptions/include’ config setting in project.json will be ignored and you’ll be missing a chunk of your project!

Build the docker image

Now let’s get that code into a Docker image! Run the following command:

sudo docker build -t myapp .

Feel free to rename myapp to something a little more descriptive. You can also specify multiple tags, such as:

sudo docker build -t myapp -t myapp:1.0 .

It’s really up to you with regards to tagging. If you’re publishing to a repository (likely), make sure to add the applicable repository tag to the list.

Running the image

Run the following command to start up a new container:

sudo docker run -p 8000:80 myapp 

Make sure to update myapp to the name you used earlier when building. Your site should now be accessible on port 8000: http://localhost:8000

You may be wondering why we forwarded to port 80, and not 5000 or whatever port you’ve specified in launchSettings.json. As part of the aspnetcore image, an environment variable is set to tell Kestrel to host on port 80. This can be overridden either in your Dockerfile, or using app.UseUrl in your Program.cs file.

Don’t connect directly to the container

Remember, the site is still running in Kestrel so it’s not magically secure by virtue of running in a container. Make sure to use a reverse-proxy such as nginx when running your site in a production environment. Microsoft are working on hardening Kestrel so that you can use it directly in the future – but we’re not there yet.

Possible errors

Did you mean to run dotnet SDK commands?

You might get the following error upon execution:

Did you mean to run dotnet SDK commands? Please install dotnet SDK from:
http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409

This basically means the .dll you referenced couldn’t be found. Double-check all of your paths and filenames. It’s easy to include the source instead of the output, or even save to / from the wrong directory.

Could not load <dependency>.dll

If you get dependency errors on execution, it means the output of the publish wasn’t saved to the /app folder within the container. The .dll files from the publish operation must all go directly into the root of the /app folder in the container. This means you can’t rename /app to something else.

More information

You can get more information from:

Github

Official MS Github: https://github.com/aspnet/aspnet-docker. Navigate to the version of .NET Core you want (1.0/jessie, 1.1/jessie, etc.). If you’re using the output of a publish, you’ll want the ‘runtime’ subfolder.

Docket

Official MS Docker Hub: https://hub.docker.com/r/microsoft/aspnetcore/. A quick overview of the base image, although it looks like MS want to spend most of their focus on the Github account.

Posted by Dan in Guides, 0 comments

Alexa Skills with ASP.NET Core – Porting Reindeer Games

Making a custom Alexa skill is surprisingly easy, especially with the samples available from Amazon. I recently took the opportunity to port the NodeJS Reindeer Games project to .NET, and at the same time improve the code to something a little more readable and maintainable.

I’ve put the code up on my GitHub here: https://github.com/danclarke/ReindeerGamesNetCore

There’s a project for both a Web Service hosted on Azure and a Lambda Function hosted on AWS.

Hosting-wise a Lambda Function is easily the preferred solution simply due to latency. Calls from Alexa to an AWS Lambda are much faster than leaving the data centre and calling your remote web service.

If you do need to create a web service it must be SSL secured. This is easy in production, but a little harder during development. To make this easier, you might want to use something like Caddy with Let’s Encrypt.

Posted by Dan in Alexa, 0 comments