.Net Core and Why it's the Future of Microsoft Development

Microsoft's latest focus is on .NET Core as the future of its development platform. What is .Net Core and how it differs from the framework.

By Tim Trott | C# ASP.Net MVC | March 7, 2016
2,607 words, estimated reading time 10 minutes.

Announced back in 2014 , .Net Core is an open source project built as a modular development stack and is the foundation of all future .NET platforms. It's already used by ASP.NET 5 and .NET Native.

.Net Core is a cross-platform open-source framework designed from the bottom up. Being open-source enables Microsoft to harness the open-source community's resources to contribute, distribute, and create add-ons and extensions. Microsoft also wanted the platform to be capable of compiling native machine code, something the.Net Framework does not support. ASP.Net 5 has been called ASP.Net Core 1.0 since the advent of.Net Core.

Getting Started with .Net Core

The easiest method of installing .NET Core on Windows is to download the official MSI installer . This installer will install the tools and add an entry to the system PATH variable. If you are using Windows 7, Windows Server 2008 or Windows Server 2012 you will also need to install Visual C++ Redistributable for Visual Studio 2012 Update 4 & Visual C++ Redistributable for Visual Studio 2015.

You should also have Visual Studio 2015+, the community edition will do.

What's Different in .Net Core?

For starters, ASP.Net Core is quite a bit different to previous versions of ASP.Net MVC, but isn't so unfamiliar as to be completely foreign. Startup.cs is now the main entry point for applications, and dependency injection is part of the native code, so no third-party libraries are required for this. Also, Web Forms have been depreciated in favour of MVC 6. There are NuGet packages to add Web Forms, but MVC is the future and support for forms will eventually be removed entirely.

The best way to see the changes is to get stuck in with a new project. As we come across the new features, I'll go through them with you. So let's get started with File > New Project. If ASP.Net has been installed correctly you should see it listed in the project templates dialogue box.

Once the new project has been created, the first thing you will notice is how different the project structure is. It's almost alien. Let's have a look at the new structure from the top down.

The first thing you'll notice is in the Solution Items folder, a file called Global.json. This file kind of replaces the project.sln file in that the compiler does not use the .sln at all, just the .json file. The solution file still exists, but it is only used by Visual Studio.

The project file, .proj, is no longer used. Instead, there is a .xproj containing the export definitions as well as a project.json. Like the global.json, project.json is used to hold all the settings for the project. The .xprj is only used by Visual Studio

If you right-click on the solution and click browse to the folder, Windows Explorer will open at the project location. You should note that the file structure matches the structure in Solution Explorer. Because the project files are structured on the disc, the project settings file no longer maintains a list of the files included in the project, fantastic news for users of source control systems! It also means that you can add files to the project by simply dragging them to the folder in Explorer, without needing to right-click "Add to Project" each time.

ASP.NET 5 Core
ASP.NET 5 Core

When looking in the solution browser you will also notice a wwwroot folder. This is the root of the web application, and only files within this folder will be served by IIS. Anything outside this folder is protected, so sensitive files such as configurations and classes are blocked from being accessed via the web.

The next special folder is called Dependencies. This is the folder for storing all the packages added to the project. More on this in a minute.

NuGet and Bower with .Net Core

NuGet is now the standard method for adding server and client-side packages to the project. For client-side packages, Bower is available to manage installations and updates of packages and libraries. NPM is also still available.

To install a client-side package, right-click on the project and select Manage Bower Packages. This will open a new window where you can click on install and browse for a package. When you install a package you will see that they have been included in the dependencies folder, but not the wwwroot. If you were paying attention, you would remember that only files in the wwwroot folder are available on the website, so how is the new package going to be accessed? This is done through the Bundling and Minification process, now part of the build procedure.

Bundling and Minification in .Net Core

If you've used bundles in previous versions, you should note that registering bundles is no longer available. Instead, use task runners Gulp and Grunt. Tasks are written in JavaScript, and control how packages are bundled together and minified.

Add a new item to the project and search for NPM. Add NPM Configuration File (package.json) This then adds the file to the project root. Open package.json for editing and you will see a simple JSON object with an empty devDependancies section. Here, list out the packages and versions used in the order that they will be added. In this example, I'm adding Gulp to minify the files.

json
{ 
  "version":"1.0.0", 
  "name":"ASP.NET", 
  "private":true, 
  "devDependancies": { 
    "gulp":"3.9.0",
    "gulp-concat":"2.5.2", 
    "gulp-cssmin":"0.1.7", 
    "gulp-uglify":"1.2.0" 
  } 
}

When you save the file, Visual Studio will download and install the packages. Within the dependencies folder, it will create a new folder called NPM where the packages will be downloaded.

