Monday, May 3, 2021

Azure DevOps Pipelines - The OutputPath property is not set for project

When trying to build a csproj file using Azure DevOps pipelines, it failed with the following error message:

The OutputPath property is not set for project

The important thing to notice here is that this only happens when pointing the build task to a csproj file instead of a sln file.

Turns out that there is a small difference between how the platform variable is configured at the solution level vs the project level.

These are the variable settings we use inside the build task:

  • $(BuildConfiguration)= “Release”
  • $(BuildPlatform)=”Any CPU”

When I took a look at the csproj file it was expecting “AnyCPU” as the platform setting not “Any CPU”. (Notice the space)

I fixed it by setting the BuildPlatform to “AnyCPU” and not use the build variable for this specific task.

Friday, April 30, 2021

Architecture Weekly

Interested in software architecture?

I discovered ‘Architecture Weekly’, a weekly list of links so you know what to read during the weekend.

Thursday, April 29, 2021

C#–Hide a base class for usage outside an assembly

I created an abstract base class in C# but didn’t want it to be used outside the assembly I created it in.

How can you achieve this?

Your first guess could be to change the access modifier of the base class to internal. When you try to do this you’ll get the following error message:

Inconsistent accessibility: base class 'MyBaseClass' is less accessible than class 'MyInheritedClass'

You have no other choice than to make the abstract class public what makes it visible outside the assembly.

Is there still a way to only allow classes in the same assembly to implement it?

The trick is to make the abstract base class public, but give it an internal default constructor:

This will allow MyBaseClass to be visible outside the assembly, but classes outside the assembly cannot inherit from it.

Tuesday, April 27, 2021

Azure DevOps–Auditing streams

  • Yesterday I blogged about Azure DevOps audit logs.  Although you could export the logs, it was only limited to the last 90 days. To have a full audit log over time, we need to take a different approach through audit streams.

Audit streams represent a pipeline that flows audit events from your Azure DevOps organization to a stream target. Every half hour or less, new audit events are bundled and streamed to your targets. Currently, the following stream targets are available for configuration:

  • Splunk – Connect to on-premises or cloud-based Splunk.
  • Azure Monitor Log - Send auditing logs to Azure Monitor Logs. Logs stored in Azure Monitor Logs can be queried and have alerts configured. Look for the table named AzureDevOpsAuditing. You can also connect Azure Sentinel to your workspace.
  • Azure Event Grid – For scenarios where you want your auditing logs to be sent somewhere else, whether inside or outside of Azure, you can set up an Azure Event Grid connection.

Create a stream

  • Select Organization settings.

  • Select Auditing.

  • Go to the Streams tab, and then select New stream.

  •   Select the stream target that you want to configure.

  • Specify the required fields and click on Set up.

More information:

    Monday, April 26, 2021

    Azure DevOps–Auditing

    A lesser known feature in Azure DevOps Services(it doesn’t exist in Azure DevOps) is the audit log. The audit log contains many changes that occur throughout an Azure DevOps organization. The feature is still in preview and the list of events that are tracked through this feature keeps growing.

    Check the audit logs

    Let’s find out how to check the audit log:

    • Select Auditing from the left menu


    • The auditing page gives you a limited view into the available audit events and recorded data. If you want to access all the data, it is possible to export the data.  Click on the Export log button in the right corner.


    If you can't find the auditing event you're looking for in the following table, be sure to check the REST API:{YOUR_ORGANIZATION}/_apis/audit/actions. Replace {YOUR_ORGANIZATION} with the name of your organization.

    More information:

    Friday, April 23, 2021

    The Art of Computers

    Scott Hanselman is always entertaining but if you are new to programming or not, this is a great talk about some important concepts in IT:

    Thursday, April 22, 2021

    ASP.NET HttpHandler - Concurrent requests

    To solve a specific issue(maybe more about this in another post) we created a custom HttpHandler in ASP.NET. Inside this handler we need access to the session. Therefore we implemented the IRequiresSessionState marker interface:

    The HttpHandler worked as expected until we started to increase the load. We noticed that a lot of requests remained pending…

    This could be traced to the usage of the IRequiresSessionState that put an exclusive lock on the current session. As a consequence the # of concurrent requests for one user are restriced.

    The good news is that another marker interface exists, IReadOnlySessionState, that does not acquire an exclusive lock. In case you only need to read data from the session state and don’t need to change any session data, you can switch to this interface: