Ingest .NET framework versions from repositories
Send this guide to your coding agent.
Prerequisite: Install Port MCP
Open plan mode if your tool supports it; otherwise present the plan below filled in and wait for my approval. Implement this Port guide in my org via MCP: https://docs.port.io/guides/all/ingest-dotnet-framework-versions Read the raw markdown version at https://docs.port.io/guides/all/ingest-dotnet-framework-versions.md - it contains every tab and code block without page markup. Goal: get the guide's core flow working end-to-end in my org; adapting it to fit my existing setup takes priority over matching the guide 1:1. Plan: 1. Confirm MCP is connected, in the right org, with sufficient permissions. 2. If the guide offers alternative implementation paths (tabs), pick the one matching my installed integrations and tools, confirm it with me, and implement only that path. 3. Diff the guide's data model (blueprints, properties, relations, workflows, actions, agents, automations, integrations, webhook data sources, secrets) against mine. 4. Propose adaptations for gaps, reusing existing blueprints/relations over guide-named duplicates. 5. Flag what needs a UI click, credential, or secret from me, testing MCP capability empirically before ruling anything out. If the guide has a "Set up via API" section, use it for anything MCP can't do before treating a step as UI-only. 6. Stop on any blocker and give me options. Approving this plan authorizes the writes it lists; pause only for writes beyond what's listed. Build: - Extend blueprint schema additively when upserting; don't remove or overwrite existing properties, and treat type conflicts as a blocker, not an auto-fix. - Never print secret values into the chat or logs; ask me to set them in Port, or write them via the secrets API without echoing them back. - List any mock data in the plan, minimal and labeled mock; once approved, seed it without re-asking, and tell me what you seeded. - For anything the guide writes downstream (e.g. a webhook target), use a real entity, not a mock. - For pages/widgets, use the real page identifier from the app URL, not a guessed slug. - When you hit a UI step confirmed (not assumed) unsupported via MCP and not covered by the guide's API sections, pause, give exact clicks, then resume via MCP. - Validate and give links after each meaningful step (only a tool-returned URL, no guessed paths); don't proceed if the last run wasn't a success. Done: - Run the guide's "Let's test it" steps where possible (e.g. execute a workflow test run) and confirm the expected output exists in Port. - Summarize adaptations, seeded data, what was mocked or skipped, remaining UI steps, and how to verify.
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 in Port.
-
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.