Files
Kawa 0c2e26e597 docs: complete project research for SharePoint Toolbox rewrite
Research covers stack (NET10/WPF/PnP.Framework), features (v1 parity + v1.x
differentiators), architecture (MVVM four-layer pattern), and pitfalls
(10 critical pitfalls all addressed in foundation phase). SUMMARY.md
synthesizes findings with phase-structured roadmap implications.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 10:07:47 +02:00

16 KiB

Stack Research

Domain: C#/WPF desktop administration tool for SharePoint Online (multi-tenant MSP) Researched: 2026-04-02 Confidence: HIGH (core framework choices), MEDIUM (charting library)


Core Technologies

Technology Version Purpose Why Recommended
.NET 10 LTS 10.x Target runtime Released November 2025, LTS until November 2028 — the current LTS. Avoid .NET 8 (ends November 2026) and .NET 9 STS (ended May 2026). WPF support is first-class and actively improved in .NET 10.
WPF (.NET 10) built-in UI framework Windows-only per project constraint. Modern MVVM data binding, richer styling than WinForms. The existing codebase uses WinForms; WPF is the correct upgrade path for richer UI.
C# 13 built-in with .NET 10 Language Current language version shipping with .NET 10 SDK.

SharePoint / Microsoft 365 API

Library Version Purpose Why Recommended
PnP.Framework 1.18.0 SharePoint CSOM extensions, provisioning engine, site templates, permissions Directly replaces PnP.PowerShell patterns the existing app uses. Contains PnP Provisioning Engine needed for site templates feature. Targets .NET Standard 2.0 so runs on .NET 10 via compatibility. This is the correct choice for a CSOM-heavy migration — use PnP.Core SDK only when starting greenfield with Graph-first design.
Microsoft.Graph 5.103.0 Microsoft Graph API access (Teams, Groups, users across tenants) Required for Teams site management, user enumeration across tenants. Complements PnP.Framework which is CSOM-first. Use Graph SDK for Graph-native operations; use PnP.Framework for SharePoint-specific provisioning.

Note on PnP.Core SDK vs PnP.Framework: PnP Core SDK is the modern Graph-first replacement for PnP Framework, but PnP Framework is the right choice here because: (1) this is a migration from PnP.PowerShell which is CSOM-based, (2) the PnP Provisioning Engine for site templates lives in PnP.Framework, not PnP Core SDK, (3) the existing feature set maps directly to PnP.Framework's extension methods.

Authentication

Library Version Purpose Why Recommended
Microsoft.Identity.Client (MSAL.NET) 4.83.1 Azure AD interactive browser login, token acquisition The underlying auth library used by both PnP.Framework and Microsoft.Graph SDK. Use directly for multi-tenant session management.
Microsoft.Identity.Client.Extensions.Msal 4.83.3 Token cache persistence to disk Required for multi-tenant session caching — serializes the MSAL token cache to encrypted local storage so users don't re-authenticate on each app launch or tenant switch. PnP.Framework 1.18.0 already depends on this (>= 4.70.2).
Microsoft.Identity.Client.Desktop 4.82.1 Windows-native broker support (WAM) Enables Windows Authentication Manager integration for WPF apps. Provides system-level SSO. Add .WithWindowsBroker() to the PublicClientApplicationBuilder.

Multi-tenant session caching pattern: Create one PublicClientApplication per tenant, serialize each tenant's token cache separately using MsalCacheHelper from Extensions.Msal. Store serialized caches in %AppData%\SharepointToolbox\tokens\{tenantId}.bin. PnP.Framework's AuthenticationManager.CreateWithInteractiveLogin() accepts a custom MSAL app instance — wire the cached app here.

MVVM Infrastructure

Library Version Purpose Why Recommended
CommunityToolkit.Mvvm 8.4.2 MVVM base classes, source-generated commands and properties, messaging Microsoft-maintained, ships with .NET Community Toolkit. Source generators eliminate 90% of MVVM boilerplate. [ObservableProperty], [RelayCommand], [INotifyPropertyChanged] attributes generate all property change plumbing at compile time. The standard choice for WPF/MVVM in 2025-2026.
Microsoft.Extensions.Hosting 10.x Generic Host for DI, configuration, lifetime management Provides IServiceCollection DI container, IConfiguration, and structured app startup/shutdown lifecycle in WPF. Avoids manual service locator patterns. Wire WPF Application.Startup into the host lifetime.
Microsoft.Extensions.DependencyInjection 10.x DI container Included with Hosting. Register ViewModels, services, and repositories as scoped/singleton/transient services.

Logging

