Thursday, November 14, 2019

IdentityServer 4 - CORS

If an endpoint is called via Ajax calls from JavaScript-based clients, CORS configuration is required.

This can be done by setting the AllowedCorsOrigins collection on the client configuration. IdentityServer will consult these values to allow cross-origin calls from the origins.

Remark: Be sure to use an origin (not a URL) when configuring CORS. For example: https://foo:123/ is a URL, whereas https://foo:123 is an origin.

Wednesday, November 13, 2019

MassTransit–Batch Message Consumption

A lesser known feature inside MassTransit is the support of batch messages. This can be a really nice feature if you want to combine a batch of high-volume smaller messages into a single atomic consumer.

How does this work?

MassTransit will combine multiple messages into a single consume by specifying a window, such as a message count (batch size), time period, or a combination of both.

There are 2 configurable limits:

  • Size: A limit specifying the maximum number of messages which can fit into a single batch will trigger once that many messages are ready to be consumed. The batch size must be less than or equal to any prefetch counts or concurrent message delivery limits in order reach the size limit.

  • Time: A limit specifying how long to wait for additional messages from the time when the first message is ready, after which the messages ready within that time are delivered as a single batch. The time limit should be well within the lock time of a message, including enough time to process the batch.

Batch configuration

To use the batching functionality, configure an extra receive endpoint and use the Batch method to configure the endpoint:

Batch consumption

The message batch is delivered as an array to the consumer, so that the existing behavior is maintained for middleware, factories, etc. An additional context is available on the payload, which can be used to discover details related to the batch. Instead of receiving a single message you get a Batch<T> of messages:

Remark: This feature is experimental.  Be sure to configure the transport with sufficient concurrent message capacity (prefetch, etc.) so that a batch can actually complete without always reaching the time limit.

Tuesday, November 12, 2019

Azure DevOps - Kanban board limits

Got a question from a customer about the Kanban board in Azure DevOps Server:

I noticed that on the Kanban board on the first and last column only a limited number of work items are shown. Is this something that can be configured?

Quick answer: no.

To limit the number of items on the board, the first and last column of your kanban board will only show 20 work items. To see more work items you need to use the Show more items link in the bottom.

Monday, November 11, 2019

ASP.NET Core 3.0 - Enable Authentication

Quick tip for anyone using ASP.NET Core 3.0 (especially when you did an upgrade from ASP.NET Core 2.x); if you want to enable authentication don’t forget to add the correct middleware. You need both UseAuthentication and UseAuthorization:

In earlier versions of ASP.NET Core, authorization support was provided via the [Authorize] attribute. Authorization middleware wasn't available. In ASP.NET Core 3.0, authorization middleware is required(!). Therefore the ASP.NET Core Authorization Middleware (UseAuthorization) should be placed immediately after UseAuthentication.

Add the UseAuthorization and UseAuthentication methods AFTER the UseRouting() but BEFORE the UseEndpoints():

A DefaultPolicy is initially configured to require authentication, so no additional configuration is required.

Friday, October 25, 2019

ElasticSearch–Decrease the monitoring data

Quick tip to prevent the monitoring index to get out of control:

To decrease the amount of data of the ElasticSearch monitoring you can change the _cluster settings

More information:

Wednesday, October 23, 2019

Azure DevOps–How to change the default iteration?

After upgrading to Azure DevOps 2019, I got a question from a customer asking how to change the default iteration used when creating new work items. By default the current iteration is used. If you are creating user stories, this is probably not what you want as these user stories should first be analyzed, groomed, … before they can be planned inside a specific iteration/sprint.

Fortunately this is something that can be changed easily at the team level:

  • Click on the Show Team Profile  icon on the Kanban board:

  • Click on Team settings:

  • Go to Iterations and Areas:

  • Click on Iterations:

  • Now you change the default iteration how you want:

Tuesday, October 22, 2019

Fork–A fast and friendly GIT client

Tooling is important and great tools can make a difference. Especially when you are using so rich and complex as GIT can be.

Last week I discovered a new GIT client; Fork.

I was especially impressed by the interactive rebase functionality. Could be a lifesaver if you are now afraid to use rebase

Remarks: My current favorite is GitKraken in case you want to know. But I’m giving Fork a try and so should you…

Friday, October 18, 2019

Orleans–Fire and forget

