transitioning to net core on red hat enterprise linux pdf pdf

  

Programming

  Transitioning to .NET Core on Red Hat Enterprise Linux Don Schenck

  Transitioning to .NET Core on Red Hat Enterprise Linux

  by Don Schenck Copyright © 2017 O’Reilly Media. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles ( . For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com.

  Editors: Nan Barber and Susan Conant Production Editor: Melanie Yarbrough Copyeditor: Gillian McGarvey Proofreader: Jasmine Kwityn Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Rebecca Demarest

  September 2016: First Edition

  Revision History for the First Edition

  2016-09-20: First Release 2016-10-21: Second Release 2016-12-06: Third Release

  The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Transitioning to .NET Core on

  Red Hat Enterprise Linux, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc.

  While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights. 978-1-491-97055-3 [LSI]

  What to Expect from This Book

  This book is targeted at—but not limited to—.NET developers with any level of experience. Starting with a basic “Hello World” console application, it moves along through ASP.NET, MVC, and Entity Framework applications, eventually arriving at a full-featured application running in a Linux container. Because the code in this book is limited to C#, your existing knowledge of .NET and C# will largely determine the speed at which you progress through this volume. More experienced developers will be interested in the few key differences when developing for Linux (and there are quite a few), whereas beginning developers can use this book to learn more advanced programming techniques—the fact that those techniques are related to .NET Core is just icing on the cake.

  If you’ve spent most of your time writing code in a language other than C#, with Linux as your native operating system, don’t fret. Though knowledge of C# is highly recommended, even a novice developer with a desire to learn can use this volume, perhaps in concert with another manual that guides the reader in C# development.

  Some Assumptions

  This book assumes some previous experience with the .NET Framework. Again, while it’s technically not necessary to have prior knowledge when you begin reading, you will need to be familiar with .NET (either by experience or education) to understand what’s happening. Again, not to worry—the knowledge needed isn’t as deep as you might fear. Grasp a few key concepts and you’ll be good to go. For the purposes of simplicity, the Linux distribution used in the examples will be Red Hat Enterprise Linux (RHEL). Any adjustments necessary for other Linux distributions will be pointed out as we go.

  Your Environment

  To follow along with the narrative and code, you need to install the Red Hat Container Development Kit (CDK) and clone or download a repository from GitHub. Step-by-step instructions are provided in

Chapter 1 . Formatting The following typographical conventions are used in this book: Text will be in the typeface you are reading now.

  // Code is formatted like this:

  using System ; namespace ConsoleApplication { public class Program

  { public static void Main ( string [] args )

  { Console . WriteLine ( "Hello World!" );

  } } } Command-line commands will be shown like this

  Italic Indicates new terms, URLs, email addresses, filenames, and file extensions.

  Constant width Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.

  Constant width bold Shows commands or other text that should be typed literally by the user.

  Constant width italic Shows text that should be replaced with user-supplied values or by values determined by context.

  

TIP

This element signifies a tip or suggestion.

  

NOTE

This element signifies a general note.

  

WARNING

This element indicates a warning or caution.

  .NET Core Is the Future

  In November 2014, Microsoft announced that the .NET Framework would be transitioned to an open source development model. This announcement was met with surprise and open arms by the .NET community. Although Microsoft had, up to that moment, done an admirable job of soliciting input from developers about .NET features and bugs, making the source available meant a much higher level of engagement. The standard open source model of using a GitHub repo—with issues, milestones, pull requests, and the related discussions—meant that anyone, anywhere could have instant and transparent access to the development team. Developers could participate in discussions and research defects and workarounds. Schedules and roadmaps would now be available to everyone, leading to more realistic expectations. Surprise announcements would give way to planned milestones. Meanwhile, developers outside the .NET world saw this as an opportunity to bring their open source experience and knowledge to one of the more pervasive software development platforms. The free exchange of ideas, code reviews, and sense of community found its place inside the Microsoft-centric developer’s world. The infusion of non-.NET developers meant that “dot netters” could gain a broader view of development in general. This is a very good thing. This is the new model. This is the future. .NET Core is not just another .NET Framework. Rather, it is the future of .NET. Microsoft has stated that the previous framework, 4.6.1, will still be supported, and bug fixes will be applied, but any new .NET features will be reserved for .NET Core. Using .NET Core as your basis for future work is in line with Microsoft’s stated intentions. While migrating existing code to .NET Core may or may not be a good idea, future development should be based on .NET Core if possible. In short, this is the .NET Framework. Period. Full stop.

  What’s Missing

  Because some parts of .NET are either specific to Windows or outdated, not everything made the journey from proprietary software to the open source model and .NET Core 1.0. Here’s a list of some of the things that didn’t make the transition:

  MWF (Windows Forms) Web forms WCF (SOAP)

  In addition, some things haven’t been ported yet—perhaps the biggest being SignalR. Microsoft has publicly stated that SignalR will be ported to .NET Core.

  

NOTE From this point on, unless the difference is worth noting, references to .NET CoreCLR, CoreFX, and the like, will be simplified to “.NET”.

  What’s New

  .NET is more modular now, which is a definite benefit from starting over when designing the framework. Parts that were previously included by default are now excluded by default. Even what may seem to be the most basic items, such as the ability to render static files in an ASP.NET page, are now optional. This means that you need to be more expressive in your coding, but it also results in performance improvements. The trade-off is worth the cost: writing code is easier than optimizing code.

Chapter 1. Setting Up Your Environment

  This chapter will guide you through setting up the environment used in the examples in this book. It includes a Linux Virtual Machine (VM) running on a Windows 10 machine, and a clone or download of a GitHub repository (repo). The VM in this setup will use the Red Hat Container Development Kit (CDK), which includes an image of Red Hat Enterprise Linux (RHEL), Oracle’s Virtual Box, and Vagrant.

  Your Red Hat Account

  

  

out of

the Red Hat Developers newsletter if you wish, but I suggest keeping it—at least initially.

  This gives you access to all the tools and help, including the CDK (with RHEL), forums, knowledge base, and more. Keep your username and password handy; you’ll need them every time you start your VM in order to register with Red Hat and enable your subscription.

  Installing the CDK

  The Red Hat CDK includes a copy of RHEL 7 that’s been preloaded with the docker command and OpenShift. It runs the RHEL VM using Vagrant and Virtual Box. Fortunately, if you’re not familiar with these technologies, the CDK makes the process of installing them transparent. Basically, you download, install, and run.

  Once you’ve registered and logged in, select the TECHNOLOGIES menu and the Red Hat Container Development Kit option, as shown in

  Figure 1-1. Select Red Hat Container Development Kit This takes you to the Container Development Kit page.

  At the top, click the GET STARTED button to reveal your choice of Windows or Mac/Linux assets. From there, simply follow the screen prompts to download the CDK, as shown in

  

Figure 1-2. Container Development Kit download page

  After the CDK installer is downloaded (the installer is development-suite-1.0.0-GA-bundle-

  installer.exe, which is about 1.4 GB in size), open it and follow the prompts to install the CDK on

  your Windows machine. You’ll need your Red Hat username and password to get started, as you can see in .

  

Figure 1-3. Sign in to start the CDK installation

  Disable Hyper-V

  Before you can use Vagrant, you’ll need to disable Hyper-V on your Windows machine. Use the Windows Features Control Panel applet to do this, as shown in

  

Figure 1-4. Disable Hyper-V

  

  Start Your VM

  Now that you’ve installed everything, you can start the VM. Assuming that you used the default values during the installation, open a command prompt, navigate to the proper folder, and launch the VM using the vagrant up command:

  PS C:\DevelopmentSuite\cdk\components\rhel\rhel-ose> vagrant up Bringing machine 'default' up with 'virtualbox' provider... ==> default: Clearing any previously set forwarded ports... ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configurat... default: Adapter 1: nat default: Adapter 2: hostonly ==> default: Forwarding ports... default: 22 => 2222 (adapter 1) ==> default: Running 'pre-boot' VM customizations... ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant

  default: SSH auth method: password default: Warning: Connection timeout. Retrying... default: Warning: Remote connection disconnect. Retrying... ==> default: Machine booted and ready! ==> default: Registering box with vagrant-registration... default: Would you like to register the system now (defau... ​ default: username: **redacted** default: password: [default] GuestAdditions 5.0.26 running --- OK. ==> default: Checking for guest additions in VM... ==> default: Configuring and enabling network interfaces... ==> default: Copying TLS certificates to C:/DevelopmentSuite/... ==> default: Rsyncing folder: /cygdrive/c/DevelopmentSuite/cdk/... ==> default: Mounting SMB shared folders... default: C:/shared => /shared ==> default: Machine already provisioned. Run `vagrant provis...

  ==> default: flag to force provisioning. Provisioners marked... ==> default: Running provisioner: shell... default: Running: inline script ==> default: Running provisioner: shell... default: Running: inline script ==> default: ==> default: Successfully started and provisioned VM with 2... ==> default: To modify the number of cores and/or available... ==> default: VM_CPU respectively VM_MEMORY. ==> default: You can now access the OpenShift console on: https... ==> default: ==> default: To use OpenShift CLI, run: ==> default: $ vagrant ssh ==> default: $ oc login 10.1.2.2:8443 ==> default: ==> default: Configured users are (<username>/<password>): ==> default: openshift-dev/devel ==> default: admin/admin ==> default: ==> default: If you have the oc client library on your host,...

  PS C:\DevelopmentSuite\cdk\components\rhel\rhel-ose>

RUN AS ADMINISTRATOR

  

Get in the habit of opening the command prompt—I suggest using PowerShell—by using the “Run as Administrator” option

because you’ll need administrator privileges later when you are editing and debugging from Windows.

  Now you can use ssh to get into the VM. The easiest option is to use the vagrant ssh command, which will open an ssh session inside the VM, as shown in .

  

Figure 1-5. Using vagrant SSH to start a bash session on the VM

At this point, the VM is set up and running and you’re ready to begin your transition to .NET on Linux.

  Getting the Source Code

  Once you are inside the VM, you can go ahead and fetch the source code associated with this book. You can do this by running the following command:

  git clone https://github.com/donschenck/NetOnLinuxBook You’ll now have a directory, NetOnLinuxBook, that contains subdirectories for this book.

  NOTE When applicable, at the beginning of each chapter, you will see a note directing you to the source code from the repo that is associated with that chapter.

Chapter 2. Getting Started: From Zero to

  “Hello World” in One Chapter From Zero to “Hello World” in One Chapter

  One of the benefits of .NET Core is the ability to get a simple console application up and running in a matter of seconds. While more complex applications require a deeper understanding of the framework and the language (C#, in our case), the building and execution of a simple “Hello World” application can be done with very little effort. This chapter will get you up and running in one quick session.

  

ASSOCIATED SOURCE CODE

The source code can be found in the /NetOnLinuxBook/HelloWorld/ directory.

  Overview of .NET

  When Microsoft introduced the .NET Framework in 2002, it marked a new era in software development for Microsoft-centric developers. The move marked a shift in thinking, allowing Windows Forms developers to create websites in a way that was somewhat familiar. Dragging text areas and buttons onto a form and adding code-behind code made the transition almost seamless, if somewhat unconventional. In fact, it was sometimes referred to as “Windows for the Web.” Fast-forward 12 years, and Microsoft announces that .NET will be open source. It now supports MVC, ORM, CSS, and every other TLA (three-letter acronym) one can imagine.

  What happened? In short, as has been said, “Open source won.” With the fight over, Microsoft has pivoted quickly and is now releasing pieces of the .NET framework at a much faster pace, with thousands of developers from all over the world contributing.

  In November 2015, when Microsoft and Red Hat announced a partnership (to replace an adversarial relationship), it became clear that .NET was not only moving into the world of open source but that being able to run .NET programs on Linux—with the full blessings and support of Microsoft and Red Hat—was actually going to happen.

  And that’s where we find ourselves today, with both Microsoft and Red Hat embracing Linux and .NET. As a developer, you have the opportunity to widen your skillset and marketplace. There’s no time to get started.

  Installing .NET

  Installing the framework is easier and quicker than ever; that’s because it’s been separated into small layers. It’s helpful to understand these layers of .NET. Each layer exists separately from the other and evolves at a different pace. Each has a separate code base and GitHub repo, as shown in .

  

Figure 2-1. The layers of the new world of .NET

.NET CLR

  This is where the Common Language Runtime (CoreCLR) lives. It includes the garbage collector, the Just-In-Time (JIT) compiler, base data types, and some low-level classes.

  .NET CoreFX

  The System.* and Microsoft.* libraries that run on .NET Core and enable you to run your applications. When you type using System.<foo> in your program, you are accessing the libraries at this level. CoreFX includes classes for collections (System.Collections), filesystems (System.IO),

  XML (System.Xml), asynchronous processing (System.Threading), and more. You can see the entire list of libraries at . At this level, basic console applications (such as the ubiquitous “Hello World” app) can run.

  .NET CLI

  The command-line interface, which allows you to build and launch your applications. Compiling programs, pulling NuGet packages, running tests, running your applications—all these tasks use the dotnet CLI. As a developer, you’ll likely spend a great deal of time here or use an IDE that leverages the CLI.

  ASP.NET Core

  These are the libraries that allow you to write web services and websites. Because it is totally modular, ASP.NET Core allows you to include only the pieces you need—for example, running a static website—while excluding the bits you don’t need. This reduces size, increases performance, and makes deployment faster.

  Tooling

  Any tools that make your life easier as a developer—whether they are a part of Visual Studio or Visual Studio Code, or other tools (such as yeoman)—reside at this level. This level is not only optional, but tools may or may not be available depending on your operating system and toolset.

  Whereas in the beginning, .NET development tools from Microsoft were tightly coupled with the framework and Visual Studio, now they are totally separate (this has actually been the case since 2008).

  

HELP, I DON’T REALLY KNOW LINUX THAT WELL!

New to Linux? That’s OK; we all were at one point in our lives. Don’t fret—you can download a free Linux Cheat Sheet

at .

  Installation Instructions

  Assuming you have a Red Hat Enterprise Linux 7 subscription, follow these instructions to install .NET Core. Note that you will need administrator privileges to perform the installation:

  sudo subscription-manager list --available

  This displays a list of all available subscriptions. Near the end of the listing, a Pool ID is revealed, as in this example output shown in .

  

Figure 2-2. subscription-manager list --available output showing Pool ID

  Using the Pool ID, run the following command:

  sudo subscription-manager attach --pool = <Pool ID>

  Now you can enable the package and perform the installation:

  sudo subscription-manager repos

  • enable = rhel-7-server-dotnet-rpms sudo yum install -y scl-utils sudo yum install -y rh-dotnetcore10

  Finally, to make the framework available to your command line, use the following command, which will enable the framework in a new bash session:

  sudo scl enable rh-dotnetcore10 bash

  Every time you open a bash session in the VM, you’ll need to run the this command. Not only is this a nuisance, but it won’t work if you wish to debug your code from within Visual Studio. To avoid this issue, add the following line to the file ~/.bashrc in your VM:

  source scl_source enable rh-dotnetcore10

  This will download and install the latest RHEL-approved .NET Core distribution and make it available. You can verify your installation (and see what version you are using) by using the version command:

  dotnet --version Other Linux Distros The easiest way to install on other distros is to visit and follow the screen prompts.

  

WHAT IF I DON’T HAVE RHEL?

  If you don’t have a machine running RHEL, or if you’d like to create a Virtual Machine on your

  

  

  recommend grabbing and installing the Container Development Kit (CDK). You can use it later when working with Linux containers.

  Keeping Current To keep up to date with the progress of .NET, visit Your First .NET Application on Linux

  Be prepared to be underwhelmed. Creating your first .NET application, the standard “Hello World” application, on Linux involves only three steps (five if you include creating a directory and moving into it). Actually, the creation of the source code is only one command:

  mkdir helloworld cd helloworld dotnet new dotnet restore dotnet run

  Putting it all together should yield something like the following (the output is included in this snippet):

  $ mkdir hw $ cd hw $ dotnet new Created new C# project in /home/vagrant/src/hw. $ dotnet restore log : Restoring packages for /home/vagrant/src/hw/project.j... log : Writing lock file to disk. Path: /home/vagrant/src/hw/project.lock.json log : /home/vagrant/src/hw/project.json log : Restore completed in 809ms. $ dotnet run Project hw (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing Compiling hw for .NETCoreApp,Version=v1.0 Compilation succeeded.

0 Warning(s)

  0 Error(s) Time elapsed 00:00:01.0233055 Hello World! $

  

Microsoft has promised that support for F# and Visual Basic is coming. In fact, you can go ahead and run dotnet new --

lang F# now and see what happens.

  We’ll cover the commands later, but first let’s take a look at what was generated by the dotnet new command:

  $ ls -l total 8

  • rwxrw-r--. 1 vagrant vagrant 202 Jun 15 14:43 Program.cs
  • rwxrw-r--. 1 vagrant vagrant 348 Jun 15 14:43 project.json $

  What just happened? Where did this code come from, what does it look like, and why doesn’t your directory look like this? We’ll cover that in

Chapter 3. Diving into the “Hello World”

  Application In Chapter 1, we installed .NET and easily created, built, and ran the “Hello World” application.

  Let’s take a look at what happened when we built and ran our “Hello World” application (although you and I both know you’ve already looked inside all the generated files).

  

ASSOCIATED SOURCE CODE

The source code can be found in the /NetOnLinuxBook/HelloWorld/.

  We started by running the dotnet new command. Confession time: in fact, we skipped a command. After running dotnet restore, you can run the dotnet build command to build the binary output. We skipped it in the interest of brevity, and in fact when you execute dotnet run, the command will check to see if a new build is required and run the build automatically. We’ll cover dotnet build later in this chapter.

  The dotnet new Command

  The dotnet new command will create a new .NET project with the minimum amount of code and associated files necessary to run the application. When run without any additional options, it will create the “Hello World” console application. In this case, two files are created—Program.cs and

  project.json: $ ls -altr total 8

  • rwxrw-r--. 1 vagrant vagrant 348 Jun 15 14:43 project.json
  • rwxrw-r--. 1 vagrant vagrant 202 Jun 15 14:43 Program.cs drwxrwxr-x. 3 vagrant vagrant 23 Jul 8 11:24 .. drwxrwxr-x. 2 vagrant vagrant 42 Jul 8 11:25 .

  Program.cs is the program, and it’s short and sweet: using System

  ; namespace ConsoleApplication { public class Program

  { public static void Main ( string [] args )

  {

  } } }

  The result is obvious; an app that writes “Hello World” to the console. Just for fun, let’s change it to say “Hello from Linux” (or whatever you please), then run the dotnet run command again:

  $ dotnet run Project hw (.NETCoreApp,Version=v1.0) will be compiled because ​ inputs were modified Compiling hw for .NETCoreApp,Version=v1.0Compilation succeeded.

0 Warning(s)

  0 Error(s) Time elapsed 00:00:00.8371978 Hello from Linux $

  Notice the message from the compiler. Even though we requested the program to run and didn’t

  

  specifically ask for a compile, the dotnet CLI recognized the change in the source cnd automatically invoked the compiler (i.e., dotnet build). If you run dotnet build now, you’ll see that the compile is not done. Then why use dotnet build at all? Because you need it in your continuous integration/continuous deployment (CI/CD) pipeline.

  The dotnet restore Command

  After we ran dotnet new, we used the dotnet restore command. What does that do? It’s a package manager, similar to how one would use npm when working in Node.js, or pip when working in Python.

  The dotnet restore command pulls the dependency libraries, which are listed in the file project.json, from then fact, the location is found inside the file

  

~/.nuget/NuGet/NuGet.Config. This file is created the first time you run the dotnet restore command.

  You can edit the NuGet.Config file, adding your own repositories if you wish. For example, you may have a repository of company-standard libraries stored within your local network or a remote server (i.e., the cloud). Likewise, you can remove the reference to NuGet.org. Additionally, if you want to live on the bleeding edge, you can use the NuGet.Config file to access daily builds in MyGet.org.

  In addition to the default NuGet.Config file location, the restore command will automatically use a

  NuGet.Config file that is in your project’s root directory. For example, if your project is in the

  directory ~/src/web, and you have a file ~/src/web/NuGet.Config, it will automatically be used. It

  Finally, you can specify a NuGet.Config file at any location by using the --configfile option of the dotnet restore command. When you do this, be aware that the default configuration file is not used.

  What Gets Restored? A look inside the file project.json reveals which libraries are restored when running dotnet restore.

  In our case, there are no libraries listed, so none need to be restored:

  { "version": "1.0.0-*", "buildOptions": { "debugType": "portable", "emitEntryPoint": true }, "dependencies": {}, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0" } }, "imports": "dnxcore50" } } }

  (The other sections of the project.json file will be discussed later.) Compare the previous section to the following partial dependencies section of a project.json that requires several dependencies:

  "dependencies": { "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0-*", "Microsoft.AspNetCore.Authentication.Facebook": "1.0.0-*", "Microsoft.AspNetCore.Authentication.Google": "1.0.0-*", "Microsoft.AspNetCore.Authentication.MicrosoftAccount": "1.0.0-*", "Microsoft.AspNetCore.Authentication.OpenIdConnect": "1.0.0-*", "Microsoft.AspNetCore.Authentication.Twitter": "1.0.0-*", "Microsoft.AspNetCore.Diagnostics": "1.0.0-*", "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0-*", "Microsoft.AspNetCore.Http.Abstractions":"1.0.0-*", "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0-*", "Microsoft.AspNetCore.Mvc": "1.0.0-*", "Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0-*", "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-*", "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*", "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0-*", }, This project.json file represents an ASP.NET MVC application that uses the Entity Framework with SQL Server. As you can see from this list, each component must explicitly be included in the “dependencies” section. Later, you’ll see that you must also write code to include these bits. This modular approach is a welcome change to .NET.

  

NOTE

This project.json file is purposely not a good example. This will be explained in .

  Where Do the Dependencies Go?

  When you run dotnet restore, the DLLs are stored in the location specified by the environment variable DOTNET_PACKAGES. If this variable is not set, the libraries are placed in

  ~/.nuget/packages/.

  When you restore the dependency libraries, a new file that contains a list of your dependencies is created. This is needed to build your application.

  $ ls -altr total 288 -rwxrw-r--. 1 vagrant vagrant 348 Jun 15 14:43 project.json -rwxrw-r--. 1 vagrant vagrant 202 Jun 15 14:43 Program.cs drwxrwxr-x. 3 vagrant vagrant

  23 Jul 8 11:24 .. drwxrwxr-x. 2 vagrant vagrant

  66 Jul 8 11:27 .

  • rwxrw-r--. 1 vagrant vagrant 283663 Jul

  8 11:27 project.lock.json

  The new file, project.lock.json, ensure that your dependencies are fixed to a moment in time—the moment you ran dotnet restore. Note that if you alter your project.json file and run dotnet restore again, the lock file will be updated. A peak inside the project.lock.json file reveals not only the dependencies you listed, but their dependencies as well.

  But which version of any particular library is restored? In the previous sample, the version numbers “1.0.0*” are used. What does that mean?

  Library Versioning in project.json

  In the previous example from a project.json file, a splat string (*) is used to designate which version of a library should be used. The splat is a wildcard that tells dotnet “use this version or any version following,” which is a greater-than-or-equals situation. This is not a good idea because it could result in restoring different versions from different builds. Because some parts of .NET Core may have more advanced versions, it could result in incompatible packages being restored.

  In short, you should fix your versions, such as in the following example:

  "Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0"

  Using this technique, you not only fix your dependencies for a moment in time, but at a particular version. This is a best practice. If you are using an IDE such as Visual Studio or Visual Studio Code, IntelliSense will guide you to select the most current version.

  What Gets Built?

  When you run dotnet build, what gets built? What happens? Staying within our “Hello World” application and using the default project.json file, the dotnet build command will produce a library at the following location:

  ./bin/<configuration>/<framework>/<binary name>.

  In our case, that will be ./bin/Debug/netcoreapp1.0/helloworld.dll. When you use the run command, it finds the library in the /bin.. directory and runs it. You can change this behavior by using the --project option on the dotnet run command and explicitly telling dotnet to use a library. Consider the following example:

  mkdir ~/apps/helloworld dotnet build --framework netcoreapp1.0

  • output ~/apps/helloworld/ dotnet run --project ~/apps/helloworld.dll

  This DLL is a .NET portable app, meaning you can run it on any platform that has .NET Core

  

installed. Yes, you can literally put the library on a thumb drive and run it on OS X and/or Windows

without any changes.

  You can also build self-contained applications for Windows and OS X. In the next chapter, we’ll create a web application: an ASP.NET MVC application.

1 The dotnet CLI has a model of inputs and outputs, and checks that for each output all of the inputs are older. If any of the inputs are newer, it needs to rebuild.

Chapter 4. “Hello World” for the Web

  Now that we’ve successfully created the “Hello World” console application, let’s take the same idea and create a simple “Hello World” application for a browser. To do that, we first need to install ... nothing more. No web server, no IIS...nothing. Why is that? Because in .NET Core, a web app is a console app. That’s right—you start it from the command line and shut it down with Ctrl-C, just like any continuously running console application. How do web pages get served? Introducing: Kestrel. In the natural world, a kestrel is a small falcon that is built for speed. Likewise, the Kestrel web server is built for speed, with non-reviewed benchmarks coming in at 5.2 million requests per second, eight times faster than Node.js and four times faster then Go. That’s flying!

  

ASSOCIATED SOURCE CODE

The source code can be found in the /NetOnLinuxBook/HelloWeb/ directory.

  The Kestrel Web Server

  So how do you access this speedy server? If you don’t install anything, what do you need to do? Let’s take a look. Start by forking and cloning (or downloading) the code at and move into the HelloWeb directory. Viewing the contents, we immediately notice a few things:

  $ ls -altr total 336 drwxrwxr-x. 8 vagrant vagrant 4096 Jul 9 09:49 ..

  • rwxrw-r--. 1 vagrant vagrant 327085 Jul 9 09:50 project.lock.json drwxrwxr-x.

  3 vagrant vagrant

  18 Jul 9 09:53 obj drwxrwxr-x. 3 vagrant vagrant

  18 Jul 9 09:53 bin -rw-rw-r--. 1 vagrant vagrant 444 Jul 9 09:53 project.json -rw-rw-r--. 1 vagrant vagrant 502 Jul 9 10:30 Program.cs -rw-rw-r--. 1 vagrant vagrant 421 Jul 9 10:30 Startup.cs drwxrwxr-x. 4 vagrant vagrant 103 Jul 9 10:32 . Where is wwwroot? Where is web.config? Where is everything? Relax—everything we need is here. Because of the new modular programming model for .NET, everything we need is in code. Let’s start by taking a look at the project.json file because we know that’s where the bits get installed:

  { "buildOptions" : { "emitEntryPoint"

  : true

  , "debugType" : "portable"

  }, "dependencies"

  : { "Microsoft.NETCore.App" : { "type" : "platform" ,

  "version" : "1.0.0" }, "Microsoft.AspNetCore.Server.IISIntegration" : "1.0.0" , "Microsoft.AspNetCore.Server.Kestrel" : "1.0.0"

  }, "frameworks"

  : { "netcoreapp1.0" : { } }

  }

PRO TIP: MASTER THE PROJECT.JSON FILE

  If you want to be a master with .NET Core, no matter what the platform, you want to master the

  

project.json file. Top skill in this area will go a long way toward understanding your builds and

reducing the size of your applications.

  Microsoft has hinted that project.json will play a much smaller role in the future, but the knowledge will still be applicable, even if these settings are stored somewhere else (*.csproj file, for example). Get started by visiting .

  The project.json File

  Starting at the top and working our way down, let’s take a closer look at each line and what it represents: "buildOptions"

  (This was "compilationOptions" until shortly before the release of .NET Core, so if you encounter that in a project file, you can change it.) Just as you might expect, these options are enforced when building the application.

  If true, the build will create an executable. Otherwise, a DLL will be built. "dependencies" This is where you keep a list of the dependencies (libraries/DLLs) that are needed by the project.

  The name of the dependency is followed by version information. "Microsoft.NETCore.App"

  An example of a dependency. In this case, a set of .NET APIs that are part of the .NET Core

  

  "type": "platform" This defines when you will need this dependency. The value "platform" means you expect this dependency (in our case, Microsoft.NETCore.App) to be available on the platform on which your application will run. In other words, it is part of the environment and not part of your application. The value "build" means the library or libraries must be available during the build phase of your application, and they will be included with your application. They do not need to be previously installed on the machine where your app will run.

  "version": "1.0.0" The server version of the dependency you are using/installing. If you’re using an IDE to edit your program, IntelliSense will prompt you. Or, you can find the appropriate page on NuGet.org and see the version history.

  “Microsoft.AspNetCore.Server.IISIntegration”: “1.0.0”

  These are the components needed to work with the IIS module. In our example, using Kestrel in Linux, we don’t need this. However, if we remove it, we get the following error when building our application:

  Startup.cs(4,28): error CS0234: The type or namespace name 'HttpOverrides' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?)

  Line 4 of Startup.cs reads as follows:

  using Microsoft.AspNetCore.HttpOverrides ;

  If we look at the Microsoft.AspNetCore.Server.IISIntegration page at nuget.org, we can see that one of the dependencies for this library is "Microsoft.AspNetCore.HttpOverrides". Because we don’t need all of the IIS integration bits, we can remove the reference in our project.json file.

  “Microsoft.AspNetCore.HttpOverrides”:" 1.0.0”

  Not only does this work but this is a perfect example of the modularity of .NET and how you can select only those bits you need. This lowers memory usage and improves performance.

  “Microsoft.AspNetCore.Server.Kestrel”: “1.0.0” This gives us the Kestrel web server. “frameworks”: “netcoreapp1.0”

  Defines the framework(s) you are targeting. Perhaps more useful, you can use this section to “lie” to the compiler, allowing you to include libraries that were written for your framework but that are, in fact, compatible. In other words, if you need a library that is targeted at Portable Framework 4.5 and Windows 8, you can add an “options” section to the frameworks, such as the following:

  "frameworks" : { "netcoreapp1.0" : { "imports"

  : "portable-net45+win8" } } A full explanation of all the project.json file values can be found at the .

  Program.cs: Where the Magic Happens

  With a better grasp of the project.json file, let’s look at another change. Opening the file Program.cs, the newness continues:

  // HelloWeb using System.IO ; using Microsoft.AspNetCore.Hosting

  ; using Microsoft.AspNetCore.Builder ; namespace HelloWeb { public class Program

  { public static void Main ( string [] args )

  { var host = new WebHostBuilder ()

  . UseKestrel () . UseContentRoot ( Directory . GetCurrentDirectory ()) . UseStartup < Startup >(). UseUrls ( "http://*:5000" ) . Build (); host . Run ();

  }

  }

  Looking at the source code, you see how the web server is built in code rather than specified in one or more configuration files. Certainly, you can (and should and will) store settings in configuration files, but the task of creating a web server is now on the developer in code, not on the framework via configuration.

  Notice we are using Kestrel, the web server. The ".UseContentRoot" function sets where the web server starts looking for content. Using the current directory is simple, but you can obviously change this for, say, security reasons. The .UseStartup function is a dependency injection point, where you specify the name of the startup library. The .UseUrls() function tells the web server which address and port to watch.

  The host.Run() function launches the web server. Because this is a console app, you can observe what’s happening simply by watching the stdout (i.e., the messages to the console). Simply run the dotnet run command and watch Kestrel take over, as shown in .

  

Figure 4-1. Results of HelloWeb

“I’M RUNNING RHEL IN A VM, AND LOCALHOST:5000 DOESN’T WORK!”

  If you are running RHEL inside a VM on your PC (or Mac), you won’t be able to access the website from your PC desktop. That’s because localhost inside your VM is referring to just the

  VM, and not the host (your PC). If you are running a UI on your VM (e.g., Gnome), you can open the browser in your VM and see the website.

  If you’re running your VM as a text interface (i.e., just the console), you’ll need to modify the generated code to make it visible to your host. In your VM, open the file Program.cs and change the .UseStartup line to read as follows:

  . UseStartup < Startup >() UseUrls ( "http://*:5000" ) This allows your website to be reached from outside of the VM. Save the change and use the dotnet run command to start the application; you’ll then be able to view the website at the IP address (and port 5000) of your VM. If you are using the Red Hat CDK, this is 10.1.2.2:5000.

  To see where the web server does its work, look inside Startup.cs:

  // Startup.cs using Microsoft.AspNetCore.Builder

  ; using Microsoft.AspNetCore.Hosting ; using Microsoft.AspNetCore.Http ; using Microsoft.AspNetCore.HttpOverrides ; namespace HelloWeb { public class Startup

  { public void

  Configure (

  IApplicationBuilder app ) { app . Run ( context =>

  { return context . Response . WriteAsync (

  "Hello World Wide Web!" ); }); } } }

  As you can see, when this Startup class is executed, it asynchronously returns a response. Very simply, it sends the “Hello World Wide Web!” response. Because this is not an MVC application, there is no routing or filtering—there’s only a simple response. This is a minimal web application. It doesn’t support MVC or static content. In the next chapter, we’ll create and examine an ASP.NET MVC application.

Chapter 5. ASP.NET and MVC

  At this point, we know how to create a basic web application in .NET Core. We know how to pull down the bits we need (the dependencies), where everything goes, and how to build a portable app. We can run the web app and see it in a browser. In this chapter, we’ll learn how to create an ASP.NET MVC web app—a bit more complicated and closer to what you’ll work with in the wild.

  There is no source code associated with this chapter; you’ll be creating it.

  Creating a Basic MVC Web Application

  We’ll start by creating a directory, moving into it, and then creating an MVC web application. This is done by introducing a new option to the dotnet new command—the --type web option:

  mkdir ~/mvc cd ~/mvc dotnet new --type web