Now that Gulp is installed, let's add the configuration file and set up how it minifies the project. Add a new item again, and this time search Gulp and add Gulp Configuration File. This will create a new gulpfile.js. Within this file, you can add the required statements, paths, source paths and tasks. Creating a Gulp configuration is better explained on the Gulp website. A basic configuration is shown below.

javascript
// <binding />
/*
This file in the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    cssmin = require('gulp-cssmin'),
    uglify = require('gulp-uglify');

var paths = {
    webroot: "./wwwroot/"
};

paths.bootstrapCss = "./bower_components/bootstrap/dist/css/bootstrap.css";
paths.jqueryJs = "./bower_components/jquery/dist/jquery.js";
paths.fonts = "./bower_components/font-awesome/fonts/*";

paths.jsDest = paths.webroot + "js";
paths.cssDest = paths.webroot + "css";
paths.fontDest = paths.webroot + "fonts";

gulp.task("min:js", function () {
    return gulp.src([paths.jqueryJs])
        .pipe(concat(paths.jsDest + "/min/site.min.js"))
        .pipe(uglify())
        .pipe(gulp.dest("."));
});

gulp.task("copy:js", function () {
    return gulp.src([paths.jqueryJs])
        .pipe(gulp.dest(paths.jsDest));
});

gulp.task("min:css", function () {
    return gulp.src([paths.bootstrapCss])
        .pipe(concat(paths.cssDest + "/min/site.min.css"))
        .pipe(cssmin())
        .pipe(gulp.dest("."));
});

gulp.task("copy:css", function () {
    return gulp.src([paths.bootstrapCss])
        .pipe(gulp.dest(paths.cssDest));
});

gulp.task("copy:fonts", function () {
    return gulp.src([paths.fonts])
        .pipe(gulp.dest(paths.fontDest));
});

gulp.task("min", ["min:js", "min:css"]);
gulp.task("copy", ["copy:js", "copy:css", "copy:fonts"]);

This Gulp config is pretty standard. Firstly we set a bunch of paths for the source files, and then some paths for the destination folders. We then create a bunch of tasks, with chained commands to combine multiple files into one (concat), then minify the file (uglify and cssmin) before writing the processed file out to the destination folder. There are also two tasks which copy the unminified files to the destination as well. This is useful for debugging and testing as minified files can be difficult to read.

When you have finished setting up Gulp, open up the Task Runner Explorer from View > Other Windows > Task Runner Explorer. It will automatically detect the entries from the config file and allow you to run your tasks. After this, the files will be processed and placed within the wwwroot folder. By right-clicking on a task, you can bind it to a build event, so each time you build your Visual Studio project it can automatically run the Gulp tasks selected.

String Interpolation in .Net Core

New in C# v6 is string interpolation. This is simply another method for joining strings together using String.Format in shorthand.

Previously a string concatenation may have looked like this:

C#
string mystring = string.Format("Hello {0}, today is {1}", model.FirstName, DateTime.Now.DayOfWeek);

Using interpolated strings which are prefixed with a $ and where the parameters are encased in curly braces the string now becomes:

C#
string mystring = $"Hello {model.FirstName}, today is {DateTime.Now.DayOfWeek}";

This is much easier to read and write as it follows a more natural structure. If you have many parameters then it makes matching up indexes with parameter values far easier.

Startup Class in .Net Core

The global.asax has been replaced by the start-up class located at the root of the solution. The start-up class (startup.cs) contains the main method. This is the entry point to the application. Nothing new here, all .Net applications use the main method as an entry point; however, this was hidden away in previous ASP.Net applications in the System.Web assembly, with certain methods exposed as events in global.asax. In .Net Core, you are in the driving seat and have total control over how the application is launched from within the start-up class.

The start-up class is simple, not derived from any other classes, nor does it implement any interfaces. The runtime will use this class and call two methods, ConfigureServices and Configure.

.Net Core Dependency Injection

The purpose of the ConfigureServices method in the start-up class is to configure dependency injection. In previous versions of ASP.Net, dependency injection was optional and controlled by the use of third-party plugins such as SimpleInjector. In ASP.Net Core, it is an integral part.

When an application starts up, types are registered within an IoC (Inversion of Control) container. These types are called services. Once registered, other types can ask the container for instances of that type. The container also controls the lifetime of objects. When registering a type, you can choose transient, scoped or singleton lifetimes. A transient type is created fresh each time it is requested, a scoped type exists for the duration of the web request, and a singleton type will exist throughout many requests until the application is closed.

To add a type to the container, in the ConfigureServices method simply make a call to services.AddSingleton, AddScoped or AddTransient methods, passing in the interface and classes to the type.

C#
public void ConfigureServices(IServiceCollection services)
{
  / Add all dependencies needed by Mvc.
  services.AddMvc();
    
  services.AddSingleton<ITypeRequested, ClassReturned>();
}

How A Request is Processed in .Net Core

Another method in the start-ups class is Configure. The runtime calls this method to configure the HTTP request pipeline. The pipeline configures how the application should respond to HTTP requests. When an internet browser requests the application, the request is passed along the pipeline where various actions take place. Eventually, a response is generated and returned to the browser. If there is nothing in the pipeline, nothing happens. Each action that is invoked during the pipeline is called Middleware. Examples of which are the MVC Framework, Authentication, Static Files and so on. Most of these are handled automatically for you. In previous versions, this was all handled by System.Web, however, is tied specifically to the IIS web server and violates cross-platform viability.

.Net Core Environments

Environments allow configuration of the different environments that the app can run in. These are typically Development, Staging and Production. Each environment can have its settings for database connections, file paths and even web server configuration. Environments are configured in the project Properties folder in a file called launchSettings.json.

In the start-up class, you can expose the hosting environment which you can use in your app to perform actions only based on the hosting environment. Simply add a constructor to the startup class accepting an IHostingEnvironment object and have it set a property on the class.

C#
private IHostingEnvironment _hostingEnvironment; 
 
public Startup(IHostingEnvironment hostingEnviromnent) 
{ 
  HostingEnvironment = hostingEnviromnent; 
}

Now you can address this from within the Configuration method

C#
if (_hostingEnvironment.IsDevelopment()) 
{ 
  App.UseDeveloperExceptionPage(); 
}

This will allow application error exceptions to only show when the environment is developing.

.Net Core Configuration Settings

In previous versions of ASP.Net, the configuration was handled by the web.config and XML files. This file has now been removed and is instead replaced by Environments and In .Net Core, there is a new configuration settings framework which out of the box supports In Memory, JSON, XML, INI (yes - INI is making a comeback!) and environment variables. You can extend the available sources by deriving from the ConfigurationSource class, which is optimised for dependency injection.

To create a simple JSON-based configuration setting, create a new JSON configuration file in the root, settings.json for example.

json
{ 
  "TestSetting":"This is a test setting" 
}

Next, create a folder called options, and a new class called settingsOptions.cs. Create properties within this class matching those in the JSON file.

C#
public class settingsOptions  
{ 
  Public string TestSetting { get; set; } 
}

Now in the startup class, ConfigureSources create an instance of the ConfigurationBuilder, and add the JSON file to the key-value pairs.

C#
var configBuilder = new ConfigurationBuilder() 
  .AddJsonFile("settings.json");

It is also handy to override the settings based on the environment. This can be done using an environment settings file. This is done by simply chaining another AddJsonFile to the new ConfigurationBuilder.

C#
var configBuilder = new ConfigurationBuilder() 
  .AddJsonFile("settings.json"); 
  .AddJsonFile($"settings{hostingEnvironment.EnvironmentName}.json", optional: true);

This looks for a file containing the current environment name, and it is optional, meaning if the file is not found it won't show any errors. The hostingEnvironment is the same one we used earlier. The configuration builder overrides the settings in the first file with those in the second if it is found.

When all the files are added, you can issue the command to build.

C#
var config = configurationBuilder.Build();

Then add it to the pipeline

C#
services.Configure<SettingsOptions>(config);

This will provide a SettingsOptions instance populated with the values from the JSON files to your applications.

Settings can be read using an injected IOptions class when creating the class.

C#
private SettingsOptions _options; 
public TestController 
{ 
  public TestController(IOptions<SettingsOptions> options) 
  { 
    _options = options 
  } 
 
  public string myMethod() 
  { 
    return _options.TestSetting; 
  } 
}

View Components in .Net Core

View Components are like partial views, except they have their mini controller. They live in a folder called ViewComponents and inherit from a class called, surprisingly, ViewComponents.

C#
public class SampleViewComponent: ViewComponent 
{ 
  IViewComponentResult Invoke() 
  { 
    return "This is a test"; 
  } 
}

MVC expects the view to be in a folder within the Components folder, usually contained in the Shared folder since they are intended to be reused. When naming the view folder, take the controller name, minus ViewComponent. In this example the folder is Views/Shared/Components/Sample. Create a view called Default.cshtml.

The view should be strongly typed to match the controller model.

View Components can be included on pages using the following syntax:

C#
@Component.Invoke("Sample")

Fin.

And that's an introduction to the new Microsoft .Net Core 1.0. Over time I'll be adding more tutorials to this series to cover aspects in more depth. For now, download .Net Core, install Visual Studio and start playing with it!

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 2 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. NP

    On Wednesday 18th of April 2018, Nikhil Pande said

    Good explanataion about .NET core; helpful to understand the technology.

  2. JI

    On Friday 20th of May 2016, Jiping said

    Great introduction, thanks for you work.