The basic building block in Orleans is a ‘Grain’. A grain is an atomic unit of isolation, distribution, and persistence. A grain perfectly matches the OO principles as it encapsulates state of an entity and encodes its behavior in the code logic.

The ‘normal’ way to communicate between Grains is through message passing. This is greatly simplified thanks to the async/await programming model in C# combined with some code generation voodoo. It almost ‘feels’ like normal method invocations.

A consequence of the async programming model is that you always should ‘await’ the results. However there are some situations where you don’t care about the results and want to call another grain in a ‘fire-and-forget’ mode.

To achieve this you can use the InvokeOneWay() extension method on a GrainReference:

Thursday, October 17, 2019

Testing–Faking a delay in SQL Server

To test the timeout settings of my application, I needed a query that exceeds a certain time.

This was not that hard to achieve in SQL Server thanks to the WAITFOR statement. This statement blocks the execution of a batch, stored procedure, or transaction until a specified time or time interval is reached, or a specified statement modifies or returns at least one row.

----Delay for 10 seconds
WAITFOR DELAY '000:00:10'
SELECT 'Hello finally!'

More information:

Wednesday, October 16, 2019

MassTransit - A convention for the message type {typename} was not found

While preparing a presentation I created a simple demo app where I wanted to publish a message to a queue.

My first (naïve) attempt looked like this:

This failed with the following error message:

A convention for the message type {typename} was not found

What was my mistake?

In MassTransit you have to make a difference between sending a message and publishing a message. Whereas publishing a message doesn’t require any extra configuration, sending a message does. Why? Because when sending a message you directly target a queue. MassTransit has to know which queue the message should be send to.

We have 2 options to make this work:

1) You specify the target queue using a convention:

2) You use the ISendEndpointprovider to specify a queue:

Tuesday, October 15, 2019

Reconfigure the ElasticSearch Windows Service

If you are running ElasticSearch on a Windows Cluster you probably are using a Windows Service to run it in the background and make it start automatically at boot time.

This Windows Service feature is available out-of-the-box if you use the .zip package.

Some settings of ElasticSearch are managed as command-line arguments(e.g. the min and max memory usage). To manipulate these settings when using the Windows Service, you have to go through the ElasticSearch Windows Service Manager.

  • To open the manager, go the ElasticSearch installation folder. (e.g. c:\elasticsearch-7.4.0\)
  • Browse to the bin folder (where you should find a elasticsearch-service.bat file)
  • Run the following command:
    • elasticsearch-service.bat manager

This will open a GUI where you can manage multiple ElasticSearch settings:

Remark: Most changes will require a restart of the service.

Monday, October 14, 2019

ASP.NET Core gRPC–Unary RPC vs Streams

When creating your gRPC implementation you have to be aware about the difference between Unary RPC and Streams.

Unary RPC

This is the simplest type of RPC, where the client sends a single request and gets back a single response. This is the simplest approach and similar to what we know when using WCF.


With streaming we have to make a difference between server streaming, client streaming and bidirectional streaming.

A server-streaming RPC is most similar to the Unary RPC, the only difference is that the server sends back a stream of responses instead of a single response after getting the client’s request message. After sending back all its responses, the server’s status details (status code and optional status message) and optional trailing metadata are sent back to complete on the server side. The client completes once it has all the server’s responses.

A client-streaming RPC turns things around, the client sends a stream of requests to the server instead of a single request. The server sends back a single response, typically but not necessarily after it has received all the client’s requests, along with its status details and optional trailing metadata.
In a bidirectional streaming RPC, the call is initiated by the client calling the method and the server receiving the client metadata, method name, and deadline. The server can choose to send back its initial metadata or wait for the client to start sending requests. What happens next depends on the application, as the client and server can read and write in any order - the streams operate completely independently.

It is important that you are aware of the difference as it can greatly impact the performance characteristics of your application. Working with streams can help you reduce the memory footprint of your application as you don’t have to buffer the whole response in memory before returning it to the client. Another advantage is that the client can start processing before all data is returned from the server(or the other way around).

More information:

Friday, October 11, 2019

Why you should not fear rebase…

Last week our junior developers shared their experiences and lessons learned during a ‘dev case’. One thing they al mentioned is that doing a ‘rebase’ in GIT is, according to their opinion, a bad idea. Although rebasing is a powerful tool, and you have to apply it carefully, there is no reason to avoid it all cost.

