.NET Core

Rainer Stropek | time cockpit

rainer@timecockpit.com | Blog | GitHub

Samples see GitHub

Agenda (German)

Als .NET-Entwickler fragt man sich momentan oft, warum Microsoft so grundlegende Änderungen an .NET vornimmt. In ASP.NET 5 entdeckt man so viele neue Tools, Libraries und Konzepte, dass man leicht den Überblick verlieren kann. In dieser Session erklärt Rainer Stropek, was hinter den Umbaumaßnahmen von Microsoft an .NET steckt.

  • Welche neuen Grundkonzepte stecken dahinter?
  • Warum und wofür sind die Änderungen sinnvoll?
  • Was ändert sich für die tägliche Entwicklungspraxis?
  • Welche Rolle spielen Open Source und Plattformunabhängigkeit?

Getting Started

What is .NET?

New to .NET? Need to introduce someone to .NET?
Quick overview

Different implementations

  • .NET Core
    New, redesigned, cross-platform, open-source, ...

  • .NET Native
    .NET adhead-of-time compiled

  • .NET Framework
    Server, client, just Windows; huge .NET Framework Class Library incl. WCF, WPF, etc.

  • Mono
    Community-driven, cross-platform, open-source; follows .NET Framework, not .NET Core

What is .NET Core?

Contender: Node.js

.NET Runtime and framework
ECMA 335 implementation

Cross-platform
Windows, Linux and MacOS

Open-source

Delivered by package manager (NuGet, APT, etc.) or Docker

"A-la-carte" framework (take just what you need)

Installation

Demo

Sample on GitHub

  • Introduction to DNVM
  • Generate console app with Yeoman
  • Learn about DNU and DNX
  • Basics about project.json
  • .NET Core on Windows and Linux

DNU: DNX Utility

Note: This will change, see .NET CLI

Manage packages for your application
Detailed reference (note --help option)

  • Restore packages
  • Install packages
  • Publish app into self-contained directory
  • Build NuGet package
  • Produce assemblies
  • Lists dependencies

DNX

.NET Execution Environment

Note: DNX will be replaced by .NET CLI (details)

Resources

Projects

project.json

Minimum Example

Try that and note that dnx run fails

namespace myApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
        }
    }
}
                    

{
  "frameworks": {
    "dnx451": {},
    "dnxcore50": {}
  },
  "commands": { 
    "run": "myApp" 
  }
}                  

Sample on GitHub

Dependencies

Add dependency to System.Console
Use VS (IntelliSense) or run dnu install System.Console

Global or framework-specific dependencies


{
  "dependencies": {
    "System.Console": "4.0.0-beta-23516"
  },
  ...
}                   

{
  "dependencies": { },
  "frameworks": {
    "dnx451": {},
    "dnxcore50": {
        "dependencies": {
            "System.Console": "4.0.0-beta-23516"
        }
    }
  }, ...
}                    

Project Lock File

Cache for package dependencies
Better performance because of significantly less disk IO

Generated when running dnu restore

Prerequisite for running dnx

locked field used to suppress dependency graph walking
dnu [ --lock | --unlock ]

Commands

Entry points with arguments (used e.g. by EF 7 and Kestrel)


{
  "dependencies": { },
  "frameworks": { ... },
  "commands": {
    "run": "myApp --target world"
  }
}                    

public static void Main(string[] args) 
{
    if (args.Length != 2 || args[0] != "--target") {
        System.Console.WriteLine("Missing parameter --target");
    } 
    else {
        System.Console.WriteLine($"Hello {args[1]}");
    }
}
                    
Details about global commands

Compilation Settings


{
  "compilationOptions": {
    "define": ["SOMETHING"],
    "allowUnsafe": true,
    "warningsAsErrors" : true,
    "languageVersion": "experimental"
  }
}
                    

Use configurations to create named groups of settings
dnu build --configuration Debug


