Friday, September 13, 2019

Principled GraphQL

In case you didn’t notice it yet, I’m a big fan of GraphQL. It solves so many problems when dealing with an ever growing list of devices and (micro)services.

The people who created Apollo distilled their experiences into a set of best practices for creating, maintaining, and operating a data graph.

INTEGRITY PRINCIPLES
AGILITY PRINCIPLES
OPERATIONS PRINCIPLES

A must read for every GraphQL enthousiast!

    Thursday, September 12, 2019

    ElasticSearch - Exposing your ElasticSearch instance

    ElasticSearch is safe out-of-the-box. If you do a new installation, your ElasticSearch instance is only listening to internal traffic. If you want to make the ElasticSearch API’s accessible outside the VM where you installed it, you have to take some extra steps:

    • Go to the ElasticSearch folder that you configured to store your index and configuration data.
    • Open the ElasticSearch.yml file inside the config folder.
    • Set the network.host value to a non-loopback address. I’ll use 0.0.0.0 but a specific IP address is of course better:

    network.host: 0.0.0.0

    If you know restart your ElasticSearch instance, you’ll notice that we are not there yet. The node fails to start with the following error message:

    [2019-07-10T14:34:59,782][INFO ][o.e.d.DiscoveryModule    ] [ESSRV1] using discovery type [zen] and seed hosts providers [settings]

    [2019-07-10T14:35:00,436][INFO ][o.e.n.Node               ] [ESSRV1] initialized

    [2019-07-10T14:35:00,436][INFO ][o.e.n.Node               ] [ESSRV1] starting ...

    [2019-07-10T14:35:00,634][INFO ][o.e.t.TransportService   ] [ESSRV1] publish_address {10.1.100.236:9300}, bound_addresses {[::]:9300}

    [2019-07-10T14:35:00,643][INFO ][o.e.b.BootstrapChecks    ] [ESSRV1] bound or publishing to a non-loopback address, enforcing bootstrap checks

    [2019-07-10T14:35:00,647][ERROR][o.e.b.Bootstrap          ] [ESSRV1] node validation exception

    [1] bootstrap checks failed

    [1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured

    [2019-07-10T14:35:00,650][INFO ][o.e.n.Node               ] [ESSRV1] stopping ...

    [2019-07-10T14:35:00,666][INFO ][o.e.n.Node               ] [ESSRV1] stopped

    [2019-07-10T14:35:00,666][INFO ][o.e.n.Node               ] [ESSRV1] closing ...

    [2019-07-10T14:35:00,678][INFO ][o.e.n.Node               ] [ESSRV1] closed

    The moment you provided a custom setting for network.host, Elasticsearch assumes that you are moving from development mode to production mode, and upgrades a number of system startup checks from warnings to exceptions. So we have to configure one extra setting; the initial_master_nodes:

    cluster.initial_master_nodes: node-1

    Azure DevOps Server–Error publishing nuget packages

    As part of our build process we package and push a set of nuget packages to our artifacts repository. Recently we made the switch to Azure Artifacts after which uploading packages started to fail with the following error message:

    The nuget command failed with exit code(1) and error(Response status code does not indicate success: 409 (Conflict - The feed already contains ‘ExceptionHandling.Database 6.4.1'. (DevOps Activity ID: CAEC4462-2E20-4C69-9AFE-3BBC3C961E20)).)

    Packages failed to publish

    Ok, it seems that Azure Artifacts doesn’t like it when you try to upload the same packages multiple times. (We bumped the package version manually and didn’t care about overwriting an existing package so far). Can we fix this?

    We are using the NuGet task. This task has an interesting option: ‘Allow duplicates to be skipped’. Let’s try this…

    Unfortunately we ended up with the same error message as above. Let’s take a look at the documentation:

    If you continually publish a set of packages and only change the version number of the subset of packages that changed, use this option. It allows the task to report success even if some of your packages are rejected with 409 Conflict errors.

    This option is currently only available on Azure Pipelines and using Windows agents. If NuGet.exe encounters a conflict, the task will fail.

    Aha, the last line explains everything. We are using Azure DevOps Server and it seems that this option only works in the cloud(no idea why?).

    As a workaround I switched to a commandline task and invoked nuget.exe directly. If you are using a recent nuget.exe version you can add the –skipduplicate option to skip existing packages.

    Wednesday, September 11, 2019

    ElasticSearch - Cache aggregations and suggestions

    A quick tip for everyone using ElasticSearch(aren’t you all?);

    It can be a good idea to separate the search request that fetches the results from the search request that returns the aggregations or suggestions. Why would you do that?

    Caching of course! On each shard the request cache module caches the local search results. But(!) by default the request cache module only caches the results of search requests where size=0.  This means that it only works when you don’t want any hits returned.

    We tested it on our development cluster and the difference in performance is significant.

    More information: https://www.elastic.co/guide/en/elasticsearch/reference/current/shard-request-cache.html

    Tuesday, September 10, 2019

    XUnit - Async lifetime

    The setup of your test context in XUnit is typically done through the constructor. For context cleanup, you can add the IDisposable interface to your test class, and put the cleanup code in the Dispose() method.

    But what if your setup/teardown logic contains some async methods? It would certainly be an anti-pattern to add this code inside your synchronous constructor or Dispose.

    The correct way to do this in XUnit is through the IAsyncLifetime interface:

    This interface provides you an async alternative to manage the lifetime of your test context.  It can be used inside your test classes directly but also works in Class and Collection fixtures.

    Monday, September 9, 2019

    Team Foundation Server–402 (Payment Required)

    As part of our build process we push some of our artifacts as NuGet packages to Team Foundation Server.

    After adding a new build agent, executing the push failed with the following log output:

    2019-09-02T13:30:07.1191540Z ##[section]Starting: dotnet push

    2019-09-02T13:30:07.1191540Z ==============================================================================

    2019-09-02T13:30:07.1191540Z Task         : .NET Core

    2019-09-02T13:30:07.1191540Z Description  : Build, test, package, or publish a dotnet application, or run a custom dotnet command. For package commands, supports NuGet.org and authenticated feeds like Package Management and MyGet.

    2019-09-02T13:30:07.1191540Z Version      : 2.131.0

    2019-09-02T13:30:07.1191540Z Author       : Microsoft Corporation

    2019-09-02T13:30:07.1191540Z Help         : [More Information](https://go.microsoft.com/fwlink/?linkid=832194)

    2019-09-02T13:30:07.1191540Z ==============================================================================

    2019-09-02T13:30:07.5722786Z SYSTEMVSSCONNECTION exists true

    2019-09-02T13:30:07.6035200Z Saving NuGet.config to a temporary config file.

    2019-09-02T13:30:07.6035200Z Saving NuGet.config to a temporary config file.

    2019-09-02T13:30:07.6035200Z [command]"C:\Program Files\dotnet\dotnet.exe" nuget push F:\Build\_work\12\s\Hub\Hub.Interfaces\bin\Development\Hub.Interfaces.1.0.0.nupkg --source http://tfs:8080/tfs/DefaultCollection/_packaging/892779dc-d854-4c9f-8b26-833d52585ae6/nuget/v3/index.json --api-key VSTS

    2019-09-02T13:30:07.9941927Z error: Unable to load the service index for source http://tfs:8080/tfs/DefaultCollection/_packaging/892779dc-d854-4c9f-8b26-833d52585ae6/nuget/v3/index.json.

    2019-09-02T13:30:07.9941927Z error:   Response status code does not indicate success: 402 (Payment Required - The user does not have a license for the extension ms.feed. (TFS Activity ID: ACE122BD-49E4-4927-B927-1C2A37F8D18B)).

    2019-09-02T13:30:08.0253954Z ##[error]Error: C:\Program Files\dotnet\dotnet.exe failed with return code: 1

    2019-09-02T13:30:08.0253954Z ##[error]Packages failed to publish

    2019-09-02T13:30:08.0253954Z ##[section]Finishing: dotnet push

    The problem is that this new agent is running using a service account that isn’t know inside Team Foundation Server. Let’s fix this…

    • Browse to your Team Foundation Server collection
    • On the Start page click on the Gear icon and select Users from the dropdown

    • On the Users tab, select Package Management on the left.

    • Afterwards click on Assign to add extra users.

    Remark: The steps above apply to Team Foundation Server not to Azure DevOps(the latest incarnation of TFS)

    Thursday, September 5, 2019

    FluentValidation–Validating collections

    On one of my projects we are using FluentValidation. After upgrading to FluentValidation 8 the way we had to validate our collections changed.

    Before we were using this:

    Now we had to use the RuleForEach method:

    But what if you also want to validate if the collection itself is empty or not. This is still possible through RuleFor:

    Wednesday, September 4, 2019

    Entity Framework Core Query Objects

    Although the name suggests otherwise you are not limited to using entity types (=objects with an id) in EF Core. EF Core 2.1 introduces support for query types, which can be used to query data that isn’t mapped to entity types.

    This allows you to directly map your query results to DTO’s, something especially useful on the query side when you are having a CQRS style architecture.

    Let’s try this!

    First we have to create our DTO:

    Next step is to make EF Core aware of the existence of this query type. We’ll use the fluent configuration api but instead of calling the Entity<T>() method on the modelBuilder we’ll use the Query<T>() method:

    Next, we configure the DbContext to include the DbQuery<T>:

    You can then define queries directly in OnModelBuilding using a LINQ query through ToQuery():

    Of course you can also map a query type to a view using ToView():

    A last option is to directly map it to a raw SQL query using the FromSql method on your DbContext:

    Remark: The query type must be registered with the DbContext as a DbQuery and all columns in the SQL need to match all of the properties in the query type.

    More information: https://docs.microsoft.com/en-us/ef/core/modeling/query-types

    Tuesday, September 3, 2019

    NSubstitute Roslyn Analyzers

    Quick tip if you are using NSubstitute (like me) as your mocking library. Certainly don’t forget to include the NSubstitute Roslyn analyzers as well.

    This allows you to detect some cases where NSubstitute will fail at runtime (e.g. when you attempt to mock non-virtual members).

    For the full list of rules that are validated, take a look at the documentation:

    https://github.com/nsubstitute/NSubstitute.Analyzers/tree/master/documentation

    Monday, September 2, 2019

    .NET Memory management posters

    If you finally want to be able to answer the dreaded “explain memory management in .NET” interview question, I have a solution for you…

    Take a look at the .NET Memory Management posters created by Konrad Kokosa:

    Friday, August 30, 2019

    Visual Studio 2019 - The mystery of ‘Run selected code locally’

    When I right clicked on some code in Visual Studio 2019, I noticed a new ‘Run selected code locally’ menu item at the top. Clicking on it doesn’t do anything(at least on my pc).

    Who can tell me what this does?

    Thursday, August 29, 2019

    XUnit - Testing event handlers

    Testing event handlers in XUnit can be done through the Assert.Raises method. This method expect 3 parameters:

    • An action of EventHandler<T> to attach a handler
    • An action of EventHandler<T> to detach the handler
    • An action containing the code that should trigger the event

    This was not immediately clear to me so here is a (simple) example:

    And here is the interface of the IUnitOfWork that is tested above:

    Wednesday, August 28, 2019

    EF Core - Structure your mapping configurations

    I typically use the Fluent API to configure my Entity Framework (Core) model. I think it gives me the most control without polluting my domain model with EF Core specific attributes.

    You can do this directly inside the OnModelCreating method inside your DbContext but this can get out-of-control quite fast if you have a lot of objects to be mapped.

    A better alternative is to use the IEntityTypeConfiguration<> interface together with the ApplyConfiguration method:

    Tuesday, August 27, 2019

    GraphQL - All errors are equal, but some errors are more equal than others.

    The GraphQL specification gives you one way to handle errors, but typically you have in your application different type of errors. (e.g. validation errors, technical errors, …)

    Not all these errors should be handled in your application in the same way. Sasha Solomon shared some interesting ideas on how they did error handling this at Medium:

    Monday, August 26, 2019

    Azure DevOps - Pull requests - Build expired

    I made a pull request in Azure Devops that had some policies. The code was reviewed and the build succeeded but  I didn’t had time to complete the Pull request.

    Later when I came back I noticed that the Build was expired and  therefore I couldn’t complete the Pull request anymore.

    Build Expiration is a part of the build branch policies. It makes sure that updates to your protected branch don't break open pull requests.

    You can choose between:

    • Always require a new build
    • Require a new build if older than ... hours
    • Don't require a new build

    If the build expired, you can retrigger it by clicking on the … next to the Build expired message and choosing Queue build:

        Friday, August 23, 2019

        XUnit–Roslyn analyzers

        I recently started using XUnit. I’m still discovering what is possible using this unit test framework.

        XUnit has built-in support for parameterized unit tests through the [Theory] and [InlineData] attributes. Nothing special there and similar to what other unit testing frameworks have to offer. But what makes this really nice in XUnit is that when you install the XUnit NuGet package, you get some Roslyn analyzers installed as well.

        These analyzers will validate your parameterized unit tests and return errors when the [InlineData] parameters match don’t match method's parameters:

        Thursday, August 22, 2019

        XUnit–Writing test output

        I recently started using XUnit. I’m still discovering what is possible using this unit test framework.
        One of the things I had to discover was how to write log messages during my tests.  I could fall back to using Trace.WriteLine or Console.WriteLine but that is not the best solution. XUnit allows you to capture test output using a special interface called ITestOutputHelper. In order to use this, just add a constructor argument for this interface and store it inside a variable inside your test class:

        
        Now if you call the ITestOutputHelper.WriteLine method, the output is captured and available inside your test output:

        Wednesday, August 21, 2019

        XUnit–Test lifecycle

        I recently started using XUnit. I’m still discovering what is possible using this unit test framework.
        Before I was using NUnit, although I really liked it I always forgot what exact attribute I needed to control the lifecycle of my tests. I had to look up in the documentation if I needed a SetupFixture, a OneTimeSetup or a Setup attribute.
        In XUnit there is a lot less magic going on and you can fallback to standard .NET idioms like the usage of the constructor and the IDisposable.Dispose() method.

        With these 2 you can already get quite far, but if necessary you can also use

        Tuesday, August 20, 2019

        .NET Conf 2019 is coming!

        Mark September 23 until 25 in your agenda’s as .NET Conf 2019 is coming.

        This year you certainly don’t want to miss out the event as .NET Core 3.0 is launched at .NET Conf 2019.

        Can’t wait…

        Monday, August 19, 2019

        Stack-trace-formatter - Pretty print .NET stack traces

        We all got this problem before. We got a stack trace copied from somewhere but due to a lack of formatting it’s almost impossible to understand what’s going on. Especially if you want to copy/paste a stack trace inside a blogpost it becomes kinda ugly.

        The guys from Elmah created a free online stack trace formatter, a small tool that allows you to pretty print any .NET stack trace and either copy or download the nicely formatted stack trace.

        Nice!

        Friday, August 16, 2019

        Azure DevOps–Reindexing

        The search experience in Azure DevOps(Server) is powered by ElasticSearch. If for any reason your search didn’t seem to work, a lot of Powershell scripts are available to help you with maintaining, updating and monitoring the health of your ElasticSearch instance.

        Remark: Be sure to take the correct scripts for your version of Azure DevOps.

        One of the scripts I use the most is the TriggerCollectionIndexing.ps1 script. This script allows you to reindex everything(wiki, workitem, code) at the collection level.

        Remark: You have to run this script on a server that has the SQL Server Client Tools installed.

        Let’s try it out:

        PS N:\Azure_DevOps_Server_2019> .\TriggerCollectionIndexing.ps1

        cmdlet TriggerCollectionIndexing.ps1 at command pipeline position 1

        Supply values for the following parameters:

        (Type !? for Help.)

        SQLServerInstance: mytfssqlinstance

        CollectionDatabaseName: tfs_defaultcollection

        ConfigurationDatabaseName: tfs_configuration

        CollectionName: DefaultCollection

        EntityType: WorkItem

        Cannot load module SQLSERVER. Trying to load SQLPS module.

        Loaded SQLPS module...

        Cleaned up the WorkItem Collection Indexing state.

        Successfully queued the WorkItem Indexing job for the collection!!

        Column1

        -------

              1

        In the example above, we triggered a reindex of the WorkItems in a specific collection You can do the same thing for Code or Wiki by changing the EntityType in the command above.

        Thursday, August 15, 2019

        Azure DevOps - Agent Auto-provisioning

        When you create a new Agent Pool in Azure DevOps, you get the following options that can be selected:

        • Auto-provision corresponding agent pools in all projects
        • Allow all pipelines to use this pool

         

        The second option is kind-of self explaining but what does the first option do?

        What’s important to understand is that an agent pool exists at multiple levels, you have one at the organization level and you have one at the project level. The project level pool is not really a new pool but rather an import of the organization level agent pool into your team project. Your Azure pipelines will always target the project level pool.

        By selecting the ‘Auto-provision corresponding agent pools in all projects’ checkbox(which is checked by default) the organization agent pool is imported in all your team projects and is accessible there immediately. If you didn’t set this checkbox, you have to import the organization agent pool yourself.

        Therefore go to Project Settings > Agent Pools and click on New Agent Pool…

        If you select here the ‘Base it on an existing organization agent pool’ option you can import the organization queue yourself.

        Wednesday, August 14, 2019

        Tuesday, August 13, 2019

        Microsoft Orleans–Integrate with your favorite IoC container

        As mentioned in a previous post, it is not that hard to start using dependency injection with Orleans. But what if you don’t want to use the built-in IoC container?

        To switch the IoC container instance you can call the UseServiceProviderFactory() method exposed by the SiloHostBuilder. Here is an example that uses StructureMap:

        Monday, August 12, 2019

        Microsoft Orleans–Dependency Injection

        Most .NET(Core) applications today use any kind of inversion of control. This is not different for a Microsoft Orleans application.

        It leverages the ASP.NET Core built-in IoC container to allow you to inject dependencies in your grains:

        This sounds really easy and in fact it is. The only thing you need to be aware of is that the Orleans application is NOT re-using the (ASP) .NET Core IoC container but uses it’s own instance. This is something I didn’t know and caused me a lot of headaches before I figured out the reason.

        Microsoft Orleans is using similar concepts as ASP.NET Core but is not using the same builder. There are plans to integrate it directly when .NET Core 3.0 is released but at the moment of writing, you have to use a specific OrleansBuilder:

        Important to notice in the code above is that the ConfigureServices() method you call here exposes a different IServicesCollection instance as the one used by ASP.NET Core.

        Friday, July 19, 2019

        Azure DevOps Pipeline Build error: Unable to determine the location of vstest.console.exe

        After replacing the existing build servers at one of my customers, some build started to fail with the following error message:

        Unable to determine the location of vstest.console.exe ---> System.IO.FileNotFoundException: Unable to determine the location of vstest.console.exe

        When looking at the build tasks, I noticed they were still trying to use Visual Studio 2015 to run their tests:

        On this new server we only had Visual Studio 2017 and 2019 installed, so Visual Studio 2015 was a ‘no-go’. To fix it, we changed the VSTest version to ‘Latest’:

        Thursday, July 18, 2019

        Azure DevOps–Why is my database so big?

        When preparing an Azure DevOps Server migration, the customer asked me why there Azure Devops databases grew so fast.

        There are 2 queries that can help you answer this question.

        • The first query gives a general overview of the different parts:

        The output of the first query returned the following results in this case:

        Owner BlobSizeInMb
        VersionCVersionControl 64992.008339881835
        FileContainer 59599.479797363281
        TeamTest 44243.018857001953
        WorkItemTracking 23674.237445831054
        CodeSense 989.945262908203
        ProcessTemplate 125.949053763671
        Generic 54.288738250000
        • The second query goes in more detail to differentiate between source control and build:

        The output of the second query returned the following results in this case:

        FileContainerOwner TotalSizeInMb
        Build 56681.754142760742

        Git

        875.809092521484

        vstfs:///Rele

        683.627062796875

        pipelines://b

        271.543574333007

        DistributedTask

        1.143143653320

        They started storing there build artifacts in the database, this explained why there Azure DevOps databases exploded so much.

        Wednesday, July 17, 2019

        Azure DevOps Pipelines–How the build agent detects Visual Studio related capabilities

        Detecting if Visual Studio is installed on the build server can be quite painful. I’ve seen a few times where the build agent didn’t pick up the Visual Studio installation, making the build server useless. As Visual Studio is not added to the capabilities of the build agent, the specific agent is never used to conduct a build.

        If everything is OK, you should see something like this in your Build Agent capabilities:

        But how does the build agent detects that Visual Studio is there?

        This is all done through vswhere.exe, a tool I blogged about before. Vswhere is installed as one of the tools of the build agent, but in case of trouble you can run it yourself to see what is going wrong.

        Let’s try this:

        • Login on your build server and open the installation folder of one of your build agents.
        • Go to the externals\vswhere  subfolder. Here you should find the vswhere.exe
        • Let’s see what options are available by calling vswhere.exe –help:

        PS D:\builds\dev-agent-1\externals\vswhere> .\vswhere.exe -help

        Visual Studio Locator version 2.6.13+a6d40ba5f4 [query version 2.1.1046.44959]

        Copyright (C) Microsoft Corporation. All rights reserved.

        Usage: vswhere.exe [options]

        Options:

        -all           Finds all instances even if they are incomplete and may not launch.

          -prerelease    Also searches prereleases. By default, only releases are searched.

          -products arg  One or more product IDs to find. Defaults to Community, Professional, and Enterprise.

                         Specify "*" by itself to search all product instances installed.

                         See https://aka.ms/vs/workloads for a list of product IDs.

          -requires arg  One or more workload or component IDs required when finding instances.

                         All specified IDs must be installed unless -requiresAny is specified.

                         See https://aka.ms/vs/workloads for a list of workload and component IDs.

          -requiresAny   Find instances with any one or more workload or components IDs passed to -requires.

          -version arg   A version range for instances to find. Example: [15.0,16.0) will find versions 15.*.

          -latest        Return only the newest version and last installed.

          -sort          Sorts the instances from newest version and last installed to oldest.

                         When used with "find", first instances are sorted then files are sorted lexigraphically.

          -legacy        Also searches Visual Studio 2015 and older products. Information is limited.

                         This option cannot be used with either -products or -requires.

          -format arg    Return information about instances found in a format described below.

          -property arg  The name of a property to return. Defaults to "value" format.

                         Use delimiters ".", "/", or "_" to separate object and property names.

                         Example: "properties.nickname" will return the "nickname" property under "properties".

          -find arg      Returns matching file paths under the installation path. Defaults to "value" format.

                         The following patterns are supported:

                         ?  Matches any one character except "\".

                         *  Matches zero or more characters except "\".

                         ** Searches the current directory and subdirectories for the remaining search pattern.

          -nologo        Do not show logo information. Some formats noted below will not show a logo anyway.

          -utf8          Use UTF-8 encoding (recommended for JSON).

          -?, -h, -help  Display this help message.

        Formats:

          json           An array of JSON objects for each instance (no logo).

          text           Colon-delimited properties in separate blocks for each instance (default).

          value          A single property specified by the -property parameter (no logo).

          xml            An XML data set containing instances (no logo).

        • Ok now that we know the available options, let’s have a look at the installed versions using vswhere.exe -all:

        PS D:\builds\dev-agent-1\externals\vswhere> .\vswhere.exe -all

        Visual Studio Locator version 1.0.62 [query version 2.1.1046.44959]

        Copyright (C) Microsoft Corporation. All rights reserved.

        instanceId: 1e1d4042

        installDate: 14/06/2019

        installationName: VisualStudio/16.1.2+29001.49

        installationPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise

        installationVersion: 16.1.29001.49

        displayName: Visual Studio Enterprise 2019

        description: Microsoft DevOps solution for productivity and coordination across teams of any size

        updateDate: 2019-06-14T06:17:25.7201719Z

        enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualS

        tudio.Setup.Service

        layoutPath: x:\vs2019

        channelId: VisualStudio.16.Release

        channelUri: https://aka.ms/vs/16/release/channel

        installChannelUri: x:\vs2019\ChannelManifest.json

        releaseNotes: https://go.microsoft.com/fwlink/?LinkId=660893#16.1.2

        thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909

        • That’s good news, it seems that a version of Visual Studio is installed. Unfortunately the build agent didn’t pick it up. So what is going wrong?
        • Let’s try to use the exact query that the build agent itself is using: vswhere.exe -version '[16.0,17.0)' -latest -format json

        PS D:\builds\dev-agent-1\externals\vswhere> .\vswhere.exe -version '[16.0,17.0)' -latest -format json

        []

        • This returns an empty array. Strange! Let’s download and install the latest vswhere version from GitHub. This version has some extra features and can give us more details.
        • After downloading the latest vswhere.exe, let’s run vswhere.exe –all again:

        PS D:\soft> .\vswhere.exe -all

        Visual Studio Locator version 2.6.13+a6d40ba5f4 [query version 2.1.1046.44959]

        Copyright (C) Microsoft Corporation. All rights reserved.

        instanceId: 1e1d4042

        installDate: 14/06/2019 8:17:25

        installationName: VisualStudio/16.1.2+29001.49

        installationPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise

        installationVersion: 16.1.29001.49

        productId: Microsoft.VisualStudio.Product.Enterprise

        productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe

        state: 13

        isComplete: 0

        isLaunchable: 0

        isPrerelease: 0

        isRebootRequired: 0

        displayName: Visual Studio Enterprise 2019

        description: Microsoft DevOps solution for productivity and coordination across teams of any size

        channelId: VisualStudio.16.Release

        channelUri: https://aka.ms/vs/16/release/channel

        enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service

        installChannelUri: x:\vs2019\ChannelManifest.json

        layoutPath: x:\vs2019

        releaseNotes: https://go.microsoft.com/fwlink/?LinkId=660893#16.1.2

        thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909

        updateDate: 2019-06-14T06:17:25.7201719Z

        catalog_buildBranch: d16.1

        catalog_buildVersion: 16.1.29001.49

        catalog_id: VisualStudio/16.1.2+29001.49

        catalog_localBuild: build-lab

        catalog_manifestName: VisualStudio

        catalog_manifestType: installer

        catalog_productDisplayVersion: 16.1.2

        catalog_productLine: Dev16

        catalog_productLineVersion: 2019

        catalog_productMilestone: RTW

        catalog_productMilestoneIsPreRelease: False

        catalog_productName: Visual Studio

        catalog_productPatchVersion: 2

        catalog_productPreReleaseMilestoneSuffix: 1.0

        catalog_productSemanticVersion: 16.1.2+29001.49

        catalog_requiredEngineVersion: 2.1.3095.63072

        properties_campaignId: 1079615330.1554282809

        properties_canceled: 1

        properties_channelManifestId: VisualStudio.16.Release/16.1.2+29001.49

        properties_nickname:

        properties_operationMode: 0

        properties_setupEngineFilePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installershell.exe

        • We get a lot more detail when using the latest version. One thing you should notice is the isComplete value which is 0. Something is definitely wrong with our installation.
        • Let’s compare the output with a server where everything is running fine:

        D:\Builds\releases-agent-1\externals\vswhere>vswhere -all

        Visual Studio Locator version 1.0.62 [query version 2.1.1046.44959]

        Copyright (C) Microsoft Corporation. All rights reserved.

        instanceId: 7a2855e5

        installDate: 16/04/2019

        installationName: VisualStudio/16.1.2+29001.49

        installationPath: d:\program files\Visual Studio

        installationVersion: 16.1.29001.49

        displayName: Visual Studio Enterprise 2019

        description: Microsoft DevOps solution for productivity and coordination across teams of any size

        updateDate: 2019-06-17T13:57:50.6461374Z

        enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service

        layoutPath: X:\VS2019

        channelId: VisualStudio.16.Release

        channelUri: https://aka.ms/vs/16/release/channel

        installChannelUri: D:\Soft\vs2019\ChannelManifest.json

        releaseNotes: https://go.microsoft.com/fwlink/?LinkId=660893#16.1.2

        thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909

        Use latest vswhere version returns the following on server where everything is ok:

        D:\Soft>vswhere -all

        Visual Studio Locator version 2.6.13+a6d40ba5f4 [query version 2.1.1046.44959]

        Copyright (C) Microsoft Corporation. All rights reserved.

        instanceId: 7a2855e5

        installDate: 16/04/2019 16:02:38

        installationName: VisualStudio/16.1.2+29001.49

        installationPath: d:\program files\Visual Studio

        installationVersion: 16.1.29001.49

        productId: Microsoft.VisualStudio.Product.Enterprise

        productPath: d:\program files\Visual Studio\Common7\IDE\devenv.exe

        state: 4294967295

        isComplete: 1

        isLaunchable: 1

        isPrerelease: 0

        isRebootRequired: 0

        displayName: Visual Studio Enterprise 2019

        description: Microsoft DevOps solution for productivity and coordination across teams of any size

        channelId: VisualStudio.16.Release

        channelUri: https://aka.ms/vs/16/release/channel

        enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service

        installChannelUri: D:\Soft\vs2019\ChannelManifest.json

        layoutPath: X:\VS2019

        releaseNotes: https://go.microsoft.com/fwlink/?LinkId=660893#16.1.2

        thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909

        updateDate: 2019-06-17T13:57:50.6461374Z

        catalog_buildBranch: d16.1

        catalog_buildVersion: 16.1.29001.49

        catalog_id: VisualStudio/16.1.2+29001.49

        catalog_localBuild: build-lab

        catalog_manifestName: VisualStudio

        catalog_manifestType: installer

        catalog_productDisplayVersion: 16.1.2

        catalog_productLine: Dev16

        catalog_productLineVersion: 2019

        catalog_productMilestone: RTW

        catalog_productMilestoneIsPreRelease: False

        catalog_productName: Visual Studio

        catalog_productPatchVersion: 2

        catalog_productPreReleaseMilestoneSuffix: 1.0

        catalog_productSemanticVersion: 16.1.2+29001.49

        catalog_requiredEngineVersion: 2.1.3095.63072

        properties_campaignId: 1079615330.1554282809

        properties_channelManifestId: VisualStudio.16.Release/16.1.2+29001.49

        properties_nickname:

        properties_setupEngineFilePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installershell.exe

        • This confirms our assumptions. It seems that the Visual Studio installation did not complete.

        I opened up the Visual Studio installer and the Visual Studio installation continued. Problem solved!

        Tuesday, July 16, 2019

        GraphQL–Use GraphQL playground to authenticate requests

        I really like GraphiQL to play around and test my GraphQL endpoints in the browser(try a live demo here). There is only one thing I really miss and that is the option to add extra headers when sending requests to your GraphQL endpoint.

        Why do I need this?

        One word; security. Most of my GraphQL endpoints are secured using oAuth. This makes using GraphiQL no longer an option as every request is answered by a 401 Unauthorized response.

        Luckily there are a lot of alternative libraries that offer similar functionality as GraphiQL. The one I like is GraphQL Playground.

        From the documentation:

        GraphQL Playground uses components of GraphiQL under the hood but is meant as a more powerful GraphQL IDE enabling better (local) development workflows. Compared to GraphiQL, the GraphQL Playground ships with the following additional features:

        • Interactive, multi-column schema documentation
        • Automatic schema reloading
        • Support for GraphQL Subscriptions
        • Query history
        • Configuration of HTTP headers
        • Tabs

        To add a security header, open your GraphQL Playground endpoint(I’m hosting it inside my ASP.NET Core app using GraphQL.Server.UI.Playground), go to the HTTP headers section and add the following JSON (every header value is a new json property):

        Now when you send a request, the headers will be included...

        Monday, July 15, 2019

        GraphQL Documentary

        Did I mention I’m a big fan of GraphQL? Now they even released a documentary:

        “Starring Lee Byron, Dan Schafer and Nick Schrock (co-creators of GraphQL) and other big names from the #GraphQL community, "GraphQL: The Documentary" explores the story of why and how GraphQL came to be and the impact it's having on big #tech companies worldwide, including Facebook, Twitter, Airbnb and Github.”

        Friday, July 12, 2019

        Selenium - OpenQA.Selenium.DriverServiceNotFoundException

        With the announcement from Microsoft to stop supporting Coded UI tests, I’m back in Selenium land.

        To get it back in my fingers, I started to write a first simple Selenium test:

        But although this test looked quite simple, it failed with the following exception:

        Test Name:        TestMethod1

        Test FullName:  SeleniumTestProject.UnitTest1.TestMethod1

        Test Source:       C:\projects\test\SeleniumTestProject\UnitTest1.cs : line 10

        Test Outcome:  Failed

        Test Duration:   0:00:00,2912324

        Result StackTrace:         

        at OpenQA.Selenium.DriverService.FindDriverServiceExecutable(String executableName, Uri downloadUrl)

           at OpenQA.Selenium.Chrome.ChromeDriverService.CreateDefaultService()

           at OpenQA.Selenium.Chrome.ChromeDriver..ctor(ChromeOptions options)

           at SeleniumTestProject.UnitTest1.TestMethod1() in C:\projects\test\SeleniumTestProject\UnitTest1.cs:line 15

        Result Message:             

        Test method SeleniumTestProject.UnitTest1.TestMethod1 threw exception:

        OpenQA.Selenium.DriverServiceNotFoundException: The chromedriver.exe file does not exist in the current directory or in a directory on the PATH environment variable. The driver can be downloaded at http://chromedriver.storage.googleapis.com/index.html.

        The exception was easy to understand, I needed the chromedriver.exe to spin up a chrome instance. I could follow the suggestions in the exception and download it from http://chromedriver.storage.googleapis.com/index.html. A simpler alternative is adding the Selenium.Chrome.WebDriver NuGet package to your project.

        This package does all the work for you: tt installs Chrome Driver(Win32) for Selenium WebDriver into your Unit Test Project and copies the "chromedriver.exe" to the bin folder when building your project.

        Thursday, July 11, 2019

        Tips from NDC Oslo 2019 - AZX

        If you are using a Mac or Linux and want to use Azure, here is a tip for your: azx.ms

        From the Github repo:

        This utility is intended to help you create the scripts you need for Microsoft Azure. You can browse them online or install a quick utility function.

        Wednesday, July 10, 2019

        Microsoft Cloud Workshop

        Interested in organizing your own Cloud workshop? Take a look at Microsoft Cloud Workshop, it contains a big library of workshop materials including presentation decks, trainer and student guides, and hands-on labs.

        Tuesday, July 9, 2019

        TFS - XAML Build controller stops working–Part 2

        Yesterday I blogged about a problem that I had with the XAML Build controllers. I reconfigured the /queue what seemed to solve the problem.

        Unfortunately the problem reappeared after a few hours. Instead of getting a 404 error, this time the details exposed a 500 error code.

        In the logs I noticed the following error message:

        WebHost failed to process a request.

        Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/17729775

        Exception: System.ServiceModel.ServiceActivationException: The service '/queue/SampleCollection/Services/v4.0/MessageQueueService2.svc' cannot be activated due to an exception during compilation.  The exception message is: Memory gates checking failed because the free memory (419909632 bytes) is less than 5% of total memory.  As a result, the service will not be available for incoming requests.  To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.. ---> System.InsufficientMemoryException: Memory gates checking failed because the free memory (419909632 bytes) is less than 5% of total memory.  As a result, the service will not be available for incoming requests.  To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.

           at System.ServiceModel.Activation.ServiceMemoryGates.Check(Int32 minFreeMemoryPercentage, Boolean throwOnLowMemory, UInt64& availableMemoryBytes)

           at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CheckMemoryCloseIdleServices(EventTraceActivity eventTraceActivity)

           at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)

           --- End of inner exception stack trace ---

           at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)

           at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath, EventTraceActivity eventTraceActivity)

        Process Name: w3wp

        Process ID: 2216

        Whoops! It seems that our TFS server is desperate for some memory. And indeed, after adding some extra memory and a reboot it finally started to work.

        Let’s move on to the next problem…

        Tips from NDC Oslo 2019 - Polly.NET policy wrapping

        I do like Polly.NET, the “resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner”(quoted from the website).

        One of the nice things you can do in Polly is combining multiple policies to achieve more complex functionality:

        This works but requires some ugly nesting. A better approach I learned at NDC was through PolicyWrap:

        More information here: https://github.com/App-vNext/Polly/wiki/PolicyWrap

        Monday, July 8, 2019

        TFS - XAML Build Controller stops working

        When I started a XAML Build Controller on the build server, I noticed the following behavior:

        • The controller and agents start up and change to the Ready state while the icons went green
        • A few seconds later the icons turn red again, although the controller and agents remain in the same state.
        • On the Build Controller, a details link appear that shows the following error message:

        TF400324: Team Foundation services are not available from server <Server/CollectionName>.
        Page not found

        So what was going on?

        Everything was caused by a change in IIS I did. Before the TFS server was hosted on https://mytfs.company.be/tfs but they wanted to get rid of the /tfs part. So I removed the tfs application from IIS and moved all services to the root of the site. This worked perfectly for TFS itself but caused issues for the build controllers.

        Why?

        Because there are in fact 2 applications that should be hosted:

        1. the root TFS webservices now hosted at https://mytfs.company.be/
        2. a /queue application that should be hosted at https://mytfs.company.be/queue

        By removing the /tfs, the /queue application was gone as well. I added the /queue application and my build controllers and agents turned green again…

        Friday, July 5, 2019

        Killing a hanging Windows Service

        While testing a newly created Windows Service, the service failed on startup. As a consequence, I couldn’t start/stop/delete the service anymore.

        To fix it I had to jump through some hoops:

        • First I had to query for all services to find the correct process id. This can be done using the sc queryex command
        • This returned a list of all services:

        SERVICE_NAME: WpnUserService_ce0fb

        DISPLAY_NAME: Windows Push Notifications User Service_ce0fb

                TYPE               : f0   ERROR

                STATE              : 4  RUNNING

                                        (STOPPABLE, NOT_PAUSABLE, ACCEPTS_PRESHUTDOWN)

                WIN32_EXIT_CODE    : 0  (0x0)

                SERVICE_EXIT_CODE  : 0  (0x0)

                CHECKPOINT         : 0x0

                WAIT_HINT          : 0x0

                PID                : 8740

                FLAGS              :

        SERVICE_NAME: FailingService.Host

        DISPLAY_NAME: FailingService.Host

                TYPE               : 10  WIN32_OWN_PROCESS

                STATE              : 4  RUNNING

                                        (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)

                WIN32_EXIT_CODE    : 0  (0x0)

                SERVICE_EXIT_CODE  : 0  (0x0)

                CHECKPOINT         : 0x0

                WAIT_HINT          : 0x0

                PID                : 18836

        FLAGS              :

        • Now that I have the PID, I can try to kill the windows service using taskkill /pid 18836
        • I got the following error message when trying to execute this:

        ERROR: The process with PID 18836 could not be terminated.

        Reason: This process can only be terminated forcefully (with /F option).

        • Let’s try this again with the ‘/F’ option: taskkill /pid 18836 /F

        SUCCESS: The process with PID 18836 has been terminated.

        • After killing the service, I was finally able to delete it.

        Thursday, July 4, 2019

        Azure Artifacts - Views

        A nice feature of Azure Artifacts(part of Azure DevOps) is the support for Views. By using Views you can split out a feed into multiple parts. This allows you to do a controlled rollout of a new package. By default, Azure Artifacts provide 3 views: @local, @prerelease, and @release.

        This allows you to do package promotion:

        • We’ll start with an automated deployment to the @local feed.
        • When a package is ready for adoption, we can promote it to the @prerelease view:

        • When the package is validated and ready for prime time, we promote it into the @release view.

        More information:

        Wednesday, July 3, 2019

        Tips from NDC Oslo 2019–F# Adding overloads to a discriminated union

        A neat trick I noticed while watching the Dungeons, Dragons and Functions talk by Mathias Brandewinder is adding overloads to a discriminated union.

        In his talk, he is modelling Dungeons and Dragons using F#. One of the things he needs to model is a dice roll. In D&D you have uncommon dice shapes and inside the rule book you’ll find dice rules like:  4d6+2d10+8.

        What does this formula means? 4 roles of a 6-sided dice + 2 roles of a 10-sided dice+ 8

        To model this in F#, Mathias created the following discriminated union:

        You can then use this Roll type to create the formula above:

        This works but is not very readible. To fix this, Mathias introduced some overloads on the Roll type:

        This nicely cleans up the formula to:

        More information can be found in Mathias blog post here: https://brandewinder.com/2018/07/31/give-me-monsters-part-3/

        Tuesday, July 2, 2019

        Tips from NDC Oslo 2019–F# Interactive built-in constants

        Reading other files through F# Interactive can be tricky when using relative paths. It’s hard to guess what F# Interactive will use as the working directory. Of course you can start using absolute paths but a better alternative is using the built-in constants;

        __SOURCE_DIRECTORY__
        __SOURCE_FILE__
        

        This allows you to do the following:

        Monday, July 1, 2019

        Tips from NDC Oslo 2019–Grid Garden

        I have to admit that I’m really bad in CSS (although I was really proud on the linear-gradient I created 2 weeks ago). Before I always used the grid layout system of Bootstrap and didn’t worry to much about it. But I feel that the time is right to really start understanding Flexbox and the newer Grid Template.

        And what is a better way than through gamification. So stop disturbing me as I’m taking care of my carrots

        Friday, June 28, 2019

        Tips from NDC Oslo 2019–Flexbox Froggy

        I have to admit that I’m really bad in CSS (although I was really proud on the linear-gradient I created last week). Before I always used the grid layout system of Bootstrap and didn’t worry to much about it. But I feel that the time is right to really start understanding Flexbox and the newer Grid Template.

        And what is a better way than through gamification. So stop disturbing me as I’m trying to get a frog on a lilypad

        Thursday, June 27, 2019

        Tips from NDC Oslo 2019 - .NET Core ReadyToRun

        In the Full .NET framework you had the concept of native images generated using Ngen.exe(Native Image Generator). By creating a native image, you can improve the startup time and performance of managed applications. A native image contains compiled processor-specific machine code. This image is then installed into the native image cache on your local computer. The runtime can use native images from the cache instead of using the just-in-time (JIT) compiler to compile the original assembly.

        With the upcoming release of .NET Core 3.0, a similar feature will appear in .NET Core through ReadyToRun(R2R) image. R2R is a form of ahead-of-time (AOT) compilation.

        R2R binaries improve startup performance by reducing the amount of work the JIT needs to do as your application is loading. The binaries contain similar native code as what the JIT would produce, giving the JIT a bit of a vacation when performance matters most (at startup). R2R binaries are larger because they contain both intermediate language (IL) code, which is still needed for some scenarios, and the native version of the same code, to improve startup.

        In contrast to NGEN where compilation must be done on client machines, R2R images are generated using crossgen, as part of your build and are “ready to run” without any additional work on client machines.

        For more details and some performance benchmarks, read more here: https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-6/

        Wednesday, June 26, 2019

        Tips from NDC Oslo 2019 - Azure Cosmos DB Data Migration tool

        If you want to start using Azure Cosmos DB, you probably want a way to get some existing data from multiple sources into Azure Cosmos DB.

        No worries, this is all possible through the Azure Cosmos DB Data Migration tool. You can import from JSON files, CSV files, SQL, MongoDB, Azure Table storage, Amazon DynamoDB, and even Azure Cosmos DB SQL API collections.

        You can download the migration tool source code from this repository on GitHub. Or if you don’t want to compile the code yourself, you can download a pre-compiled binary.

        To get started, you can follow the tutorial here: https://docs.microsoft.com/en-us/azure/cosmos-db/import-data

        Tuesday, June 25, 2019

        ASP.NET Core 2.2 free ebook

        Just in time for the summer holidays released Syncfusion another free ebook. This time on ASP.NET Core 2.

        Download it for free from the Free Ebooks section of Syncfusion Tech Portal.

        Monday, June 24, 2019

        Nice quote–Entrepreneurship

        A quote by Reid Hoffman, the founder of LinkedIn:

        “If you are not embarrassed by the first version of your product, you've launched too late.”

        Reid Hoffman

        Friday, June 21, 2019

        Tips from NDC Oslo 2019–The C stands for Cascade

        People seems to forget the power of CSS. If you can’t remember how CSS selectors exactly work and why the cascading part is so important, go and improve your CSS skills using CSS Diner. You’ll have 32 levels to go through and solve every challenge by writing the correct CSS selector:

        Thursday, June 20, 2019

        Tips from NDC Oslo 2019–SpendOps with Azure Cosmos DB

        During a presentation today about Azure Cosmos DB, the cost aspect of Cosmos DB was mentioned. Although Cosmos DB doesn’t have to be expensive, you hear a lot of horror stories. The challenge is in choosing the right settings for your use case or scenario.

        To help you keep the cost under control the SpendOps with Azure Cosmos DB post by William Liebenberg was mentioned. In this post he explains an approach where an Azure DevOps Release gate is used to check the cost of a particular feature or function . When it is higher than expected  the release is blocked.

        Here is the related presentation video: