Health middleware in AspnetCore, or rather Dotnet6 throws TaskCanceledException

January 21st, 2022

I added some health check to my aspnet site to trigger from Kubernetes startupProbe and sometimes got

{
	"EventId": 1,
	"LogLevel": "Error",
	"Category": "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",
	"Message": "An unhandled exception has occurred while executing the request.",
	"Exception": "System.Threading.Tasks.TaskCanceledException: A task was canceled.    
        at Microsoft.Extensions.Diagnostics.HealthChecks.DefaultHealthCheckService.CheckHealthAsync(Func`2 predicate, CancellationToken cancellationToken)    
        at Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckMiddleware.InvokeAsync(HttpContext httpContext)    
        at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)    
        at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)    
        at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)",
	"State": {
		"Message": "An unhandled exception has occurred while executing the request.",
		"{OriginalFormat}": "An unhandled exception has occurred while executing the request."
	}
}

There is nothing in my health checking code that can throw (famous last words…). In the stack above there is none of my code.

There might be a call to cancel that results in a TaskCanceledException or something with authentication/authorisation as can be seen in the stack.

To make a long story short I moved the calls to UseHealthCheck from below UseEndpoints to above UseAuthentication as my endpoints are anonymous (they are very lightweight).

app.UseRouting();

app.UseHealthChecks("/api/article/health/alive", new HealthCheckOptions
{
    Predicate = check => true
});
app.UseHealthChecks("/api/article/health/ready", new HealthCheckOptions
{
    Predicate = check => true
});
app.UseHealthChecks("/api/article/health/startup", new HealthCheckOptions
{
    Predicate = check => true
});

app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

Sanity check, nykterhetstest

October 6th, 2021

In a (unit) test I sometimes add extra tests to check the test tests what is anticipated.

user = new User(Id="A", Name = "N1")
sut.Create(user)
saved = sut.Get("A")

saved.Name.Should.Be("N1", "Sanity check we know what we have stored.")

// Act.
sut.Clear("A")

// Assert.
result = sut.Get("A")
result.Name.Should.Be(null)

Notice the “sanity check” to verify a bug didn’t set Name to null when creating the user.

My naming convention is “Sanity check” or “Nykterhetskontroll” in Swedish.
[I know the translation, word per word, is incorrect.]

Azure devops tests fail with very little clue

September 9th, 2021

I updated some references in my Azure Devops build and got the following error in the unit testing task:

...
##[error]Error: The process '/opt/hostedtoolcache/dotnet/dotnet' failed with exit code 1 
Result Attachments will be stored in LogStore 
Run Attachments will be stored in LogStore 
No Result Found to Publish '/home/vsts/work/_temp/_fv-az101-233_2021-09-09_10_21_12.trx'. 
No Result Found to Publish '/home/vsts/work/_temp/_fv-az101-233_2021-09-09_10_21_17.trx'. 
No Result Found to Publish '/home/vsts/work/_temp/_fv-az101-233_2021-09-09_10_21_24.trx'. 

##[warning].NET 5 has some compatibility issues with older Nuget versions(<=5.7), so if you are using an older Nuget version(and not dotnet cli) to restore, then the dotnet cli commands (e.g. dotnet build) which rely on such restored packages might fail. To mitigate such error, you can either: (1) - Use dotnet cli to restore, (2) - Use Nuget version 5.8 to restore, (3) - Use global.json using an older sdk version(<=3) to build 
Info: Azure Pipelines hosted agents have been updated and now contain .Net 5.x SDK/Runtime along with the older .Net Core version which are currently lts. Unless you have locked down a SDK version for your project(s), 5.x SDK might be picked up which might have breaking behavior as compared to previous versions. You can learn more about the breaking changes here: https://docs.microsoft.com/en-us/dotnet/core/tools/ and https://docs.microsoft.com/en-us/dotnet/core/compatibility/ . To learn about more such changes and troubleshoot, refer here: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops#troubleshooting 

##[error]Dotnet command failed with non-zero exit code on the following projects : 
Async Command Start: 
Publish test results Publishing test results to test run '1136330'.
...

Especially the last, “Dotnet command failed … on the following projects” does not give the clue I am looking for. What failed?

To cut a long story short: One of my test project lacked reference to Microsoft.NET.Test.Sdk.

A longer story is that I updated from xunit.runner.visualstudio from 2.4.1 to 2.4.3 and it doesn’t have a reference to the Microsoft.Net.Test.Sdk project as it is no longer Visual studio that holds the reference but the project itself. The clues I got were from https://github.com/xunit/visualstudio.xunit/issues/219 and https://github.com/xunit/visualstudio.xunit/issues/259 in no special order.

Error message “Can’t bind to ‘ngIf’ since it isn’t a known property of ‘div'” solved

June 11th, 2021

When testing a component in Angular you might receive the follwoting warning:

Can’t bind to ‘ngIf’ since it isn’t a known property of ‘div’

It might depend on you not declaring the component-under-test.

See this repo.

describe('AppComponent', () => {
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       imports: [
         RouterTestingModule
       ],
       declarations: [
         AppComponent
       ],
     }).compileComponents();
   });
   it('should create the app', () => {
       const fixture = TestBed.createComponent(AppComponent);
       const app = fixture.componentInstance;
       expect(app).toBeTruthy();
     });
 });

The code is slightly different than the boiler plate Angular/Jasmine test code but still visualises the issue.

The row

const fixture = TestBed.createComponent(AppComponent);

Creates a component that must be declared in

declarations: [
  AppComponent
],

It took me an hour to find it due to code being convoluted.
If it saves you 5 minutes, it was worth writing this post.

When programming we should have 1 based index

December 21st, 2020

It is a bold statement.

Well… is it?

IIRC the most usual, unwanted, exception we get is null reference error.
The second is off-by-one error.

The off-by-one error is the result of us programmers on remembering to subtract one from an index, or subtracting once too many.

Alas we should have 1 based index, like natural language, and let the computer do the subtraction.

What…? That is not how computers work!

No.

But that is how Humans work.

It is many years since we stopped arguing that a computer wants its data layed out such and therefore we adopt to it. Today we try to solve business problems, not computer problems (your domain may vary). We use higher level language. We name our variables after the domain. We use domain language.

We do not ask the customer for the zeroth invoice. And when we ask for the 2nd invoice we expect the 2nd invoice in a list.

The reason for 0 based index is, I believe, a historical technical reason.

When programming assembler, it is easy to point to a memory position and then add an index. Hence having a zero based index is a natural thing; we solve a computer problem.
Then C, a higher level language, comes along. It is way above assembler but is till constructed to be close to the physical machine to be easy to implement on any processor. By that time we still solved computer problems and keeping a zero based index was probably a no brainer.

Then came Java and C#. They try to look like C/C++ due to reasons of not-thinking-things-through and it-is-easier-to-not-move-the-cheese. They keep the zero based index even though they didn’t have to. So now we are stuck with it.

Until either 1) we invent a new operator

1
myArray@1
or
1
myArray/1/
or 2) invent a yet new language.

Until then: Keep spreading the word that we should have a 1 based index.

Write (arrange) Act and Assert in your automatic tests

November 14th, 2020

It is a good custom to write out Act and Assert in test as it helps to write the test in a clean way; and helps the next reader to understand where Arrange stops and Act begins. It helps the writer to not involuntarily write Act statements in Assert.
Like so:

myTest()
sut = setup()

// Act.
sut.do()

// Assert.
assert(sut.value).equals(12)

The above code is too simple to make the upside of this coding standard visible but soon tests get a few lines long and commentning Act and Assert is a good idea.

I don’t bother to write out // Arrange any more as all tests start with Arrange anyway.

Well… that was not true. I have stumbled upon tests with several Arrange, Act and Assert in them. Typically for integration tests.

Tip: fail explicitly during developing a test

August 17th, 2020

When figuring out how to write a test – add an assert that always fails in the bottom. Remove it when you know the test works as it should.

Why: Because you might get interrupted to spend energy on something else. When you get back the test shines red and you know where to continue. No risk of sending sub par test code to a PR.

I start Domain names with capital letter

July 12th, 2020

When writing comments, and documentation, I usually write domain names with a capital start letter.

// Persist the Customer in the next layer.

// Group all Orders by their Packaging-type.

The Customer database is co-located with the Project database. The common key is a string.

Running the Adobe XD viewer gives me 9! new processes

June 4th, 2020

I wondered why my laptop fan kicked in whenever I started the Adobe XD viewer. So I checked Task managter and found 9 processes!
When I killed the processes another one, a crash recovery process started.

To top it of I got 3 processes for autostart, running whether I have started the XD viewer or not.
Or maybe 6, depending on where you look and what you look for.

I have disabled 3 tasks in Task manager->Startup
but whenever I start the machine there are 3 processes from Adobe running.
So, through Sysinternals’ autoruns I find 6+2+5 autostarts and various settings. I have not delved into what is running processes and what “just another” setting.

As a viewer it is quite hefty.

As if the computer, Dell, with latest version of Windows, and Microsoft bloat ware was not enough…

I am running Windows10. I don’t know what the XD viewer looks like on MacOS.

In Adobe’s defence I have not measured the memory and cpu and power consumption impact.
On the other hand I have not checked what else Adobe has done, like installing programs that are not so easily linked to adobe (svchost) or bogging down the machine in other ways (hard disk, changing order of processes in the network pipe) or what it does when it calls home.

tags: , , | categories: Miscellaneous | no comments »

Starting an Aspnet core site on IISExpress

April 16th, 2020

One cannot point at a folder and just start, as we did with the full framework. There seems to be several solutions for Core and the one described here requires a publish. (Visual studio 2017:menu->Build->Publish)

Publishing a dotnet core site copies relevant parts to a folder

"path\iisexpress.exe" /path:"path\site\bin\Debug\netcoreapp2.2\publish" /port:betweenmagicalnumbers

Here is the exact command I recently used.

"C:\Program Files\IIS Express\iisexpress.exe" /path:"C:\DATA\PROJEKT\Lagardsdorren\Lagardsdorren\bin\Debug\netcoreapp2.2\publish" /port:44342

The port number is limited to 44300 to 44399 to avoid having to start Visual studio with elevated privileges. Reference.

Do not walk the path with “..” as you get an “Invalid physical path.” error.

Set an environment variable to give better debug output. Reference.

$Env:ASPNETCORE_ENVIRONMENT = "Development"