Some things to keep in mind before you rebase:

  1. Never rebase commits that have been pushed to a remote origin and shared with others.
  2. Use rebase to catch up with the commits on another branch as you work with a local feature branch.
  3. You can't update a published branch with a push after you've rebased the local branch. You'll need to force push the branch to rewrite the history of the remote branch to match the local history. Never force push branches in use by others.

As a general rule it would only use rebase on local changes that haven't been shared with others. Once you’ve shared your changes, switch to merge instead.

  • To use rebase, go to Team Explorer –> Branches.
  • Select Rebase instead of Merge.
  • Specify the target branch and click Rebase.

Thursday, October 10, 2019

ASP.NET Core 3.0 - ConfigureContainer magic

Last week I blogged about the changes I had to make to let Autofac work with ASP.NET Core 3.0. Inside my Startup.cs file I had to use the .ConfigureContainer() method:

But where is this method coming from? Let’s dig into the ASP.NET Core source code to find out…

The source of all magic is the StartupLoader class:

This class uses reflection to find the following 3 methods in the Startup.cs file:

  • a Configure() method
  • a ConfigureServices() method
  • a ConfigureContainer() method

If you want environment-specific setup you can put the environment name after the Configure part, like ConfigureDevelopment, ConfigureDevelopmentServices, and ConfigureDevelopmentContainer. If a method isn’t present with a name matching the environment it’ll fall back to the default.

If a ConfigureContainer() method is found, the IServiceProviderFactory<TContainerBuilder> CreateBuilder method is invoked and the created builder is passed as a parameter to the ConfigureContainer()

Wednesday, October 9, 2019

Visual Studio 2019–Code Cleanup

Did you notice the small broom icon at the bottom of your code editor window in Visual Studio?

This is the  Code Cleanup button. It allows you to apply code styles from an EditorConfig file or from the Code Style options page. (The .editorconfig takes precedence).

To configure the exact Code Cleanup actions, you can click the expander arrow next to the code cleanup broom icon and then choose Configure Code Cleanup.

Configure Code Cleanup in Visual Studio 2019

After you've configured code cleanup, you can either click on the broom icon or press Ctrl+K, Ctrl+E to run code cleanup.

Tuesday, October 8, 2019

Visual Studio–Generate an EditorConfig file

I talked about the .editorconfig file a long time ago as a way to standardize code style conventions in your team. These conventions allow Visual Studio to offer automatic style and format fixes to clean up your document.

But did you know that in Visual Studio 2019, you can generate an .editorconfig file dynamically based on the style and formatting found in your existing codebase?

  • Go to Tools –> Options –> IntelliCode.
  • Change the EditorConfig inference setting to Enabled.
  • Right click on you solution in the Solution Explorer and choose Add –> New EditorConfig (IntelliCode)

Add IntelliCode-generated EditorConfig file in Visual Studio

After you add the file in this way, IntelliCode automatically populates it with code style conventions it infers from your codebase.

Friday, October 4, 2019

Azure DevOps - Publish code as wiki–Advanced features

One of the features I really like in Azure DevOps is to publish your code as a wiki. This allows you to choose a Git repository, branch and folder that contain Markdown files. The markdown files are then published as pages inside the wiki.

Unfortunately when we take a look at the table of contents(TOC) we see all the markdown files listed in alphabetical order. Every subfolder is also shown as a wiki page even when it doesn’t contain any markdown files.

This is probably not what we want. Let’s improve the TOC…

Change the page order

To change the order of the files in the TOC, you can add a .order file to the repository.

Each .order file defines the sequence of pages contained within a folder. The root .order file specifies the sequence of pages defined at the root level. And for each folder, a .order file defines the sequence of sub-pages added to a parent page.

Inside the .order file you can specify each file name without the .md extension. An example:


By default, the first file that appears at the root within alphabetical order is set as the wiki home page.

Promote folder to page

Another annoying thing is that every subfolder is shown as a TOC item in the wiki although no page exists. It would be logical to have a wiki page for every folder. Therefore we need to create a markdown file with the same name as the folder as a sibling to the folder (meaning both the folder and the md file of the same name should lie next to each other). See the screenshot below:

Promote a folder to a page

