Skip to main content


Showing posts from April, 2019

Event Storming Cheat sheet

If you want to organize your own Event Storming workshop, here is a good cheat sheet to get started with: This cheat sheet aims to provide a short opinionated summary of preparing and facilitating an Event Storming Workshop. It is not intended to give a complete introduction to the topic, prior knowledge on DDD and Event Storming is required to make responsible use of this document.

Ionic 4 - There is always a way back

I’m currently working on a PWA using Ionic 4 and I really like the experience so far. After all the struggles with Xamarin and Phonegap this is really a relieve. However every technology has it’s tradeoffs and one of the problems we encountered when using Ionic was the following: We were using the ion-back-button control for our navigation inside the app. From the documentation : The back button navigates back in the app's history upon click. It is smart enough to know what to render based on the mode and when to show based on the navigation This control worked perfectly until the user decides to do a full page refresh(don’t ask why he/she should do that). After a full page refresh the navigation stack is lost and the user is stuck on the current page without any navigation option to go back. Luckily a colleague found a solution and it was all there in the documentation: The ion-back-button has a defaultHref property that can be set to a url. This url is used to

PWABuilder - the simplest way to create progressive web apps across platforms and devices

Last month, a new version the PWABuilder , a community project led by Microsoft was released. PWABuilder is a PWA that easily takes a normal web app / web site and transforms it to a PWA. PWABuilder 2.0 introduces the following new features: A new more user friendly design New snippets to support newer API's such as the Web Share API and the async Clipboard API To get started browse to and enter the URL of your website: After entering an URL, hit start and the PWABuilder app will scan your website for the availability of a manifest, serviceworkers and https, all prerequisites to have a PWA. If any of these things are missing, the tool will report this and provide you with snippets and an example manifest to get started:

Web Development–Force a download of an image instead of opening in new window

You probably all have had the experience where you click on an image link and instead of downloading the image it is previewed in a new browser window. The web wouldn’t be the web if you couldn’t control this behavior. By adding the download attribute on your a tag you can trigger a download instead of a navigation: More info: Unfortunately this doesn’t always work. Firefox and Chrome 65+ only support same-origin download links as a security measure. More info: (see "Known issues" tab) As most of our images are hosted on a separate CDN, we bumped on exactly this issue. To fix this in cross-origin scenario’s, the web server that hosts the image needs to send a  Content-Disposition HTTP header. If this header is found, the download attribute will be honored in all situations. In ASP.NET Core this is easily achieved by using one of the overloads of the File method on the Control

NGen- What assemblies are in my native image cache?

I blogged yesterday about NGen as a way to improve the startup speed of some applications. But I got immediately a follow-up question; how can you see what images are already installed in the native image cache? Let’s find out… The first command you should know is ngen display . This shows all images available in the cache: As the list can be quite large, it is sometimes easier to search if a specific assembly is inside the cache. This can be done by adding (part of) the assembly name to the display command, e.g. ngen display xsltc :

Improve the startup performance of your .NET apps

In our continuous quest to improve the performance of our applications, I found the following ‘trick’ to improve the startup times of your application: Add large assemblies to the NGen cache on the server While profiling our ASP.NET applications, we noticed that some of them took a long time(>15 seconds) to render their first page after a cold start. The problem is that some of the assemblies used inside our application (I’m looking at you Entity Framework!) are quite large. Every time the application restarts, these large assemblies needs to JIT-ted. To avoid the JIT cost, we can create a native image using ngen . The runtime can use these native images from the cache instead of using the just-in-time (JIT) compiler to compile the original assembly. Let’s go through the steps: Login on the server Open an Administrator command prompt Browse to the bin folder of one of the (slow) apps Execute the following command for every DLL you want to add to the NGen c

Finding the right IoC container for you

There are a lot of IoC containers out there in the .NET world. Most of them offer a comparable set of features but they all have there small differences. If you don’t know where to start when picking a container, have a look a the IoC Container Benchmark - Performance comparison article by Daniel Palme. He keeps an up-to-date list of benchmarks for the most popular IoC containers in .NET:

A PackageReference to 'Microsoft.AspNetCore.App' specified a Version of `2.2.0`. Specifying the version of this package is not recommended.

When opening an ASP.NET Core application created by a colleague, I got the following warning: NETSDK1071      A PackageReference to 'Microsoft.AspNetCore.App' specified a Version of `2.2.0`. Specifying the version of this package is not recommended. For more information, see Inside the csproj file, the Microsoft.AspNetCore.App metapackage was referenced using an explicit version number: This turns out not to be a good idea. When using .NET Core 2.1 or 2.2 and referencing Microsoft.AspNetCore.App or Microsoft.AspNetCore.All , the version attribute is unnecessary. The .NET Core SDK can automatically select the version of these packages that should be used. The recommendation is to remove the version number from the PackageReference to get rid of the warning: More information:

IdentityModel - DiscoveryClient is obsolete

In one of our applications we had the following code to fetch a ClientCredentials token from IdentityServer. This access token could then be used to call another API from our backend: After updating the IdentityModel NuGet package to the latest version, we got the following warnings: 'DiscoveryClient' is obsolete: 'This type will be deprecated or changed in a future version. It is recommended that you switch to the new extension methods for HttpClient. They give you much more control over the HttpClient lifetime and configuration. See the docs here: ' 'TokenClient' is obsolete: 'This type will be deprecated or changed in a future version. It is recommended that you switch to the new extension methods for HttpClient. They give you much more control over the HttpClient lifetime and configuration. See the docs here: https://identitymod

Visual Studio 2019 - Migrate from packages.config to PackageReference

Starting from Visual Studio 2017 Version 15.7 there is built-in support for migrating project from the packages.config management format to the PackageReference format. The new format has some advantages like: Only top-level dependencies are listed Performance improvements thanks to the usage of a global-packages folder To migrate from the old to the new format, right-click on a package.config file inside your project and choose Migrate package.config to PackageReference from the context menu. This will load the following view: It gives you a clear view of the identified top-level dependencies, any transitive dependencies and possible compatibility issues. If a package is accidently flagged as transitive you can still promote it to a top-level dependency by hitting the checkbox. I’m currently in the process of migrating a big project and this makes my job so much easier! More information:

Visual Studio Extension - Convert a WPF project to .NET Core 3.0

Brian Lagunas created a nice extension that helps you to convert your existing WPF projects to .NET Core 3.0. After installing the extensions, right click on your WPF project and select the "Convert Project to .NET Core 3" option. Nice one!

Looking for an Entity Framework (Core) alternative? Try XPO.

While reading through some comments on a discussion forum, I noticed a discussion about EF Core. They were talking about a specific feature that was missing(can’t remember the feature). My answer was to try NHibernate but I know that the learning curve is quite steep. Another  person on the forum suggested XPO (eXpress Persistent Objects), a free(!) ORM from DevExpress . From the site: eXpress Persistent Objects (XPO) is an Object-Relational Mapping (ORM) tool that handles all aspects of database creation and object persistence, allowing you to concentrate on your application's business logic rather than database complexities. It offers Code First, Model First and Database First development workflows. Getting started Install the DevExpress XPO nuget package: dotnet add package DevExpress.Xpo Create a new class that inherits from XPLiteObject or XPObject: Configure the XPO data layer: Create a unit of work and execute a query:

C#7.2 –Readonly struct

C# 7.2 introduces the ability to make struct declaration readonly . What does this do? The readonly modifier on a struct definition declares that the struct is immutable . the Every instance field of the struct must be marked readonly , as shown in the following example: It guarantees that no member of the struct can manipulate its content as it ensures every field is marked as readonly . Adding a field not marked as readonly will generate the following compiler error: CS8340 : "Instance fields of readonly structs must be readonly." This guarantee is important because it allows the compiler to avoid defensive copies of struct values.  For example when invoking members of a struct which is stored in a readonly field(like the ToString() method in the example above). Invocations like the ToString now occur directly on the field, avoiding the wasteful copy it had to do before. You can even go one step further by using readonly auto properties . That ins

The power of C#–Porting a C++ app to C#

If you are in doubt about the power of C# and it’s ability to build high speed applications, check out the following blog post by Matt Warren: By using some of the newer language constructs, like the updated Math functions , the support for ref returns and ref locals and the introduction of ref structs , you can get quite far in building high performance C# code…

Reporting Services - “The feature: "Scale-out deployment" is not supported in this edition of Reporting Services.” (again)

