Wednesday, February 28, 2018

ASP.NET Core SignalR– Configure logging

As we don’t have an official release yet of the ASP.NET Core SignalR package, it’s a quest to find the right information in the Github repo. Yesterday I lost some time searching on how to configure logging in SignalR.

To enable logging you have to pass an extra parameter to your HubConnection specifying a loglevel:

Supported log levels are:

Tuesday, February 27, 2018

Debugging websockets in Chrome

Debugging websockets using Chrome turns out to be quite simple.

Here is a step by step guide:

  1. Hit F12 to open the Developer Tools in Chrome

  2. image
  3. Go to the Network tab and select the "WS" filter to only show WebSocket connections.    

  4. image
  5. Open a page where you are using websockets. You should see a request appear in the list.     

  6. Click on the name of the request, and select the tab "Frames".

  7. Messages triggered by your client are shown in green, while messages from the server are white.

  8. clip_image002

Monday, February 26, 2018

Optimize your memory usage when deserializing large JSON objects

During a code review of a customers code base I noticed they were doing a lot of JSON serialization and deserialization actions. As the JSON data was quite large, this caused high memory pressure.  Way to much time was spent in the garbage collector as too many (large) objects were allocated.

To minimize memory usage and the number of objects allocated, Json.NET supports serializing and deserializing directly to a stream.

Here is a code snippet:

Friday, February 23, 2018

jwt-decode - Decode a JWT token in your browser

During the preparation for a training I found the following great utility library; jwt-decode.

jwt-decode is a small browser library that helps decoding JWTs token which are Base64Url encoded.

Installation

I installed the library using

npm install jwt-decode

Usage

As I’m using webpack I was able to include the package using a require

var jwtDecode = require('jwt-decode');
Next step is to take the token and call jwtDecode:
var token = 'eyJ0eXAiO.../// jwt token';

var decoded = jwt_decode(token);
console.log(decoded);
  

Thursday, February 22, 2018

Angular error: Cannot find module '@angular-devkit/core'

Yesterday a colleague asked me for help with the following problem. Angular CLI was working fine on his system(he was using version 1.6.4 on his system), but when he tried to run an Angular project created using an earlier Angular CLI version, he got the following error:

Cannot find module '@angular-devkit/core'

We found 2 solutions that both seemed to work.

Solution 1

Install the @angular-devkit/core package explicitly using 

npm i -D @angular-devkit/core

Solution 2

Upgrade the angular-cli version using

npm update -g @angular/cli

Wednesday, February 21, 2018

Log Parser Studio

The last 2 weeks we had some production issues where an unexpected 401 message was returned from our IIS servers. To further investigate the issue, I got an old tool out of the dust; Log Parser Studio.

Log Parser Studio is a utility that allows you to search through and create reports from your IIS, Event, EXADB and others types of logs. It builds on top of Log Parser 2.2 and has a full user interface for easy creation and management of related SQL queries.

Log Parser Studio allows to query all kinds of log files using a SQL like syntax. It comes out of the box with a large list of sample queries that can help get started.

image

How to use it

  • Open Log Parser Studio(LPS.exe)
  • Click on the New Query button or choose one of the queries from the library

 image

  • A new query window appears

image

  • Now it is time to first specify the LogType. Click on the Log Type link in the middle and choose the correct type from the list:

image

  • Next we have to select the files to query. Click on the Choose Files/folders icon

image

  • The Log File Manager window appears. Here you can use Add Files or Add Folders to add log files.
    • After selecting some files, click OK to return to the Main screen.

image

  • Now it is finally time to execute the query. Click on the Execute button

image

  • After some time(depending on the number of log files and the complexity of the query), the query results are returned:

image

Tuesday, February 20, 2018

ASP.NET Core - IHttpContextAccessor

ASP.NET Core introduces the IHttpContextAccessor interface as a way to provide access to the HttpContext. Before you can use it, you have to register it at application startup inside the IServicesCollection. During a code review I noticed that it was registered like this:

This turns out to be wrong. The IHttpContextAccessor should be registered as a singleton. So the correct code is the following:

More information: https://www.strathweb.com/2016/12/accessing-httpcontext-outside-of-framework-components-in-asp-net-core/

Monday, February 19, 2018

JSON.NET–Resolve private setters

On one of my projects we are using event sourcing as our data persistence strategy. Based on the event stream I build projections using read models.

I prefer to keep my projected read model immutable but turns out that JSON.NET fails to deserialize the state. All properties retain their default values.

A solution is to create a custom contract resolver that uses reflection to set the property values:

Don't forget to apply this contract resolver using the JsonSerializerSettings:

Thursday, February 15, 2018

PostgreSQL–Generate an auto incrementing number on year basis

For an application we are building we had the following requirement:

A unique increasing number should be generated for every document on a year by year basis. So at the end of each year the document counter should be reset to 0 and start to increase again.

As we are using PostgreSQL as our database, I decided to implement this feature using sequences.

First thing I did was creating a function that generates a new sequence based on a specific name:

This allows me to create a new sequence dynamically at the beginning of each year.

Next thing I did was creating another function that will first invoke the f_create_seq function to see if a sequence already exists and then calls this sequence to get the next number in line.

I invoke this function from my application where I pass a year as the sequence name parameter:

Wednesday, February 14, 2018

Stacktrace demystifier

As the C# compiler gets smarter and smarter and more complex features like iterators, generics, async/await are added, our stack traces become more and more unreadible. This is because the .NET stack traces output the compiler transformed methods; rather than the source code methods, which make them slow to mentally parse and match back to the source code.

A library that can help you get more readible stacktraces is Ben.Demystifier.

Let’s try it:

  • Create a new console application. Set the C# target version to 7.1(Instructions here)
  • Include the Ben.Demystifier nuget package
  • Add the following code:
    • Note that we call the exception.Demystify() extension method to generate a better stacktrace.
  • Let’s now run the application first and compare our stacktraces:

The normal stacktrace(with a lot of compiler noise):

  at System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at ConsoleApp1.Program.<Iterator>d__2.MoveNext() in c:\projects\test\ConsoleApp1\ConsoleApp1\Program.cs:line 35
   at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
   at ConsoleApp1.Program.<AsyncCount>d__1.MoveNext() in c:\projects\test\ConsoleApp1\ConsoleApp1\Program.cs:line 28
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at ConsoleApp1.Program.<Main>d__0.MoveNext() in c:\projects\test\ConsoleApp1\ConsoleApp1\Program.cs:line 15

The demystified stacktrace:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at bool System.Collections.Generic.List<T>+Enumerator.MoveNextRare()
   at IEnumerable<string> ConsoleApp1.Program.Iterator(int startAt)+MoveNext() in c:\projects\test\ConsoleApp1\ConsoleApp1\Program.cs:line 35
   at int System.Linq.Enumerable.Count<TSource>(IEnumerable<TSource> source)
   at async Task ConsoleApp1.Program.AsyncCount() in c:\projects\test\ConsoleApp1\ConsoleApp1\Program.cs:line 28
    at async Task ConsoleApp1.Program.Main(string[] args) in c:\projects\test\ConsoleApp1\ConsoleApp1\Program.cs:line 15

Check out the documentation to see the full list of problems with your default stacktraces that this library solves.

Tuesday, February 13, 2018

Rearchitect a monolithic .NET application using microservices

Google goes “all-in” to win the hearth and mind of .NET developers to let them use the Google Cloud Platform. To support this effort they released a set of whitepapers to help you rearchitect your monolithic .NET application using microservices and modernize your authentication, database and caching building blocks.

Here are the whitepapers:

image image

All improvement steps are done on a typical .NET application. You can find the related code in this GitHub repository.

Monday, February 12, 2018

Failed to load resource: the server responded with a status of 400 (Bad Request (Request Header too long))

During development, my web debugging sessios suddenly started to fail with a 400 Bad Request error. I started looking around what I could have done wrong but I couldn’t find any mistake in my code(at least not one that could explain this error).

clip_image002

A search on the Internet brought some insights, the error is probably related to a corrupt website cookie. So I deleted all my cookies and indeed the problem disappeared.