Wednesday, October 2, 2019

.NET Core 3.0 - HTTP/2 support

You maybe think this is a bad title for this blog post? HTTP/2 support was already available for .NET Core 3.0. So why a blog post with the release of .NET Core 3.0?

The reason is that although it was possible to host an ASP.NET Core 2.0 application behind an HTTP/2 endpoint, the HttpClient class didn’t had support for it!

There are 2 ways that can be used to enable HTTP/2:

Enable HTTP/2 at the instance level

To enable HTTP/2 support at the instance level, you can set the DefaultRequestVersion when creating the HttpClient instance:

For example, the following code creates an HttpClient instance using HTTP/2 as its default protocol:

Of course even better is to use the HttpClientFactory to create and configure the HttpClient:

Enable HTTP/2 at the request level

It is also possible to create a single request using the HTTP/2 protocol:

Remark: Remember that HTTP/2 needs to be supported by both the server and the client. If either party doesn't support HTTP/2, both will use HTTP/1.1.

Tuesday, October 1, 2019

ASP.NET Core 3.0 - Autofac error

After upgrading my ASP.NET Core application to 3.0 I got an error in Startup.cs  when I switched to the new HostBuilder:

System.NotSupportedException: 'ConfigureServices returning an System.IServiceProvider isn't supported.'

Let’s take a look at my ConfigureServices() method:

Inside my ConfigureServices I’m using the Autofac containerbuilder to build up my container and return an AutofacServiceProvider. Therefore I updated the ConfigureServices() method signature to return an IServiceProvider. This worked perfectly in ASP.NET Core 2.x but is not allowed anymore when using the new HostBuilder in ASP.NET Core 3.0.

Time to take a look at the great Autofac documentation for a solution: Ok, so to fix this we have to change our ConfigureServices() method to no longer return an IService Provider:

Then we have to update the program.cs to register our AutofacServiceProvider there:

As a last step we have to add a ConfigureContainer() method to the Startup.cs where we can configure the containerbuilder instance:

Remark: We don’t have to build the container ourselves, this is done by the framework for us.

Monday, September 30, 2019

ASP.NET Core 3.0–Swashbuckle error

As probably most people in the .NET ecosystem I’m using Swashbuckle to generate my OpenAPI documentation. (Anyone using NSwag instead?)

After upgrading to ASP.NET Core 3.0 (and switching to the 5.0-rc4 prerelease version of Swashbuckle), the following code no longer compiled:

I had to replace the Info class which couldn’t be found by the OpenApiInfo class:

This OpenApiInfo class is now part of the Microsoft.OpenApi.Models namespace.

Friday, September 27, 2019

C# 8.0 Nullable reference types for framework and library authors

C# 8.0 introduces the concept of nullable reference types. If you are a framework or library author, introducing this functionality in your code is not without its challenges.

A good introduction can be found here:

Thursday, September 26, 2019

Setup the Kubernetes dashboard on Docker for Windows

A useful tool when you are new to Kubernetes is the Kubernetes Dashboard.

Unfortunately the Kubernetes Dashboard is not included out-of-the-box with Docker for Windows however it can be easily setup for your local cluster.

To setup the dashboard use the following command:

kubectl apply -f 
The output should look like this:

secret/kubernetes-dashboard-certs created
serviceaccount/kubernetes-dashboard created created created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created

To view the Dashboard in your web browser run:

kubectl proxy

And nagivate to your Kubernetes Dashboard at:


The first time you open the dashboard you have to enter an authentication token.

Creating an authorization token

To create an authorization token, we first need a Service Account:

kubectl create serviceaccount admin-user

Now we need a clusterrolebinding to assign the ClusterRole to the created admin-user:

kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user admin-user

Check an associated secret:

kubectl get serviceaccounts admin-user -o yaml

As a last step we need to request the secret data:

kubectl describe secret admin-user-token-5s5rv

Now you can copy and past the generated token in the Token field.

Wednesday, September 25, 2019

Switch between Kubernetes contexts

Lost some time yesterday figuring out how to switch between different Kubernetes environments. So a quick post, just as a reminder for myself:

You can view contexts using the kubectl config command:

kubectl config get-contexts

CURRENT  NAME                            CLUSTER                    NAMESPACE           
*         docker-desktop                   docker-desktop             docker-desktop                                   
          docker-for-desktop               docker-desktop             docker-desktop

