10-03-2017 Door: Renzo Veldkamp

The story behind new .Net features

Deel dit bericht

This is a story about three valuable Microsoft employees: Cornelius Sharp, Michael V. Coben and Webster A. Pi. They are proud of their achievements on C#, MVC and WebAPI and asked several speakers to present the latest releases of products on the Microsoft Tech Days. And I was lucky enough to be there.

The Microsoft TechDays programme covered an impressive range of topics. The sessions that caught my interest in particular centred on the following:
• Microservices (including bus technologies)
• Open-source software (Angular, JS tools)
• New .Net features (e.g. C# 7, ASP.Net MVC 6 and WebAPI 6)

In addition to the standard Microsoft fare like .Net, Azure and DevOps, the TechDays programme covered topics not specifically relating to Microsoft, like front-end technology, the IoT, SCRUM, open-source software and robotics.

To keep this column concise, it has been divided into three separately published articles. (Part one, Part two). This, the third and final part, is all about new .Net features.

Introduction

Cornelius, Michael and Webster are close friends, so they have nicknames for each other. Next to Cornelius’ front door is a sign saying ‘C. Sharp’, so Webster abbreviates this to ‘C#’. This is not entirely coincidental, as Cornelius works on the C# compiler. Cornelius and Michael call Webster Web A. Pi and – as you might have guessed – he works on WebAPI. Working on the MVC product, Michael really feels at home, because of his initials.

Each year Microsoft assigns them new targets. Last year, Cornelius had to find ways to speed up development of C# code even more, and Michael and Webster needed to find a way to build their products on .Net Core.

C# 7.0

After conceiving the string interpolation feature of C# 6.0, Cornelius came up with more ways to make writing C# code easier and faster. He asked Bart de Smet to present some of the new language features of his new release C# 7.0. Some of these new features are aimed at allowing you to make C# code more concise, like local functions, tuples and implicit declaration of out variables.

The Tuple class itself is not new (https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx), but now, in C# 7.0, declaring a Tuple has been simplified:

var tuple = (x: 3, y: 5, z: -2);

The properties of this tuple are named x, y and z. This allows you to use more descriptive names than the predefined names the Tuple elements had: .Item1, .Item2, etc. The following method is now also allowed:

(string, int, bool) GetInfo()
{
    string text = "something";
    int number = 42;
    bool really = false;

    return (theString: text, theNumber: number, theBoolean: really);
}

‘GetInfo()’ returns a tuple containing three items of different types. Its return statement can also be written without the name literals:

return (text, number, really);

Pleased with this achievement, Cornelius went on to make the next improvement, tackling the cumbersome but mandatory declaration of an uninitialized variable to be used for the out parameter in a TryParse statement. This he made a thing of the past:

bool isItAnInteger = int.TryParse(s, out int num);

Another one of Cornelius’ brainwaves for this release is the possibility of ‘nesting’ methods, using local functions.

public int IncrementTo(int numberToIncrement, int step, int finalValue)
{
    int returnNumber;

    if (finalValue <= numberToIncrement) returnNumber = finalValue;

    if (step == 0) returnNumber = finalValue;

    returnNumber = Increment(numberToIncrement);

    return returnNumber;

    int Increment(int number)
    {
        while (number < finalValue)
        {
            number = Add(number);
        }

        return number;

        int Add(int internNumber)
        {
            return iternNumber + step;
        }
    }
}

Using a local function helps to reduce the number of methods in the class and keep related code together. The local functions in the above example are the ‘Increment’ method declared inside the body of the ‘IncrementTo’ method and the ‘Add’ method inside the ‘Increment’ method. It is also permissible to call a local function before declaring it. The compiler performs an operation comparable to the ‘hoisting’ of functions in JavaScript, where the local function definition is made available before it is called for the first time. Cornelius wanted it to be known that this makes it easier to write recursive methods.

You also need to be aware of the scope of arguments: the ‘Add’ method cannot have an argument named ‘number’, because that identifier is already taken by the argument of the ‘Increment’ method. They share the same scope, as you can see by the use of the ‘finalValue’ and ‘step’ variables in the local functions. For the sake of clarity the argument is called ‘internNumber’.

Cornelius included some more goodies, like pattern matching and deconstruction, in this release. To learn more about this, you can check out the recordings of the session led by Bart de Smet.

ASP.Net Core

The three friends regularly enjoy a weekend together, going camping. On one of these trips, they sat around the campfire discussing the products they work on. Michael and Webster realised that their products had many aspects in common, but each with its own implementation. They both use HTTP-pipeline middleware for handling HTTP requests and returning appropriate responses. They both support registering dependency injection and authorisation frameworks. And they also use Controller objects containing actions for handling these HTTP requests. They decided to cooperate, so the next releases of MVC and WebAPI would use the same middleware and the same pipeline. After this improvement, they could join forces to build a version that uses the ASP.Net Core framework.

Just like the .Net Core framework contains the bare essentials for running a .Net application, ASP.Net Core contains the bare essentials for running an ASP.Net web application. The result is a smaller, more portable code base, suitable for hosting an ASP.Net web application in a container (like a Docker container), as demonstrated by Alex Thissen and Rene van Osnabrugge.

afb2_aspnetcore.png

Michael and Webster addressed the issue of the many merge conflicts in .csproj files that frequently occur when multiple developers check in their changes. This happens often at the start of a project, when multiple developers add files to the project, leading to conflicting changes in the .csproj file.

So, Webster decided to tackle this problem. Which is good news because this doesn’t happen anymore in a .Net Core solution. The .csproj (XML format) has been replaced by a project.json file that doesn’t sum up all of the files of that project; instead, all files in the project (sub)directories are assumed to be part of the project. And the choice for JSON seems natural, as it is a data format that is used often for WebAPI services. Problem solved!

(It should be noted, however, that when Michael and Webster recently released ASP.Net Core 1.1.0, this reintroduced the .csproj file. It still doesn’t sum up all the files that are part of the project, but the file format is XML again. If you have projects with a project.json file, you can convert this through a migration function.)

Michael’s new release includes a new feature called TagHelpers. Twin brothers Alex and Chris van Beek demonstrated how to use this feature. A TagHelper is comparable to an HtmlHelper. Where an HtmlHelper aids in declaring HTML elements in your view, the TagHelper helps in binding attributes of HTML elements. This allows you to add functionality to the rendering of your view by adding server-side (C#) code. It is a powerful feature that you can use, for example, to add a class to all elements in a view of your web application using just a few lines of C# code. This also works for inline style rules, but that is often not the correct way to go.

An extremely simple TagHelper:

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Threading.Tasks;

namespace CoreWebApplication1.Controllers
{
    [HtmlTargetElement("a")]
    public class ExampleTagHelper : TagHelper
    {
        public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            return Task.Run(() =>
            {
                output.Attributes.Add(new TagHelperAttribute("style", "color:hotpink;"));
                base.ProcessAsync(context, output);
            });
        }
    }
}

And adding it to the view using a single line:

@addTagHelper "CoreWebApplication1.Controllers.ExampleTagHelper, CoreWebApplication1"

will turn all hyperlink elements a bright and shiny pink.

Despite all their effort, Michael and Webster realised that a bare-bones ASP.Net Core stack has its disadvantages as well. Web applications running on IIS have a plethora of capabilities, like support for various identity providers, easy integration with Windows authentication, many extensions and the web.config transform feature.

An ASP.Net Core web app does not provide all these capabilities. If you want to use a single-sign-on mechanism based on the Windows Active Directory, your web app needs to use an IIS host. If you need to run multiple Core web apps on the same server, all using the same TCP port, you also need the IIS host for its reverse proxy functionality. That’s one of the downsides of using the ASP.Net Core stack.

The current transforms for the web.config file are based on XML transformations. A configuration file for an ASP.Net Core web app has a JSON format, so XML transformations are not applicable. There are two ways to deal with these shortcomings: write a PowerShell script that replaces the values of your settings depending on your deployment environment or use the Replace Tokens extension for TFS (https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens), or use deployment tooling like Octopus deploy (that has a feature called ‘JSON configuration variables’; 
in this blog about Octopus deploy I show how to use this feature).

Time for another camping trip!

Cornelius, Michael and Webster were satisfied with their achievements. To celebrate their success and get some rest, they went on another camping trip, where they contemplated what new features and improvements to their products they could develop over the coming year.

Disclaimer

The characters in this story are purely fictional. Any resemblance to real persons, living or dead, is entirely coincidental. The products they have worked on (C# 7, ASP.Net MVC 6 and ASP.Net WebAPI 6) are, however, real products offered by Microsoft.

Sessions

The recordings of the sessions on .Net are available on Channel9:
Bart de Smet: What's new in C# 7.0
Bart de Smet: C# Language Internals
Alex and Chris van Beek: MVC 6 Web API
Alex Thissen and René van Osnabrugge: How Docker and ASP.Net Core will change the life of a Microsoft developer

Renzo Veldkamp

Renzo Veldkamp werkt bij Centric als software-engineer in het .NET Team. Een fantastisch vak volgens Renzo, en een vak dat flink in ontwikkeling is. Want naast het leveren van een ‘werkend stukje code’, wordt er ook kennis verwacht van verschillende methodieken, zoals Scrum of DevOps en van hulpmiddelen voor testen en versiebeheer. En  verder zijn sociale vaardigheden nodig om werkzaamheden goed af te stemmen met opdrachtgever en eindgebruikers. Het leukste vindt hij om te zien hoe een applicatie in de praktijk wordt gebruikt. Als gebruikers enthousiast zijn over gebruikersgemak of efficiency levert het hem veel voldoening op.
Renzo is ook als expert actief binnen Craft, het groeiprogramma voor IT'ers (powered by Centric). Graag deelt hij binnen het Craft-programma zijn kennis en ervaring op het gebied van softwareontwikkeling, processen en sociale vaardigheden.

Alle blogs van deze auteur

Partners