Friday, February 9, 2018

TFS Build - Agent 'AgentName' is using a deprecated version '1.105.7'

A colleague mentioned to me he was the following warning on our build server:

Agent 'AgentName' is using a deprecated version '1.105.7'. You will not be able to use this version of agent with the next major version of Team Foundation Server. Migrate to the latest 2.x version of agent. For more information, see https://go.microsoft.com/fwlink/?linkid=851067.

I was suprised to see this as I recently updated all agents. Still I’m stuck with version 1 agents…

It turns out that there are 2 types of agents:

  1. Windows specific agents having number 1.x
  2. cross platform agents having number 2.x

The thing is that the Update All Agents button will only upgrade to a more recent minor version but will not do an upgrade to a new major version.

If you want to upgrade to a new major version of the agent, you’ll have to uninstall the old agent and install the new one yourself.

Thursday, February 8, 2018

Application Insights–Use a different instrumentation key per environment

By default when you configure Application Insights, the Instrumentation key is hardcoded in the JavaScript snippet

image

and the ApplicationInsights.config:

image

This makes it very hard to integrate your application into your devops pipeline and use different instrumentation keys for different environments(development, test, production).

Let’s see how we can fix this:

  • Start by commenting out the InstrumentationKey setting in the ApplicationInsights.config:

image

  • Instead add an extra appsetting to your web. config. By using the web.config you can use the web.config transformations to inject different instrumentation keys for different environments.

image

  • Now we have to tell Application Insights to use the key specified in our web.config. Therefore add the following line of code to the Application_Start method of the global.asax:
  • As a last step we also have to fix this for the JavaScript snippet injected into our page:

    Wednesday, February 7, 2018

    Configure Application Insights option not shown

    While following the documented steps to configure Application Insights for my ASP.NET MVC website, I was already blocked on the first step:

    • Step 1: Add the Application Insights SDK: Right-click your web app name in the Solution Explorer, and choose Configure Application Insights

    Screenshot of Solution Explorer, with Configure Application Insights highlighted

    But I couldn’t find this option when I right clicked on my project?!

    In Visual Studio 2017, ‘Configure Application Insights’ is no longer a separate option on the context menu. Instead you can access it through the Connected Services:

    • Right click on Connected Services and choose Add Connected Service.

    image

    • Select Monitoring with Application Insights from the list of options.

    image

    • The Application Insights configuration wizard is loaded and you can continue following the documentation.

    image

    Tuesday, February 6, 2018

    ASP.NET Core–Use refresh token to acquire new access token

    In an ASP.NET Core application we are building we are using OpenID Connect Hybrid flow.

    From the Identity Server documentation:

    Access tokens are a bit more sensitive than identity tokens, and we don’t want to expose them to the “outside” world if not needed. OpenID Connect includes a flow called “Hybrid Flow” which gives us the best of both worlds, the identity token is transmitted via the browser channel, so the client can validate it before doing any more work. And if validation is successful, the client opens a back-channel to the token service to retrieve the access token.

    On our ASP.NET Core backend we use the acquired access token to call another API. However as an access token typically has a short lifetime, this only works until the access token is expired.  To refresh our access token, we can use a refresh token to acquire a new access token from our Security Token Service.

    After trying multiple possible solutions, I ended up with an implementation where I use an ASP.NET Core MVC filter to handle this:

    Monday, February 5, 2018

    JetBrains Rider: The specified task executable location "C:\Program Files\dotnet\sdk\2.1.4\Roslyn\RunCsc.cmd" is invalid.

    Last week during a workshop, I got into trouble when trying to use Rider to build my .NET application. The compiler failed with the following error message:

    Microsoft.CSharp.Core.targets(84, 5): [MSB6004] The specified Task executable location "C:\Program Files\dotnet\sdk\2.1.2\Roslyn\RunCsc.cmd" is invalid.

    Compiling in Visual Studio didn’t give any problems.

    Another participant in the workshop noticed I was struggling and told me it was a bug in Rider that was fixed in release v2017.3. (Available here: https://www.jetbrains.com/rider/download/)