You can set the context by specifying the context name:

kubectl config use-context docker-for-desktop

Tuesday, September 24, 2019

ElasticSearch–Performance testing

When trying to load test our ElasticSearch cluster, we noticed big variations in results that we couldn’t explain based on the changes we made.

Turned out that our tests were not executed in comparable situations as we didn’t clear the ElasticSearch cache.

So before running our tests, we cleared the cache using following command:

POST /<myindexname>/_cache/clear?request=true

If you want to view what’s inside the Elastic node cache, you can use the following command::

GET /_cat/nodes?v&h=id,name,queryCacheMemory,queryCacheEvictions,requestCacheMemory,requestCacheHitCount,requestCacheMissCount,flushTotal,flushTotalTime

Monday, September 23, 2019

GraphQL Rules

As with every technology you give to your team everyone has different opinions and conventions. A style guide becomes an indispensible part of your development organisation. Otherwise the ‘tabs vs spaces’ discussion can go on forever.

This also applies to GraphQL. So to help you get started take a look at

Rules and recommendations mentioned here were the results of 3 years' experience of using GraphQL both on the frontend and backend sides. We also include the recommendations and experience of Caleb Meredith (PostGraphQL author, Facebook ex-employee) and Shopify engineers.

This guide is intended to be open source and could change in the future, - the rules may be improved on, changed, or even become outdated. What is written here is a culmination of time and pain suffered from the use of horrible GraphQL-schemas.

Friday, September 20, 2019

Cannot create or delete the Performance Category 'C:\Windows\TEMP\tmp3DA0.tmp' because access is denied.

After migrating some .NET applications from an old server to a brand new Windows Server 2019 instance, we stumbled over a range of errors.

Yesterday we got one step closer to a solution but we are not there yet. The application still doesn’t work but now we get the following error message:

Server Error in '/AppServices' Application.

Cannot create or delete the Performance Category 'C:\Windows\TEMP\tmp3DA0.tmp' because access is denied.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.UnauthorizedAccessException: Cannot create or delete the Performance Category 'C:\Windows\TEMP\tmp3DA0.tmp' because access is denied.

ASP.NET is not authorized to access the requested resource. Consider granting access rights to the resource to the ASP.NET request identity. ASP.NET has a base process identity (typically {MACHINE}\ASPNET on IIS 5 or Network Service on IIS 6 and IIS 7, and the configured application pool identity on IIS 7.5) that is used if the application is not impersonating. If the application is impersonating via <identity impersonate="true"/>, the identity will be the anonymous user (typically IUSR_MACHINENAME) or the authenticated request user.

To grant ASP.NET access to a file, right-click the file in File Explorer, choose "Properties" and select the Security tab. Click "Add" to add the appropriate user or group. Highlight the ASP.NET account, and check the boxes for the desired access.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