{
  "configurations": {
    "Debug": { "compilationOptions": { ... } },
    "Release": { "compilationOptions": { ... } }
  }
}
                    

Including/Excluding Files

  • compile: What should be compiled?
  • exclude: What should be totally ignored?
  • publishExclude: What should be ignored for publishing?

{
  "compile": "*.cs",
  "exclude": [
    "node_modules",
    "bower_components"
  ],
  "publishExclude": [
    "**.xproj",
    "**.user",
    "**.vspscc"
  ]
}
                    

Use glob patterns
More details about include/exclude settings

Sharing Files

Compile code in shared directory as if it was part of the project
Note: Use internal types only


{
    "dependencies": {
        "System.Console": "4.0.0-beta-23516"
    },
    "frameworks": {
        "dnxcore50": {}
    },
    "shared": "*.cs"
}
                    

Sample on GitHub

Libraries

Projects are just folders with files in them

global.json at the top level needs the names of each project (folder name)


{
    "projects":[
        "consumer",
        "lib"
    ]
}
                    

project.json includes a reference


{
    "dependencies": {
        "lib": "",
        ...
    },
    ...
}
                    

Sample on GitHub

Creating NuGet Packages

Create NuGet package with DNU
dnu pack [ --configuration ... ]

Sample on GitHub

Package Metadata


{
    "title": ".NET Core Demo",
    "authors": [ "Rainer Stropek" ],
    "version": "1.0.0",
    "copyright": "MIT License",
    "description": "This is small sample for .NET Core",
    ...
}
                    
More details about package metadata

Script

Add scripts to project.json
Used for e.g. npm, gulp, etc.


{
  "scripts": {
    "prebuild": "executed before building",
    "postbuild": "executed after building",
    "prepack": "executed before packing",
    "postpack": "executed after packing",
    "prepublish": "executed before publish",
    "postpublish": "executed after publish",
    "prerestore": "executed before restoring packages",
    "postrestore": "executed after restoring packages",
    "prepare": "After postrestore but before prepublish"
  }
}
                    
More details about scripts

Resources

ASP.NET Fundamentals

Startup

Main in our code or in referenced assemblies
See e.g. Kestrel's Main method


public class Program
{
    public void Main(string[] args) => WebApplication.Run<Startup>(args);
}
                    

Startup class is detected based on conventions
Supports multiple environments


public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    { ... }

    public void Configure(IApplicationBuilder app)
    { ... }
}
                        

Sample on GitHub

Startup Services

During startup, application services are available
List of services


public class Startup
{
    // Note constructor injection here
    public Startup(IApplicationEnvironment appEnv, IHostingEnvironment env)
    {
        Console.WriteLine($"App name: {appEnv.ApplicationName}");
        Console.WriteLine($"Root path: {env.WebRootPath}");
    }
    ...
}
                    

Sample on GitHub

Configure and ConfigureServices


public void Configure(IApplicationBuilder app)
{
    app.Use(async (context, next) => {
        await context.Response.WriteAsync(">>> Hello ");
        await next();
        await context.Response.WriteAsync("World <<<");
    });
    app.Map("/beautiful", beautifulApp => beautifulApp.Run(
        async context => await context.Response.WriteAsync("beautiful ")));
}
                    

Note: Encapsulate complex logic in middleware
Details

Sample on GitHub

Visual Studio Demo

  • Create empty ASP.NET 5 project
    Walkthrough generated code
  • Add Microsoft.AspNet.StaticFiles dependency
    More about static files
  • Add static files middleware in Configure
  • Run in IIS with HTTP Platform Handler
  • Run with dnx web (self-hosted)
  • Publish to Azure from Visual Studio

Linux Demo with Docker

  • Connect to VM in Azure with PuTTY
  • Copy sample to VM with FileZilla
  • Get ASP.NET Docker Image
  • Start Docker container
    docker run -it -v ~/myApp:/src -p 80:5000 microsoft/aspnet /bin/bash
  • Start web app and show it in browser