Library Version Purpose Why Recommended
Serilog 4.3.1 Structured logging Industry standard for .NET desktop apps. Structured log events (not just strings) make post-mortem debugging of the existing app's 38 silent catch blocks tractable. File sink for persistent logs, debug sink for development.
Serilog.Extensions.Logging 10.0.0 Bridge Serilog into ILogger Allows injecting ILogger<T> everywhere while Serilog handles the actual output. One configuration point.
Serilog.Sinks.File latest Write logs to rolling files %AppData%\SharepointToolbox\logs\log-.txt with daily rolling. Essential for diagnosing auth and SharePoint API failures in the field.

Data Serialization

Library Version Purpose Why Recommended
System.Text.Json built-in .NET 10 JSON read/write for profiles, settings, templates Built into .NET, no NuGet dependency, faster and less memory-hungry than Newtonsoft.Json. Sufficient for the simple config/profile/template structures this app needs. The existing PowerShell app uses JSON — System.Text.Json with source generators enables AOT-safe deserialization, important for self-contained EXE size.

Why not Newtonsoft.Json: Slower, adds ~500KB to the EXE, no AOT support. Only justified when you need LINQ-to-JSON or highly polymorphic deserialization — neither of which applies here.

Data Visualization (Charts)

Library Version Purpose Why Recommended
ScottPlot.WPF 5.1.57 Pie and bar charts for storage metrics Stable, actively maintained (weekly releases), MIT licensed, no paid tier. Supports pie, bar, and all chart types needed. Renders via SkiaSharp — fast even for large datasets. LiveCharts2 is still RC for WPF (2.0.0-rc6.1 as of April 2026) and introduces unnecessary risk. OxyPlot is mature but lacks interactive features and has poor performance on large datasets. ScottPlot 5.x is the stable choice.

Report Generation

Library Version Purpose Why Recommended
CsvHelper latest stable CSV export Industry standard for .NET CSV serialization. Handles encoding, quoting, header generation. Replaces manual string concatenation.
No HTML library needed HTML reports Generate HTML reports via StringBuilder or T4/Scriban text templates with embedded JS (Chart.js or DataTables). Self-contained HTML files require no server. Keep it simple — a ReportBuilder service class is sufficient.

Localization

Library Version Purpose Why Recommended
.NET Resource files (.resx) built-in EN/FR localization ResX is the standard WPF localization approach for a two-language desktop app. Compile-time safety, strong tooling in Visual Studio, no runtime switching complexity. The existing app uses a key-based translation system — ResX maps directly. Use Properties/Resources.en.resx and Properties/Resources.fr.resx. Runtime language switching (if needed later) is achievable via Thread.CurrentThread.CurrentUICulture.

Distribution

Tool Version Purpose Why Recommended
dotnet publish with PublishSingleFile + SelfContained .NET 10 SDK Single self-contained EXE Built-in SDK feature. Set <PublishSingleFile>true</PublishSingleFile>, <SelfContained>true</SelfContained>, <RuntimeIdentifier>win-x64</RuntimeIdentifier>. No third-party tool needed. Expected output size: ~150-200MB (runtime + SkiaSharp from ScottPlot).

Project File Configuration

<PropertyGroup>
  <TargetFramework>net10.0-windows</TargetFramework>
  <UseWPF>true</UseWPF>
  <Nullable>enable</Nullable>
  <ImplicitUsings>enable</ImplicitUsings>
  <!-- Distribution -->
  <PublishSingleFile>true</PublishSingleFile>
  <SelfContained>true</SelfContained>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <!-- Trim carefully — MSAL and PnP use reflection -->
  <PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>

Note on trimming: Do NOT enable PublishTrimmed with PnP.Framework or MSAL.NET. Both libraries use reflection internally and are not trim-safe. The EXE will be larger (~150-200MB) but reliable. Trimming would require extensive [DynamicDependency] annotations and is not worth the effort.


Installation (NuGet Package References)

<!-- SharePoint / Graph API -->
<PackageReference Include="PnP.Framework" Version="1.18.0" />
<PackageReference Include="Microsoft.Graph" Version="5.103.0" />

<!-- Authentication -->
<PackageReference Include="Microsoft.Identity.Client" Version="4.83.1" />
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.83.3" />
<PackageReference Include="Microsoft.Identity.Client.Desktop" Version="4.82.1" />

<!-- MVVM + DI -->
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />

<!-- Logging -->
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />

<!-- Charts -->
<PackageReference Include="ScottPlot.WPF" Version="5.1.57" />