[UnauthorizedAccessException: Cannot create or delete the Performance Category 'C:\Windows\TEMP\tmp3DA0.tmp' because access is denied.]

   System.Diagnostics.PerformanceCounterLib.RegisterFiles(String arg0, Boolean unregister) +482

   System.Diagnostics.PerformanceCounterLib.RegisterCategory(String categoryName, PerformanceCounterCategoryType categoryType, String categoryHelp, CounterCreationDataCollection creationData) +105

   System.Diagnostics.PerformanceCounterCategory.Create(String categoryName, String categoryHelp, PerformanceCounterCategoryType categoryType, CounterCreationDataCollection counterData) +275

   Akka.Monitoring.PerformanceCounters.ActorPerformanceCountersMonitor.Init(IEnumerable`1 akkaMetrics) in D:\olympus\akka-monitoring\src\Akka.Monitoring.PerformanceCounters\ActorPerformanceCountersMonitor.cs:116


[TargetInvocationException: Exception has been thrown by the target of an invocation.]

   System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0

   System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +128

   System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +142

   Owin.Loader.<>c__DisplayClass12.<MakeDelegate>b__b(IAppBuilder builder) +93

   Owin.Loader.<>c__DisplayClass1.<LoadImplementation>b__0(IAppBuilder builder) +212

   Microsoft.Owin.Host.SystemWeb.OwinAppContext.Initialize(Action`1 startup) +873

   Microsoft.Owin.Host.SystemWeb.OwinBuilder.Build(Action`1 startup) +51

   Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint() +101

   System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) +135

   Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication context) +160

   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +581

   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +168

   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +277

   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +369


[HttpException (0x80004005): Exception has been thrown by the target of an invocation.]

   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +532

   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +111

   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +714

I couldn’t find a ‘good’ solution to get rid of the error message above. In the end I did 2 things to get rid of the error:

  1. I temporarily gave the application pool accountAdministrator rights on the server.
  2. I gave the application pool account ‘Write’ permissions on the following registry path: Computer\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\

After creating the performance counters on startup, I revoked these permissions.

Anyone with a better solution?

Thursday, September 19, 2019

Access to the registry key 'Global' is denied.

After migrating some .NET applications from an old server to a brand new Windows Server 2019 instance, we stumbled over a range of errors.

Here is the first error we got:

Server Error in '/AppServices' Application.

Access to the registry key 'Global' is denied.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.UnauthorizedAccessException: Access to the registry key 'Global' is denied.

ASP.NET is not authorized to access the requested resource. Consider granting access rights to the resource to the ASP.NET request identity. ASP.NET has a base process identity (typically {MACHINE}\ASPNET on IIS 5 or Network Service on IIS 6 and IIS 7, and the configured application pool identity on IIS 7.5) that is used if the application is not impersonating. If the application is impersonating via < identity impersonate="true"/>, the identity will be the anonymous user (typically IUSR_MACHINENAME) or the authenticated request user.

To grant ASP.NET access to a file, right-click the file in File Explorer, choose "Properties" and select the Security tab. Click "Add" to add the appropriate user or group. Highlight the ASP.NET account, and check the boxes for the desired access.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


[UnauthorizedAccessException: Access to the registry key 'Global' is denied.]

   Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) +144

   Microsoft.Win32.RegistryKey.InternalGetValue(String name, Object defaultValue, Boolean doNotExpand, Boolean checkSecurity) +640

   Microsoft.Win32.RegistryKey.GetValue(String name) +62

   System.Diagnostics.PerformanceMonitor.GetData(String item) +121

   System.Diagnostics.PerformanceCounterLib.GetPerformanceData(String item) +177

   System.Diagnostics.PerformanceCounterLib.get_CategoryTable() +138

   System.Diagnostics.PerformanceCounterLib.CategoryExists(String machine, String category) +72

   System.Diagnostics.PerformanceCounterCategory.Exists(String categoryName, String machineName) +155

   Akka.Monitoring.PerformanceCounters.ActorPerformanceCountersMonitor.Init(IEnumerable`1 akkaMetrics) in D:\olympus\akka-monitoring\src\Akka.Monitoring.PerformanceCounters\ActorPerformanceCountersMonitor.cs:102


[HttpException (0x80004005): Exception has been thrown by the target of an invocation.]

   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +532

   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +111

   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +714


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.3429.0


What’s happening here?

As part of our application initialization, we try to create some performance counters for Akka.Net. As the application is running under the AppPoolIdentity it has no rights to register the performance counters in the registry, explaining the ‘Access to the registry key 'Global' is denied. ‘ error message.

First step to fix this is to add the AppPool account to the Performance Monitor Users group on the server:

Unfortunately we are not there yet, but that is for the next post…

Wednesday, September 18, 2019

Microsoft Orleans - Configure .NET garbage collection

To increase the performance of your Orleans application it is important that you tweak the .NET garbage collection settings. According to the documentation the best settings is a combination of gcServer=true and gcConcurrent=true.

This can be done inside your csproj file by adding the following lines:


Remark: If the changed settings are not picked up immediately, deleting the bin/ and obj/ folders can help. (As mentioned here)

Tuesday, September 17, 2019

Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

After introducing the dynamic keyword in my .NET core codebase, the project failed to compile with the following error message:

Error      CS0656 Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' SOFACore.Messaging              C:\Projects\SOFACore\SOFACore.Messaging\MessagingModule.cs   

To fix it I had to add the Microsoft.CSharp nuget package. This package is necessary to use the C# dynamic data type in a .NET Standard library.

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.


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 value to a non-loopback address. I’ll use but a specific IP address is of course better:

    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 {}, 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, 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:

    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 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](

    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:

    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:

    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: