-
-
Save DocGreenRob/a7f08d56bae684f7f00583f446c27e8a to your computer and use it in GitHub Desktop.
Windows Pro Tips | |
----------------- | |
powertoys - https://apps.microsoft.com/store/detail/microsoft-powertoys/XP89DCGQ3K6VLD | |
devtoys - https://apps.microsoft.com/store/detail/devtoys/9PGCV4V3BK4W | |
Visual Studio 2022 Pro Tips | |
--------------------------- | |
vscoloroutput - https://marketplace.visualstudio.com/items?itemName=MikeWard-AnnArbor.VSColorOutput | |
solutionColor - https://marketplace.visualstudio.com/items?itemName=Wumpf.SolutionColor | |
save vs settings to apply to other computer - https://learn.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2022 | |
Podcasts | |
-------- | |
Dev interrupted | |
Hacking Humans | |
Cyber Security Headlines | |
Click Here | |
Malicious Life | |
The Stack Overflow Podcast | |
The Backend Engineering (with Hussein Nasser) | |
The Changelog: Software Development, Open Source | |
Tech Stuff | |
Cyberwire Daily | |
Techmeme Ride Home | |
Soft Skills Engineering | |
Syntax - Tasty Web Development Treats | |
Cyber Security Today | |
Software Engineering Daily | |
Developer Tea | |
Coding Blocks .NET | |
The Cloud Cast | |
JS Party: Javascript, CSS, Web Development | |
Go Time: Golang, Software Engineering | |
Cyber | |
Dev Questions with Tim Corey | |
Thoughtworks Technology Podcast | |
.NET Rocks! | |
Smashing Security | |
Hanselminutes with Scott Hanselman | |
Software Engineering | |
Talk Python To Me | |
Security Now | |
Darknet Diaries | |
Hacked | |
The .NET Core Podcast | |
The .NET MAUI Podcast | |
Kubernetes Podcast from Google | |
Adventures in .NET | |
Coding After Work | |
Base.cs Podcast | |
The Static Void Podcast | |
Tools | |
------ | |
couchbase | |
honeycomb.io/changelog | |
firehydrant | |
logrocket | |
playwright | |
openmct | |
thundra.io | |
raygun | |
fly.io | |
appwrite | |
sentry.io | |
https://sourcegraph.com/ | |
https://www.kolide.com/ | |
https://entity.services/ | |
WeekPlan | |
Docker Extensions | |
------------------ | |
Ddosify - High-performance load testing tool | |
- https://github.com/ddosify/ddosify | |
BurpSuite | |
- https://portswigger.net/burp | |
- https://danaepp.com/ | |
VS Tips | |
-------- | |
Extract method from selected code | |
- Ctrl + R + M | |
Ctrl + K + D | |
Ctrl + R + G | |
Ctrl + M + Z (Code Maid) | |
Important | |
---------- | |
ApplicationInsights SamplingSettings for AzFn | |
- https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json | |
Design Patterns in C# | |
- https://www.dofactory.com/net/factory-method-design-pattern | |
- https://github.com/DovAmir/awesome-design-patterns?utm_source=programmingdigest&utm_medium&utm_campaign=1493 | |
Shopify Query | |
- https://shopify.engineering/reducing-bigquery-costs?utm_source=programmingdigest&utm_medium&utm_campaign=1403 | |
Building Own Operating System | |
- https://o-oconnell.github.io/2023/01/12/p1os.html?utm_source=programmingdigest&utm_medium&utm_campaign=1493 | |
Debugging Linq | |
- https://www.red-gate.com/simple-talk/development/dotnet-development/linq-secrets-revealed-chaining-and-debugging/ | |
--> https://michaelscodingspot.com/debug-linq-in-csharp/ | |
Bleeping Computer | |
- https://www.bleepingcomputer.com/ | |
Utilities | |
--------- | |
Handle v5.0 | |
- https://learn.microsoft.com/en-us/sysinternals/downloads/handle?WT.mc_id=DT-MVP-5003978 | |
Auto Increment Build # | |
- https://stackoverflow.com/questions/826777/how-to-have-an-auto-incrementing-version-number-visual-studio | |
Phylosophy | |
---------- | |
1. Do I have to have a "purpose" to have an address in the USA? | |
- if yes, then as a Human being I must have a purpose? Seriously? Ok, a purpose to whom? To whom must I state my pupose or execute or report to about...??? | |
2. System Failure - Zero Day Exploit | |
3. Good PR example - https://github.com/dotnet/aspnetcore/pull/45587/files | |
App Insights Log Queries | |
------------------------ | |
availabilityResults | |
| where timestamp > datetime("2022-12-19T04:07:00.000Z") and timestamp < datetime("2022-12-20T04:07:00.000Z") | |
| where customDimensions["WebtestArmResourceName"] == "availability-test-1-app-notepad-physical-activity-dev-eastus" | |
| where true and true | |
| extend percentage = toint(success) * 100 | |
| summarize avg(percentage) by bin(timestamp, 1h) | |
| render timechart | |
****************************************************************** | |
[HttpPatch("api/blandai/callflow/{id}")]
[ProducesResponseType(typeof(Task<IActionResult>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(NotFoundResult), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(UnauthorizedResult), StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> UpdateMaintenanceTimeAsync(string id, JsonPatchDocument<PatchCallFlowDto> jsonPatchDocument)
{
// Before processing the Patch, validate by FluentValidation
//var userDto = await _userService.GetByIdAsync(id).ConfigureAwait(false);
//var roleEntity = _mapper.Map<User>(userDto);
//jsonPatchDocument.Map<PatchUser, User>().ApplyTo(roleEntity);
//userDto = _mapper.Map<UserDto>(roleEntity);
//// TODO: Ensure other controllers' PatchAsync validates the Dto prior to sending to Service
//var validationResult = new UserValidator().Validate(userDto);
//if (!validationResult.IsValid)
//{
// return BadRequest(validationResult.Errors.Select(x => x.ErrorMessage));
//}
var result = await _blandAiManager.PatchCallFlowAsync(id, jsonPatchDocument);
var recordPatchedMessage = new RecordPatchedMessageDto<CallFlowDto>
{
OldRecord = result.Item1,
NewRecord = result.Item2
};
var userProperties = new Dictionary<string, string>
{
{ "CallFlowDto", id }
};
TelemetryClient.TrackEvent($"RecordPatch", userProperties);
return Ok(recordPatchedMessage);
}
public class PatchCallFlowDto
{
public bool? IsNextStepOk { get; set; }
public bool? IsNextStepComplete { get; set; }
}
public async Task<Tuple<CallFlowDto, CallFlowDto>> PatchCallFlowAsync(string id, JsonPatchDocument<PatchCallFlowDto> jsonPatchDocument)
{
if (!long.TryParse(id, out long callFlowId))
{
throw new ArgumentException("Invalid time log id");
}
var blandAiCallFlowEntities = await _unitOfWork.BlandAiCallFlowRepository.GetAsync(x => x.Id == callFlowId);
if (!blandAiCallFlowEntities.Any() || blandAiCallFlowEntities.Count() > 1)
{
throw new ArgumentOutOfRangeException(nameof(id));
}
var blandAiCallFlowEntity = blandAiCallFlowEntities.First();
var originalTimeLogDto = _mapper.Map<CallFlowDto>(blandAiCallFlowEntity);
jsonPatchDocument.Map<PatchCallFlowDto, BlandAiCallFlow>().ApplyTo(blandAiCallFlowEntity);
blandAiCallFlowEntity.UpdatedByUser = Constants.UserEmail;
blandAiCallFlowEntity.UpdatedDate = DateTime.UtcNow;
Expression<Func<Project, bool>> expression = x => x.Id == blandAiCallFlowEntity.Id;
await _unitOfWork.BlandAiCallFlowRepository.UpdateAsync(blandAiCallFlowEntity).ConfigureAwait(false);
await _unitOfWork.BlandAiCallFlowRepository.SaveAsync().ConfigureAwait(false);
return new Tuple<CallFlowDto, CallFlowDto>(originalTimeLogDto, _mapper.Map<CallFlowDto>(blandAiCallFlowEntity));
}
CreateMap<BlandAiCallFlow, Common.Dto.External.BlandAi.CallFlowDto>().ReverseMap();
public class RecordPatchedMessageDto<T>
{
public T OldRecord { get; set; }
public T NewRecord { get; set; }
public string TypeName { get; set; }
}
public static class JsonPathDocumentExtensions
{
public const string InvalidPatchDocumentCode = "InvalidPatchDocument";
public const string InvalidPatchDocumentProperty = "JsonPatchDocument";
private static readonly ConcurrentDictionary<Type, ConstructorInfo> _defaultConstructors = new ConcurrentDictionary<Type, ConstructorInfo>();
private static readonly ConcurrentDictionary<Type, IValidator> _validators = new ConcurrentDictionary<Type, IValidator>();
public static JsonPatchDocument<TOut> Map<TIn, TOut>(this JsonPatchDocument<TIn> instance)
where TIn : class, new()
where TOut : class, new()
{
return new JsonPatchDocument<TOut>(instance.Operations.Select(x => x.Map<TIn, TOut>()).ToList(), instance.ContractResolver);
}
public static Operation<TOut> Map<TIn, TOut>(this Operation<TIn> instance)
where TIn : class, new()
where TOut : class, new()
{
return new Operation<TOut>(instance.op, instance.path, instance.from, instance.value);
}
}
{
"op": "replace",
"path": "/OwnerBudget",
"value": 350000
}
]
You're getting this error in Dev but not Local:
"The instance of entity type 'AssessmentItem' cannot be tracked because another instance with the same key value for {'AssessmentItemId'} is already being tracked."
This is an Entity Framework Core error that occurs when two separate instances of an entity with the same primary key are being tracked in the same DbContext
. Let’s break it down:
✅ Why It Happens
EF Core enforces a one tracked instance per primary key rule. If you:
- Load an entity (e.g., from a query), then
- Later
Attach
orInsert
another entity with the same primary key, EF will throw this error.
📍 Most Likely Cause in Your Code
You're doing:
var serializedCurrentAssessmentItemEntity = JsonConvert.SerializeObject(assessmentItemEntity);
var newAssessmentItemEntity = JsonConvert.DeserializeObject<AssessmentItem>(serializedCurrentAssessmentItemEntity);
...
newAssessmentItemEntity.AssessmentItemId = 0; // so it becomes a "new" insert
BUT LATER, this logic is violated here:
var asdf = await unitOfWork.AssessmentItemRepository.FindByAsync(...);
// If asdf is not null, you do:
await unitOfWork.AssessmentItemRepository.UpdateAsync(asdf);
If asdf
is already being tracked AND you’re also tracking a new instance with the same AssessmentItemId
, this will trigger the error.
And worse: your object graphs (sections, assessmentItems) might carry references to previously tracked entities from deserialization.
✅ Fix (3 Options)
Option 1: Use .AsNoTracking()
Anywhere you're querying for something that you don’t plan to update, make sure to use .AsNoTracking()
to avoid the DbContext tracking that entity.
Update your repository to support it:
// In your repository FindByAsync or FindAllByAsync:
var query = dbContext.Set<T>().AsQueryable();
if (asNoTracking)
query = query.AsNoTracking();
Use it like:
var currentAssessmentEntity = await unitOfWork.AssessmentRepository
.FindByAsync(x => ..., cancellationToken, asNoTracking: true);
Option 2: Use Detach()
before reusing the entity
Before reinserting deserialized copies or updating found ones, you can manually detach tracked entities like:
context.Entry(existingEntity).State = EntityState.Detached;
Or detach the whole context (not usually recommended).
Option 3: Use a clean DbContext
scope
Instead of reusing a long-living DbContext that accumulates tracked state, do:
using (var scope = new TransactionScope(...))
{
using (var newContext = new MyDbContext())
{
// work with clean context
}
}
You can also do it with IServiceScopeFactory
if using DI.
🕵️ Why This Works in Local But Not in Dev?
Because your Dev likely uses different EF configuration, possibly:
- SensitiveDataLogging is off (you should enable it in Dev temporarily)
- Different lifetime for
DbContext
(Scoped vs Singleton) - Different records already in Dev that aren’t in local, triggering entity tracking conflict when resolving duplicates
✅ Suggested Next Steps
- Enable this for clearer logs in Dev:
optionsBuilder.EnableSensitiveDataLogging();
-
Update all your repo
FindBy
andFindAllBy
to supportAsNoTracking
. -
During cloning, ensure you're only attaching new objects (with
Id = 0
) or objects that EF is not already tracking.
Want me to give you a diff of which repo queries to apply AsNoTracking()
to based on the code above?
Podcasts
Syntax 7/21/25
AI Tools
VS Code --> Windsurf --> Cursor
CLI Agents
- Claude Code
Setup...
1. Docker Setup
Download and install Docker Desktop - link
- if forced to restart, launch Docker Desktop
- if you get an error about Windows Subsystem for Linux, in Powershell (as Admin) run
wsl --update
2. SonarQube Setup
docker run -d --name sonarqube -p 9000:9000 -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true sonarqube:latest
!! If you get a port error
docker: Error response from daemon: ports are not available: exposing port TCP 0.0.0.0:9000 -> 127.0.0.1:0: listen tcp 0.0.0.0:9000: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.
then you can either:
-
Kill the port:
a. Find out what's running on port9000
:
netstat -aon | findstr :9000
then you will see:
TCP 0.0.0.0:9000 0.0.0.0:0 LISTENING 13388
TCP 127.0.0.1:9000 0.0.0.0:0 LISTENING 13388
TCP 127.0.0.1:9000 127.0.0.1:50528 TIME_WAIT 0
TCP 127.0.0.1:9000 127.0.0.1:64865 ESTABLISHED 13388
TCP 127.0.0.1:50530 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:50531 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:50533 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:50541 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:50554 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:50566 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:50579 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:63479 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:63484 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:63509 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:63510 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:63517 127.0.0.1:9000 TIME_WAIT 0
TCP 127.0.0.1:64865 127.0.0.1:9000 ESTABLISHED 14204
TCP 172.17.1.214:9000 20.37.135.94:50549 ESTABLISHED 13388
TCP 172.17.1.214:9000 20.59.87.225:64896 ESTABLISHED 13388
TCP 172.17.1.214:9000 20.59.87.226:57486 ESTABLISHED 13388
TCP 172.17.1.214:9000 20.169.174.231:63252 ESTABLISHED 13388
TCP 172.17.1.214:9000 23.33.29.208:63447 TIME_WAIT 0
TCP 172.17.1.214:9000 23.193.200.119:63254 ESTABLISHED 13388
TCP 172.17.1.214:9000 40.82.248.226:50571 ESTABLISHED 13388
TCP 172.17.1.214:9000 40.82.248.226:50575 ESTABLISHED 13388
TCP 172.17.1.214:9000 40.82.248.226:63425 TIME_WAIT 0
TCP 172.17.1.214:9000 40.126.27.66:63368 FIN_WAIT_2 13388
TCP 172.17.1.214:9000 52.96.16.162:63357 ESTABLISHED 13388
TCP 172.17.1.214:9000 52.96.119.194:61662 ESTABLISHED 13388
TCP 172.17.1.214:9000 52.109.8.89:50559 ESTABLISHED 13388
TCP 172.17.1.214:9000 52.109.16.87:62244 ESTABLISHED 13388
TCP 172.17.1.214:9000 52.152.143.207:63434 ESTABLISHED 13388
TCP 172.17.1.214:9000 52.152.143.207:63501 ESTABLISHED 13388
TCP 172.17.1.214:9000 52.179.73.37:63334 ESTABLISHED 13388
TCP 172.17.1.214:9000 54.149.170.228:64213 ESTABLISHED 13388
TCP [::]:9000 [::]:0 LISTENING 13388
UDP 0.0.0.0:9000 *:* 13388
UDP [::]:9000 *:* 13388
The Process ID is the last column (i.e., 13388)
b. Then you can kill it by taskkill /PID 13388 /F
or...
- you can use another port (which is what I'm doing)
docker run -d --name sonarqube -p 9001:9000 -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true sonarqube:latest
! If you get this error:
docker: Error response from daemon: Conflict. The container name "/sonarqube" is already in use by container "656085e89c234748d11cbdd41aaa2ece8ad3aa44f809702660eb4db88f271602". You have to remove (or rename) that container to be able to reuse that name.
Now run docker rm -f sonarqube
to remove it
Then run:
docker run -d --name sonarqube -p 9001:9000 -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true sonarqube:latest
This spins up SonarQube on http://localhost:9000.
3. Get your SonarQube Token
- Go to: http://localhost:9000/
- Default credentials:
• Username: admin
• Password: admin - Click on "Account" icon in upper right
- Click "My Account"
- Select the "Security" tab at the top
- Proceed to "Generate Token" as per your needs. (Set the Token Type to "User" from the Dropdown list)
4. SonarScanner
- Download 👉 https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/
- Extract & Add to PATH
- Unzip the contents (e.g., to
C:\SonarScanner
) - Then add the bin folder to your PATH environment variable:
- Press ⊞ Win → search "Environment Variables"
- Click “Edit the system environment variables”
- Click “Environment Variables”
- Under System Variables → select Path → click Edit
- Add:
C:\SonarScanner\bin
(or wherever you extracted)
- Test the Install
- Open a new terminal (so it reloads the PATH) and run:
sonar-scanner -v

5. Install support for .NET
Temporarily disable CPS Nuget feed to avoid the 401 error in the next step
dotnet nuget list source
- You should see a response like:
Registered Sources:
1. nuget.org [Enabled]
https://api.nuget.org/v3/index.json
2. CPS [Enabled]
https://pkgs.dev.azure.com/ComprehensivePharmacyServices/_packaging/ComprehensivePharmacyServices%40Local/nuget/v3/index.json
3. Microsoft Visual Studio Offline Packages [Enabled]
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
dotnet nuget disable source "CPS"
dotnet tool install --global dotnet-sonarscanner
dotnet nuget enable source "CPS"
verify it works:
dotnet sonarscanner --version

6. PAT for NuGet feed access
- Go to Projects - Home

7. Support for internal NuGet feeds
dotnet nuget update source CPS --source https://pkgs.dev.azure.com/ComprehensivePharmacyServices/_packaging/ComprehensivePharmacyServices%40Local/nuget/v3/index.json --username [email protected] --password PERSONAL_ACCESS_TOKEN__PAT --store-password-in-clear-text
** If needed, this will show all your nuget packages in the solution/project dotnet nuget list source
8. Install coverlet.collector
-
C:\...PATH_TO_TEST_PROJECT> dotnet add package coverlet.collector --source https://api.nuget.org/v3/index.json
-
C:\...PATH_TO_TEST_PROJECT> dotnet add package coverlet.msbuild --source https://api.nuget.org/v3/index.json
-
C:\...PATH_TO_TEST_PROJECT> dotnet clean
#Running...
Setup Code Coverage analysis
-
dotnet nuget disable source "CPS"
-
dotnet tool install --global dotnet-sonarscanner
-
C:\...PATH_TO_TEST_PROJECT> dotnet tool install --global dotnet-reportgenerator-globaltool
-
dotnet nuget enable source "CPS"
-
In VisualStudio rebuild your solution
-
C:\...PATH_TO_SOLUTION>
dotnet test CPS.RxAssess.Business.Tests/CPS.RxAssess.Business.Tests.csproj --no-build /p:CollectCoverage=true /p:CoverletOutput=./TestResults/coverage.opencover.xml /p:CoverletOutputFormat=opencover

Running a scan locally...
-
C:\...PATH_TO_SOLUTION> dotnet sonarscanner begin /k:"AccountingAssistant2" /d:sonar.host.url="http://localhost:9000" /d:sonar.token="SONARQUBE_TOKEN" /d:sonar.cs.opencover.reportsPaths="AccountingAssistant.Api.Tests/TestResults/coverage.opencover.xml"
-
C:\...PATH_TO_SOLUTION> dotnet build CPS.RxAssess.sln
-
C:\...PATH_TO_SOLUTION> dotnet sonarscanner end /d:sonar.token="SONARQUBE_TOKEN"
See results
- Go to
http://localhost:9000/dashboard?id=AccountingAssistant2
Supercharger:
tt4e2HN4X3gO09PJIuXK5ZOviuyQORn77YtQ3fsLyPAcScMg3qFGj+8KgLLQr0WWggKFxnyEAezbDaT6Uiyb4N3WzHvKoMl5S24i/eQCCCYQdCeroyqE12g3h7ro3v8sCwKOA10kfQy
The first line should be a single line summary with no more than 50 characters.
The second line should be blank.
Start the full summary on the third line. Ignore whitespace changes in the summary. Use bullet points for each line in the summary when describing changes.
import { AfterViewInit, Component, Input, OnInit } from '@angular/core';
import { CommunicationService } from '../../../services/_internal/communication/communication.service';
import { SessionDataService } from '../../../services/_internal/session-data/session-data.service';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-global-spinner',
standalone: true,
imports: [CommonModule],
templateUrl: './global-spinner.component.html',
styleUrl: './global-spinner.component.scss'
})
export class GlobalSpinnerComponent implements OnInit, AfterViewInit {
// *********************
// variables declaration
// *********************
// private
// ********
// public
// ******
@Input() spinnerText: string = "Searching...";
constructor(private sessionDataService: SessionDataService,
private communicationService: CommunicationService) {
}
// ***************
// lifecycle hooks
// ***************
ngOnInit(): void {
this.housekeeping();
}
ngAfterViewInit(): void {
}
// *******
// methods
// *******
// public
// ******
// private
// *******
private housekeeping() {
}
}
RxProcessManagerLocalTest
Set WshShell = CreateObject("WScript.Shell")
Do
WshShell.SendKeys "{SCROLLLOCK}"
WScript.Sleep 60000 ' 60 seconds
Loop
cscript //nologo RxProcessManagerLocalTest.vbs
What you're seeing is likely a combination of Roslyn analyzers + editor config + stylecop settings, and possibly code analysis rules configured to treat warnings as errors in that project.
Here’s how to trace and port that setup:
✅ 1. Look for
.editorconfig
in the project rootThis file governs most style and formatting rules now (replacing
ruleset
files in many modern .NET projects).Open it and look for things like:
👉 Copy this file into the root of your personal project(s) to carry over the rules.
✅ 2. Check for Roslyn Analyzers in
.csproj
In your
.csproj
, check if there’s a reference to something like:These are NuGet packages enforcing coding rules. If present, copy them to your personal
.csproj
.You might also see:
This line converts specific warnings into compile-breaking errors. Copy this too.
✅ 3. Check for ruleset files (older projects)
Some older projects still use
.ruleset
files:.csproj
or right-click the project → Properties → Code Analysis.ruleset
file path.If you see it, copy that file and the reference in the
.csproj
.✅ 4. Copy recommended StyleCop settings (if missing)
If you’re missing StyleCop, you can install and configure it like this:
Then add or adjust
.editorconfig
like:✅ 5. Optional: Use
Directory.Build.props
to share across projectsIf you want all your projects to inherit these rules, create a
Directory.Build.props
file at a higher folder level with shared package references and settings.✅ Summary: What to Copy
.editorconfig
.ruleset
(if applicable)StyleCop.Analyzers
orMicrosoft.CodeAnalysis.*
<WarningsAsErrors>
or<AnalysisLevel>
in.csproj
Directory.Build.props
overridesLet me know if you want me to generate a clean baseline
.editorconfig
and.csproj
with strict rules for your own projects. I can tailor it exactly like the one your customer uses.