Ingest .NET framework versions from repositories
This guide demonstrates how to track .NET framework versions across your repositories by ingesting .csproj files into Port.
Each .csproj file becomes its own entity, allowing you to see exactly which framework versions are in use per project and per repository.
Common use cases
- Version standardization: Identify repositories still targeting older .NET versions and drive upgrades.
- Compliance tracking: Use scorecards to flag projects not on supported framework versions.
- Multi-project visibility: See all
.csprojfiles across a repository, each with its own framework version.
Prerequisites
This guide assumes the following:
- You have a Port account and have completed the onboarding process.
- Repositories containing
.csprojfiles with a<TargetFramework>or<TargetFrameworks>element.
- GitLab
- GitHub (Ocean)
- GitLab integration is installed in your account.
- GitHub Ocean integration is installed in your account.
Set up data model
We will create a dedicated blueprint related back to the repository to track the .NET framework versions.
Create net_versions blueprint
-
Go to the Builder page of your portal.
-
Click on
+ Blueprint. -
Click on
{...} Edit JSONat the top right corner. -
Add this JSON schema:
net_versions blueprint (click to expand)
{"identifier": "net_versions","title": ".NET Version","icon": "Service","schema": {"properties": {"dotnet_version": {"type": "string","title": "Target Framework","description": "The .NET target framework extracted from the .csproj file"},"file_path": {"type": "string","title": "File Path","description": "Path to the .csproj file in the repository"}},"required": []},"relations": {"repository": {"target": "githubRepository","title": "Repository","required": false,"many": false}},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {}}Relation targetIf you're using GitHub, change the relation target from
"githubRepository"to"gitlabRepository"(or whichever blueprint represents your repositories). -
Click
Saveto create the blueprint.
Configure the mapping
Add the following mapping to your integration's data source configuration.
This uses the file kind with skipParsing: true (since .csproj files are XML, not JSON/YAML) and extracts the framework version via a JQ regex.
-
Go to your data sources page.
-
Select your Git integration.
-
Add the mapping below:
- GitLab v2
- GitHub (Ocean)
Integration mapping (click to expand)
resources:- kind: fileselector:query: "true"files:path: "*.csproj"# Optional: limit to specific repos (omit to search all groups)repos:- group/my-dotnet-serviceskipParsing: trueport:entity:mappings:identifier: .repo.path_with_namespace + "/" + .file.file_pathtitle: .file.file_nameblueprint: '"net_versions"'properties:dotnet_version: >-.file.content| capture("<TargetFrameworks?>(?<ver>[^<]+)</TargetFrameworks?>")| .verfile_path: .file.file_pathrelations:repository: .repo.path_with_namespaceIntegration mapping (click to expand)
resources:- kind: fileselector:query: "true"files:- path: "**/*.csproj"skipParsing: trueport:entity:mappings:identifier: .repo.name + "/" + .file.pathtitle: .file.nameblueprint: '"net_versions"'properties:dotnet_version: >-.file.content| capture("<TargetFrameworks?>(?<ver>[^<]+)</TargetFrameworks?>")| .verfile_path: .file.pathrelations:repository: .repo.name -
Click on
Resync and Saveand wait for the entities to be ingested in your Port environment.
How the JQ extraction works
The regex <TargetFrameworks?>(?<ver>[^<]+)</TargetFrameworks?> matches both:
<TargetFramework>net8.0</TargetFramework>(single target)<TargetFrameworks>net6.0;net8.0</TargetFrameworks>(multi-target)
The ? after s makes the plural s optional, and capture returns the named group ver containing the version string (e.g., net8.0 or net6.0;net8.0).
This same skipParsing: true + JQ regex approach works for any XML-based manifest file (.nuspec, .fsproj, .props, pom.xml, etc.).
Add aggregation properties
To see a summary of .NET versions at the repository level, add aggregation properties to your repository blueprint.
-
Go to the Builder page and select your Git repository blueprint.
-
Click
...and choose{...} Edit JSON. -
Add the following to the
aggregationPropertiesobject:Aggregation properties JSON (click to expand)
{"csproj_count": {"title": ".csproj file count","target": "net_versions","calculationSpec": {"calculationBy": "entities","func": "count"}},"dotnet_versions_in_use": {"title": ".NET versions in use","target": "net_versions","calculationSpec": {"calculationBy": "property","func": "unique","property": "dotnet_version"}}} -
Click
Saveto update the blueprint.
This gives you a per-repository view showing how many .csproj files exist and the unique set of framework versions in use (e.g., net6.0, net8.0).
Summary
After completing this guide, you will have:
- A
net_versionsblueprint where each entity represents a.csprojfile. - Automatic extraction of the target framework from XML content using JQ regex.
- Repository-level aggregation showing all .NET versions in use.
This pattern generalizes to any XML-based manifest. You can replace the file path and regex to track Java versions from pom.xml, Rust editions from Cargo.toml, or any other framework metadata.