dnvm install 1.0.0-rc1-update1 -r coreclr
dnvm use 1.0.0-rc1-update1 -r mono
dnu restore
dnvm use 1.0.0-rc1-update1 -r coreclr
dnx web
                    

Details about DNX on Linux
Issus about DNX on LInx

Diagnostics

Control environment with environment variables
Can be done directly in VS


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        // Running in development mode
        app.UseDeveloperExceptionPage();
        app.UseRuntimeInfoPage();
    }

    app.Use(async (context, next) =>
    {
        if (context.Request.Query.ContainsKey("exception"))
        {
            throw new InvalidOperationException("Something bad happened ...");
        }

        await next();
    });
    ...
}
                    

Sample on GitHub

Configuration

No web.config anymore

Key/value pair settings from different providers
E.g. memory, environment variables, JSON, INI, XML

Extensible
Details about writing custom providers

Options pattern for DI integration

Configuration Demo

  • In-memory configuration
  • JSON configuration
  • Configuration via command line
  • Configuration with environment variables
  • Options pattern

Sample on GitHub

See practical use in AppInsights

Logging

Support for logging built into ASP.NET Core

Various logger built in
E.g. console, NLog

Details about logging

Sample on GitHub

Dependency Injection

Support for DI built into ASP.NET Core
Details about DI

Framework-provided services and your own services

Default container can be replaced
Details


public void ConfigureServices(IServiceCollection services)
{
    ...
    // My own service
    services.AddSingleton(typeof(INameGenerator), typeof(NameGenerator));
    ...
    // Framework services
    services.AddApplicationInsightsTelemetry(configuration);
    services.AddCors();
    services.AddMvc();
    ...
}
                    

Sample on GitHub

DI Service Lifetime

  • Transient
  • Scoped
  • Singleton
  • Instance

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<MySingletonService>();
    services.AddTransient<MyTransientService>();
    services.AddScoped<MyScopedService>();
    
    services.AddMvc();
}
                    

Sample on GitHub

ASP.NET Core Demo

Build end-to-end sample app with server and client components

Sample on GitHub

Unit Testing

Test Frameworks and Runners

DNX supports/will support multiple test frameworks

Current, XUnit is preferred

Used to MSTest but new to XUnit? Compare ...

Project Setup

Create global.json referencing projects


{
    "projects":[
        "src/client",
        "src/math-library",
        "test/lib-test"
    ]
}
                    

Sample on GitHub

Writing tests

project.json


{
    "dependencies": {
        "xunit": "2.1.0",
        "xunit.runner.dnx": "2.1.0-rc1-build204",
        "math-library": ""
    },
    "frameworks": {
        "dnxcore50": {}
    },
    "commands": {
        "test": "xunit.runner.dnx"
    }
}
                    

Sample on GitHub

Writing tests


using Xunit;
namespace Tests
{
    public class TestClass
    {
        [Fact]
        public void TestAdd()
        {
            Assert.Equal(2, Library.Math.Add(1, 1));
        }
        ...
    }
}
                    

Sample on GitHub

Running tests

dnx test

Sample on GitHub

News in Visual Studio 2015 Update 1

Goto Implementation :-)

C# Scripting

Roslyn Scripting API for C#
Finally back ;-)


{
"dependencies": {
...
"Microsoft.CodeAnalysis.CSharp.Scripting": "1.1.1"
}, ...
}
                

csi.exe for running C# scripts in dev command prompt

C# Interactive Windows in VS

Sample on GitHub

Parallel Test Execution

VS2015 Update 1 can run tests in parallel on multi-core
Must be separate assemblies, distinct processes


<?xml version='1.0' encoding='utf-8'?>
<RunSettings>
<RunConfiguration>
<MaxCpuCount>8</MaxCpuCount>
</RunConfiguration>
</RunSettings>
                

Sample on GitHub

Thank you for attending!

See you next SNEK!