During an Azure DevOps Server (TFS) migration, one of the steps I have to execute is the backup and restore of the Reporting Services databases. After reconfiguring the Reporting Services on the new server, I always have to fix the following error message: The feature: “Scale-out deployment” is not supported in this edition of Reporting Services. (rsOperationNotSupported) This is caused by a combination of 2 elements: By restoring the database on a new server, the new server is added to the list of reporting services instances which makes Reporting Services think this is a scaled out deployment Most organisations are using a SQL Server Standard Edition for Azure DevOps Server. This edition does not support ‘Scale-Out' deployments’. My solution to fix this problem was always the same: Unfortunately during my last upgrade I noticed that the Scale-Out Deployment tab wasn’t even

GraphQL.NET - Exporting the GraphQL schema

In case you didn’t notice, I’m a big fan of GraphQL . Most of the time I use GraphQL.NET and more specifically the GraphType first approach; . The disadvantage of this approach is that you don’t have a schema file but that the schema is generated dynamically from your mappings. Why is this a problem? There are a number of tools that expect to work from a schema file and try to import it. Luckily it is not that hard to create some extra middleware that allows us to export the schema from a GraphQL.NET service: To invoke this middleware we add it inside our Startup configuration:

Azure DevOps (Server)–Retrospectives

For most of my projects we just take a picture from our Retrospective result and that’s it. There is no digital trace which makes it hard to find the things decided. Recently I started using Team Retrospectives, an extension for Azure DevOps. So far I liked the experience, but let’s wait for conclusions in a few sprints… From the extension documentation : Team Retrospectives, a Microsoft Garage project, is an extension for Azure DevOps that provides a first-class experience for retrospectives and general feedback board scenarios. Collect feedback on your project milestones, organize and prioritize, and create and track actionable tasks to help your team improve over time. Optimized for both desktop and mobile. Celebrate the good, improve the bad, and increase productivity with Team Retrospectives.  

Visual Studio 2019 - View clipboard ring content

The clipboard ring is not exactly a new feature in Visual Studio. It allows you to copy multiple blocks of code and cycle through them to paste the one you need. I didn’t use it that much because the extra burden of cycling through the list of copied values to find the correct one was waaaay to much for me. In 2019 this experience became a lot better as you can cycle through the content visually when you hit ctrl-shift-v . Remark: This option is also available under Edit Menu > Show Clipboard History .

PII is hidden

While trying to get WSFederation working inside an ASP.NET Core application, I got the following error message: SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'. Hiding the PII seems a good idea from a security perspective but makes it hard to debug this problem. To make the PII visible, you can add the following line of code:

ASP.NET Core - IHostingStartup

ASP.NET Core 2.0 introduces a new interface called IHostingStartup . Through this interface you can manipulate the process of building the web host outside your ASP.NET Core project. Just by including the DLL, you can hook into the configuration pipeline. Implementing IHostingStartup Let’s start by implementing this interface: Create a new .NET Standard Class Library Reference the Microsoft.AspNetCore.Hosting.Abstractions package. This package contains the IHostingStartup interface. Create a new class and implement this interface. Just as an example we add a Console.Writeline to the Configure method: Make the magic work Unfortunately we are not there yet and we have to take some extra steps: First add the HostingStartup attribute to your class library: [assembly: HostingStartup(typeof(ClassLibrary1.MyCustomStartup))] Now the ASP.NET Core runtime has the necessary information where to find our startup inside the DLL. Next step is to setup an envir

SQL Server - Minimize Query Store overhead

I’m a big fan of the Query Store feature in SQL Server. From the documentation: The SQL Server Query Store feature provides you with insight on query plan choice and performance. It simplifies performance troubleshooting by helping you quickly find performance differences caused by query plan changes. Query Store automatically captures a history of queries, plans, and runtime statistics, and retains these for your review. It separates data by time windows so you can see database usage patterns and understand when query plan changes happened on the server. The only problem is that all this extra monitoring and  logging comes with some overhead. If your CPU’s are already going through the roof, enabling the Query store will certainly not help. Instead of turning it back off, I have a better solution for you: By default when you turn on Query Store, Capture Mode is set to All . That means that everything is collected(important data or not). If you change the Capture Mode