<!-- CSV Export -->
<PackageReference Include="CsvHelper" Version="33.0.1" />

Alternatives Considered

Category Recommended Alternative Why Not
.NET version .NET 10 LTS .NET 8 LTS .NET 8 support ends November 2026 — too soon for a new project to start on
.NET version .NET 10 LTS .NET 9 STS .NET 9 ended May 2026 — already past EOL at time of writing
SharePoint API PnP.Framework PnP Core SDK PnP Core SDK is Graph-first and not yet feature-complete for CSOM-heavy provisioning operations. Wrong choice for a migration from PnP.PowerShell patterns.
MVVM toolkit CommunityToolkit.Mvvm Prism Prism adds module/region/navigation complexity appropriate for large enterprise apps. This is a focused admin tool — CommunityToolkit.Mvvm is leaner and Microsoft-maintained.
Charts ScottPlot.WPF LiveCharts2 LiveCharts2 WPF package is still RC (2.0.0-rc6.1). Unstable API surface is inappropriate for production.
Charts ScottPlot.WPF OxyPlot OxyPlot has poor performance on large datasets and limited interactivity. Low activity/maintenance compared to ScottPlot 5.
JSON System.Text.Json Newtonsoft.Json Newtonsoft.Json adds ~500KB to EXE, is slower, and has no AOT support. Not needed for simple config structures.
Localization ResX (.resx files) WPF ResourceDictionary XAML ResourceDictionary localization is more complex, harder to maintain with tooling, and overkill for a two-language app. ResX provides compile-time safety.
HTML reports T4/StringBuilder Razor / Blazor Hybrid A dedicated template engine adds a dependency for what is a one-time file generation task. StringBuilder or Scriban (lightweight) is sufficient.
Logging Serilog Microsoft.Extensions.Logging (built-in) Built-in logging lacks file sinks and structured event support without additional providers. Serilog is de facto standard for desktop .NET apps.

What NOT to Use

Avoid Why Use Instead
LiveCharts2 WPF Still in RC (2.0.0-rc6.1 as of April 2026) — unstable API, potential breaking changes before 2.0 GA ScottPlot.WPF 5.1.57 (stable, weekly releases)
PnP Core SDK (as primary SharePoint lib) Graph-first design doesn't match the CSOM-heavy provisioning/permissions operations being migrated. The PnP Provisioning Engine is only in PnP.Framework PnP.Framework 1.18.0
Prism Framework Overengineered for this use case. Adds module system, region navigation complexity that doesn't match a single-window admin tool CommunityToolkit.Mvvm 8.4.2
PublishTrimmed=true PnP.Framework and MSAL.NET use reflection and are not trim-safe. Trimming causes runtime crashes Keep trimming disabled; accept larger EXE
.NET 8 as target EOL November 2026 — a new project started now should not immediately be on a near-EOL runtime .NET 10 LTS (supported until November 2028)
SQLite / LiteDB Out of scope per project constraints. JSON is sufficient for profiles, settings, templates. System.Text.Json with file-based storage
DeviceLogin / client secrets for auth Per project memory note: MSP workflow requires interactive login, never DeviceLogin for PnP registration MSAL interactive browser login via WithInteractiveBrowser()
WinForms The existing app is WinForms. The rewrite targets WPF explicitly for MVVM data binding and richer styling WPF

Version Compatibility Notes

Concern Detail
PnP.Framework on .NET 10 PnP.Framework targets .NET Standard 2.0, .NET 8.0, .NET 9.0. It runs on .NET 10 via .NET Standard 2.0 compatibility. No explicit .NET 10 TFM yet (as of April 2026), but the .NET Standard 2.0 path is stable.
MSAL version pinning PnP.Framework 1.18.0 requires Microsoft.Identity.Client.Extensions.Msal >= 4.70.2. Installing 4.83.3 satisfies this constraint. Pin to 4.83.x to avoid drift.
Microsoft.Graph SDK major version Use 5.x only. The 4.x to 5.x upgrade introduced Kiota-generated code with significant breaking changes. Do not mix 4.x and 5.x packages.
CommunityToolkit.Mvvm source generators 8.4.2 introduces partial properties support requiring C# 13 / .NET 9+ SDK. On .NET 10 this is fully supported.
ScottPlot.WPF + SkiaSharp ScottPlot 5.x bundles SkiaSharp. Ensure no version conflict if SkiaSharp is pulled in by another dependency. ScottPlot.WPF 5.1.57 bundles SkiaSharp 2.88.x.

Sources


Stack research for: SharePoint Online administration desktop tool (C#/WPF) Researched: 2026-04-02