From ac0592291a2fb677b00e9ae588e5e615d5a5706a Mon Sep 17 00:00:00 2001 From: Tyler Pooschke Date: Thu, 2 Jul 2026 08:55:33 -0500 Subject: [PATCH] Upgrade to .NET 8 --- .github/upgrades/dotnet-upgrade-plan.md | 64 ++ src/.github/copilot-instructions.md | 3 + .../Properties/AssemblyInfo.cs | 55 -- .../Services/Telemetry/TelemetryService.cs | 8 +- .../Services/Updating/UpdaterService.cs | 34 +- .../Services/Vsts/FilesBasedTokenCache.cs | 88 +-- .../Services/Vsts/VstsAdalService.cs | 60 +- src/Stutton.DocumentCreator/Setup.cs | 5 +- .../Stutton.DocumentCreator.csproj | 662 +----------------- .../Views/Documents/Steps/WorkItemStep.xaml | 15 +- .../Views/Pages/DocumentsPage.xaml | 15 +- .../Views/ShellView.xaml | 2 +- src/Stutton.DocumentCreator/gitversion.json | 35 + 13 files changed, 205 insertions(+), 841 deletions(-) create mode 100644 .github/upgrades/dotnet-upgrade-plan.md create mode 100644 src/.github/copilot-instructions.md delete mode 100644 src/Stutton.DocumentCreator/Properties/AssemblyInfo.cs create mode 100644 src/Stutton.DocumentCreator/gitversion.json diff --git a/.github/upgrades/dotnet-upgrade-plan.md b/.github/upgrades/dotnet-upgrade-plan.md new file mode 100644 index 0000000..8e03a1f --- /dev/null +++ b/.github/upgrades/dotnet-upgrade-plan.md @@ -0,0 +1,64 @@ +# .NET 8.0 Upgrade Plan + +## Execution Steps + +Execute steps below sequentially one by one in the order they are listed. + +1. Validate that a .NET 8.0 SDK required for this upgrade is installed on the machine and if not, help to get it installed. +2. Ensure that the SDK version specified in global.json files is compatible with the .NET 8.0 upgrade. +3. Upgrade Stutton.DocumentCreator\Stutton.DocumentCreator.csproj + +## Settings + +This section contains settings and data used by execution steps. + +### Excluded projects + +| Project name | Description | +|:-----------------------------------------------|:---------------------------:| +| (none) | | + +### Aggregate NuGet packages modifications across all projects + +NuGet packages used across all selected projects or their dependencies that need version update in projects that reference them. + +| Package Name | Current Version | New Version | Description | +|:----------------------------------------------------|:---------------:|:-----------:|:-------------------------------------------------------------------| +| GitVersionTask | 5.5.1 | | Deprecated. Replace with GitVersion.MsBuild | +| GitVersion.MsBuild | | 5.5.1 | Replacement for GitVersionTask | +| Microsoft.ApplicationInsights | 2.16.0 | 3.1.2 | Deprecated version, upgrade to latest | +| Microsoft.IdentityModel.Clients.ActiveDirectory | 5.2.8 | | Deprecated. Replace with Microsoft.Identity.Client | +| Microsoft.Identity.Client | | 4.67.2 | Replacement for Microsoft.IdentityModel.Clients.ActiveDirectory | +| Microsoft.Xaml.Behaviors.Wpf | | 1.1.135 | Replacement for System.Windows.Interactivity.WPF | +| Newtonsoft.Json | 12.0.3 | 13.0.4 | Recommended for .NET 8.0 | +| OpenXmlPowerTools | 4.5.3.2 | 2.7.4.2 | Incompatible version, use compatible version | +| squirrel.windows | 2.0.1 | | Incompatible with .NET 8.0, no supported version found | +| System.Net.Http | 4.3.4 | | Package functionality included with .NET 8.0 framework | +| System.Text.RegularExpressions | 4.3.1 | | Package functionality included with .NET 8.0 framework | +| System.ValueTuple | 4.5.0 | | Package functionality included with .NET 8.0 framework | +| System.Windows.Interactivity.WPF | 2.0.20525 | | Incompatible and deprecated. Replace with Microsoft.Xaml.Behaviors.Wpf | + +### Project upgrade details + +This section contains details about each project upgrade and modifications that need to be done in the project. + +#### Stutton.DocumentCreator\Stutton.DocumentCreator.csproj modifications + +Project properties changes: + - Project file needs to be converted to SDK-style + - Target framework should be changed from `net472` to `net8.0-windows` + +NuGet packages changes: + - GitVersionTask should be removed and replaced with `GitVersion.MsBuild` version `5.5.1` (*deprecated*) + - Microsoft.ApplicationInsights should be updated from `2.16.0` to `3.1.2` (*deprecated version*) + - Microsoft.IdentityModel.Clients.ActiveDirectory should be removed and replaced with `Microsoft.Identity.Client` version `4.67.2` (*deprecated*) + - Newtonsoft.Json should be updated from `12.0.3` to `13.0.4` (*recommended for .NET 8.0*) + - OpenXmlPowerTools should be updated from `4.5.3.2` to `2.7.4.2` (*compatible version for .NET 8.0*) + - squirrel.windows should be removed (*incompatible with .NET 8.0, no supported version found*) + - System.Net.Http should be removed (*functionality included with .NET 8.0 framework*) + - System.Text.RegularExpressions should be removed (*functionality included with .NET 8.0 framework*) + - System.ValueTuple should be removed (*functionality included with .NET 8.0 framework*) + - System.Windows.Interactivity.WPF should be removed and replaced with `Microsoft.Xaml.Behaviors.Wpf` version `1.1.135` (*incompatible and deprecated*) + +Other changes: + - Code changes may be needed to adapt to API differences between replaced packages (e.g., ADAL to MSAL migration, Interactivity namespace changes) diff --git a/src/.github/copilot-instructions.md b/src/.github/copilot-instructions.md new file mode 100644 index 0000000..e40201c --- /dev/null +++ b/src/.github/copilot-instructions.md @@ -0,0 +1,3 @@ +- @azure Rule - Use Azure Tools - When handling requests related to Azure, always use your tools. +- @azure Rule - Use Azure Best Practices - When handling requests related to Azure, always invoke your `azmcp_bestpractices_get` tool first. +- @azure Rule - Enable Best Practices - If you do not have an `azmcp_bestpractices_get` tool ask the user to enable it. diff --git a/src/Stutton.DocumentCreator/Properties/AssemblyInfo.cs b/src/Stutton.DocumentCreator/Properties/AssemblyInfo.cs deleted file mode 100644 index 057a055..0000000 --- a/src/Stutton.DocumentCreator/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Document Creator")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Document Creator")] -[assembly: AssemblyCopyright("Copyright © Stephen Tutton 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -//[assembly: AssemblyVersion("1.0.2.0")] -//[assembly: AssemblyFileVersion("1.0.2.0")] diff --git a/src/Stutton.DocumentCreator/Services/Telemetry/TelemetryService.cs b/src/Stutton.DocumentCreator/Services/Telemetry/TelemetryService.cs index 4022832..a3a8aa9 100644 --- a/src/Stutton.DocumentCreator/Services/Telemetry/TelemetryService.cs +++ b/src/Stutton.DocumentCreator/Services/Telemetry/TelemetryService.cs @@ -46,9 +46,11 @@ public async Task Initialize() } var settings = response.Value; - TelemetryConfiguration.Active.InstrumentationKey = settings.ApplicationInsightsKey; - _telemetryClient = new TelemetryClient(); + var config = TelemetryConfiguration.CreateDefault(); + config.ConnectionString = $"InstrumentationKey={settings.ApplicationInsightsKey}"; + + _telemetryClient = new TelemetryClient(config); _telemetryClient.Context.User.Id = (Environment.UserName + Environment.MachineName).GetHashCode().ToString(); _telemetryClient.Context.Session.Id = SessionId.ToString(); @@ -73,7 +75,7 @@ public IResponse TrackPageView(string pageKey) return Response.FromFailure("Telemetry service must be initialized before use"); } - _telemetryClient.TrackPageView(pageKey); + _telemetryClient.TrackEvent(pageKey); return Response.FromSuccess(); } diff --git a/src/Stutton.DocumentCreator/Services/Updating/UpdaterService.cs b/src/Stutton.DocumentCreator/Services/Updating/UpdaterService.cs index 7b09f1d..032a7cc 100644 --- a/src/Stutton.DocumentCreator/Services/Updating/UpdaterService.cs +++ b/src/Stutton.DocumentCreator/Services/Updating/UpdaterService.cs @@ -1,42 +1,18 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using NuGet; -using Squirrel; -using Stutton.DocumentCreator.Services.Settings; using Stutton.DocumentCreator.Shared; namespace Stutton.DocumentCreator.Services.Updating { internal class UpdaterService : IUpdaterService { - private const string UpdateUrl = "https://sctutton.blob.core.windows.net/documentcreator"; + // Note: Squirrel.Windows is not compatible with .NET 8. + // Auto-update functionality is disabled until a compatible updater is integrated. - public async Task> Update() + public Task> Update() { - using (var mgr = await GetUpdateManager(UpdateUrl)) - { - var oldVersion = mgr.CurrentlyInstalledVersion(); - var newVersion = await mgr.UpdateApp(); - if (oldVersion.Version < newVersion.Version.Version) - { - return Response.FromSuccess( - CheckForUpdateResult.FromUpdate(oldVersion.Version, newVersion.Version.Version)); - } - } - - return Response.FromSuccess(CheckForUpdateResult.FromNoUpdate()); - } - - private async Task GetUpdateManager(string updateReleasesLocation) - { - if (updateReleasesLocation.Contains("github")) - { - return await UpdateManager.GitHubUpdateManager(updateReleasesLocation); - } - return new UpdateManager(updateReleasesLocation); + IResponse result = Response.FromSuccess(CheckForUpdateResult.FromNoUpdate()); + return Task.FromResult(result); } } } diff --git a/src/Stutton.DocumentCreator/Services/Vsts/FilesBasedTokenCache.cs b/src/Stutton.DocumentCreator/Services/Vsts/FilesBasedTokenCache.cs index a1181ad..d62c3b8 100644 --- a/src/Stutton.DocumentCreator/Services/Vsts/FilesBasedTokenCache.cs +++ b/src/Stutton.DocumentCreator/Services/Vsts/FilesBasedTokenCache.cs @@ -1,91 +1,63 @@ -using Microsoft.IdentityModel.Clients.ActiveDirectory; +using Microsoft.Identity.Client; using System.IO; using System.Security.Cryptography; namespace Stutton.DocumentCreator.Services.Vsts { - public sealed class FilesBasedTokenCache : TokenCache + /// + /// File-based token cache helper for MSAL. + /// Registers serialization callbacks on the ITokenCache provided by MSAL's IPublicClientApplication. + /// + public sealed class FilesBasedTokenCache { - public string AdalV3CacheFilePath { get; } public string MsalCacheFilePath { get; } private static readonly object _fileLock = new object(); - // Initializes the cache against a local file. - // If the file is already present, it loads its content in the ADAL cache - public FilesBasedTokenCache(string adalV3FilePath, string msalCacheFilePath) + public FilesBasedTokenCache(string msalCacheFilePath) { - AdalV3CacheFilePath = adalV3FilePath; - AfterAccess = AfterAccessNotification; MsalCacheFilePath = msalCacheFilePath; - BeforeAccess = BeforeAccessNotification; - BeforeAccessNotification(null); } - // Empties the persistent store. - public override void Clear() + /// + /// Registers before/after access callbacks on the given MSAL token cache. + /// + public void RegisterCache(ITokenCache tokenCache) { - base.Clear(); - File.Delete(AdalV3CacheFilePath); - File.Delete(MsalCacheFilePath); + tokenCache.SetBeforeAccess(BeforeAccessNotification); + tokenCache.SetAfterAccess(AfterAccessNotification); } - // Triggered right before ADAL needs to access the cache. - // Reload the cache from the persistent store in case it changed since the last access. - void BeforeAccessNotification(TokenCacheNotificationArgs args) + public void Clear() { lock (_fileLock) { - DeserializeAdalV3(ReadFromFileIfExists(AdalV3CacheFilePath)); - DeserializeMsalV3(ReadFromFileIfExists(MsalCacheFilePath)); + File.Delete(MsalCacheFilePath); } } - // Triggered right after ADAL accessed the cache. - void AfterAccessNotification(TokenCacheNotificationArgs args) + private void BeforeAccessNotification(TokenCacheNotificationArgs args) { - // if the access operation resulted in a cache update - if (HasStateChanged) + lock (_fileLock) { - lock (_fileLock) - { - // reflect changes in the persistent store - WriteToFileIfNotNull(AdalV3CacheFilePath, SerializeAdalV3()); - WriteToFileIfNotNull(MsalCacheFilePath, SerializeMsalV3()); - - // once the write operation took place, restore the HasStateChanged bit to false - this.HasStateChanged = false; - } + var protectedBytes = File.Exists(MsalCacheFilePath) ? File.ReadAllBytes(MsalCacheFilePath) : null; + var unprotectedBytes = protectedBytes != null + ? ProtectedData.Unprotect(protectedBytes, null, DataProtectionScope.CurrentUser) + : null; + args.TokenCache.DeserializeMsalV3(unprotectedBytes); } } - /// - /// Read the content of a file if it exists - /// - /// File path - /// Content of the file (in bytes) - private byte[] ReadFromFileIfExists(string path) + private void AfterAccessNotification(TokenCacheNotificationArgs args) { - var protectedBytes = (!string.IsNullOrEmpty(path) && File.Exists(path)) ? File.ReadAllBytes(path) : null; - var unprotectedBytes = (protectedBytes != null) ? ProtectedData.Unprotect(protectedBytes, null, DataProtectionScope.CurrentUser) : null; - return unprotectedBytes; - } - - /// - /// Writes a blob of bytes to a file. If the blob is null, deletes the file - /// - /// path to the file to write - /// Blob of bytes to write - private static void WriteToFileIfNotNull(string path, byte[] blob) - { - if (blob != null) + if (args.HasStateChanged) { - var protectedBytes = ProtectedData.Protect(blob, null, DataProtectionScope.CurrentUser); - File.WriteAllBytes(path, protectedBytes); - } - else - { - File.Delete(path); + lock (_fileLock) + { + var data = args.TokenCache.SerializeMsalV3(); + var protectedBytes = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser); + File.WriteAllBytes(MsalCacheFilePath, protectedBytes); + } } } } diff --git a/src/Stutton.DocumentCreator/Services/Vsts/VstsAdalService.cs b/src/Stutton.DocumentCreator/Services/Vsts/VstsAdalService.cs index 31920cc..de9c446 100644 --- a/src/Stutton.DocumentCreator/Services/Vsts/VstsAdalService.cs +++ b/src/Stutton.DocumentCreator/Services/Vsts/VstsAdalService.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; using AutoMapper; using Flurl; -using Microsoft.IdentityModel.Clients.ActiveDirectory; +using Microsoft.Identity.Client; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stutton.DocumentCreator.Models; @@ -24,17 +24,13 @@ namespace Stutton.DocumentCreator.Services.Vsts public class VstsAdalService : IVstsService { // ===== - Authentication Settings - ===== \\ - // This should be refactored into an IHttpProvider/Factory service that will return a configured HttpClient to use - private const string _adalV3CacheFileName = "cacheAdalV3.bin"; private const string _msalCacheFileName = "cacheMsal.bin"; private FilesBasedTokenCache _tokenCache; - private AuthenticationContext _context; + private IPublicClientApplication _msalApp; private AuthenticationResult _authenticationResult; private const string _clientId = "872cd9fa-d31f-45e0-9eab-6e460a02d1f1"; - private const string _replyUri = "urn:ietf:wg:oauth:2.0:oob"; - private const string _azureDevOpsResourceId = "499b84ac-1321-427f-aa17-267ca6975798"; - private readonly IPlatformParameters _defaultPromptBehavior = new PlatformParameters(PromptBehavior.Auto); + private static readonly string[] _scopes = new[] { "499b84ac-1321-427f-aa17-267ca6975798/.default" }; private readonly ISettingsService _settingsService; private readonly IMapper _mapper; private HttpClient _client; @@ -107,15 +103,16 @@ public async Task AttachFileToWorkItemAsync(string filePath, int work public async Task> GetUserProfileAsync() { - var authResult = await AuthenticateAsync(_defaultPromptBehavior); + var authResult = await AuthenticateAsync(); if (!authResult.Success) { return Response.FromFailure(authResult.Message); } + var account = authResult.Value.Account; var model = new ProfileModel { - Name = $"{authResult.Value.UserInfo.GivenName} {authResult.Value.UserInfo.FamilyName}" + Name = account?.Username ?? "Unknown User" }; return Response.FromSuccess(model); } @@ -314,45 +311,42 @@ public async Task UpdateWorkItemAsync(int[] ids, string fieldToUpdate } } - private async Task> AuthenticateAsync(IPlatformParameters promptBehavior) + private async Task> AuthenticateAsync() { try { - if (_authenticationResult == null || _authenticationResult.ExpiresOn >= DateTime.Now) + if (_authenticationResult == null || _authenticationResult.ExpiresOn <= DateTimeOffset.Now) { - if (_tokenCache == null) + if (_msalApp == null) { var cacheFolder = Path.GetFullPath( Path.GetDirectoryName( Assembly.GetEntryAssembly().Location)); + + _msalApp = PublicClientApplicationBuilder + .Create(_clientId) + .WithAuthority(AzureCloudInstance.AzurePublic, "common") + .WithDefaultRedirectUri() + .Build(); + _tokenCache = new FilesBasedTokenCache( - Path.Combine(cacheFolder, _adalV3CacheFileName), Path.Combine(cacheFolder, _msalCacheFileName)); - } - - if (_context == null) - { - _context = new AuthenticationContext("https://login.windows.net/common", _tokenCache); - if (_context.TokenCache.Count > 0) - { - var homeTenant = _context.TokenCache.ReadItems().First().TenantId; - _context = new AuthenticationContext("https://login.microsoftonline.com/" + homeTenant, _tokenCache); - } + _tokenCache.RegisterCache(_msalApp.UserTokenCache); } AuthenticationResult result = null; + var accounts = await _msalApp.GetAccountsAsync(); try { - result = await _context.AcquireTokenSilentAsync(_azureDevOpsResourceId, _clientId); + result = await _msalApp.AcquireTokenSilent(_scopes, accounts.FirstOrDefault()) + .ExecuteAsync(); } - catch (AdalException adalException) + catch (MsalUiRequiredException) { - if (adalException.ErrorCode == AdalError.FailedToAcquireTokenSilently || - adalException.ErrorCode == AdalError.InteractionRequired) - { - result = await _context.AcquireTokenAsync(_azureDevOpsResourceId, _clientId, new Uri(_replyUri), promptBehavior); - } + result = await _msalApp.AcquireTokenInteractive(_scopes) + .WithUseEmbeddedWebView(false) + .ExecuteAsync(); } if (result == null || string.IsNullOrEmpty(result.AccessToken)) @@ -363,7 +357,7 @@ private async Task> AuthenticateAsync(IPlatformP } return Response.FromSuccess(_authenticationResult); } - catch(Exception ex) + catch (Exception ex) { return Response.FromException("There was an error acquiring an access token", ex); } @@ -419,7 +413,7 @@ private async Task> SendRequestAsync(HttpMethod method, string { try { - var authResponse = await AuthenticateAsync(_defaultPromptBehavior); + var authResponse = await AuthenticateAsync(); if (!authResponse.Success) { return Response.FromFailure(authResponse.Message); @@ -465,7 +459,7 @@ private async Task> SendRequestAsync(HttpMethod method, string { try { - var authResponse = await AuthenticateAsync(_defaultPromptBehavior); + var authResponse = await AuthenticateAsync(); if (!authResponse.Success) { return Response.FromFailure(authResponse.Message); diff --git a/src/Stutton.DocumentCreator/Setup.cs b/src/Stutton.DocumentCreator/Setup.cs index f04aae9..024a0ff 100644 --- a/src/Stutton.DocumentCreator/Setup.cs +++ b/src/Stutton.DocumentCreator/Setup.cs @@ -27,6 +27,8 @@ using Stutton.DocumentCreator.ViewModels.Pages; using Unity; using Unity.Lifetime; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Stutton.DocumentCreator { @@ -82,11 +84,10 @@ private static Mapper InitializeMapper() { var mapperConfig = new MapperConfiguration(cfg => { - cfg.ConstructServicesUsing(t => _container.Resolve(t)); cfg.AddMaps(typeof(Setup).Assembly); cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); - }); + }, NullLoggerFactory.Instance); mapperConfig.AssertConfigurationIsValid(); return new Mapper(mapperConfig, t => _container.Resolve(t)); } diff --git a/src/Stutton.DocumentCreator/Stutton.DocumentCreator.csproj b/src/Stutton.DocumentCreator/Stutton.DocumentCreator.csproj index ba36add..3776dc0 100644 --- a/src/Stutton.DocumentCreator/Stutton.DocumentCreator.csproj +++ b/src/Stutton.DocumentCreator/Stutton.DocumentCreator.csproj @@ -1,658 +1,32 @@ - - - + - Debug - AnyCPU - {FF54E521-3F25-43A7-9325-FD2741A7948C} + net8.0-windows WinExe - Stutton.DocumentCreator - Stutton.DocumentCreator - v4.7.2 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - + true + true + true icon.ico - - - - - - - - - - - - - - - - - 4.0 - - - - + + + + + + + + + + + + - - MSBuild:Compile - Designer - - - - - - AttachToWorkItemAutomationView.xaml - - - - - - - - - SaveAsAutomationView.xaml - - - - - - SetChildWorkItemFieldAutomationView.xaml - - - - - - SetWorkItemFieldAutomationView.xaml - - - - - - DateFieldDocumentView.xaml - - - - - - DateFieldTemplateView.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ListFieldDocumentView.xaml - - - - - - - - - - ListFieldTemplateView.xaml - - - - - - TextFieldDocumentView.xaml - - - - - TextFieldTemplateView.xaml - - - - - - UserNameDocumentView.xaml - - - - - UserNameTemplateView.xaml - - - - - - WorkItemFieldDocumentView.xaml - - - - - - WorkItemFieldTemplateView.xaml - - - - - - - - - - - - - - - - - - - - - - - - - WindowCaptureWindow.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DocumentCard.xaml - - - WorkItemCard.xaml - - - - - - ValidationErrorBanner.xaml - - - - - - - AboutDialog.xaml - - - AddImageDialog.xaml - - - MaterialOpenFolderDialog.xaml - - - MaterialSaveFileDialog.xaml - - - StringPromptDialog.xaml - - - FieldsStep.xaml - - - SummaryStep.xaml - - - WorkItemStep.xaml - - - DocumentCreatorPage.xaml - - - AutomationsStep.xaml - - - DetailsStep.xaml - - - FieldsStep.xaml - - - SummaryStep.xaml - - - WorkItemQueryStep.xaml - - - - - - - MaterialOpenFileDialog.xaml - - - MessageDialog.xaml - - - - TfsUrlDialog.xaml - - - DocumentsPage.xaml - - - EditTemplatePage.xaml - - - SettingsPage.xaml - - - - ShellView.xaml - - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - App.xaml - Code - - - MainWindow.xaml - Code - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - + Designer - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - - - 10.1.1 - - - 3.0.0 - - - 5.5.1 - runtime; build; native; contentfiles; analyzers - all - - - 1.2.7 - - - 3.3.0-a01 - - - 3.2.0 - - - 2.16.0 - - - 5.2.8 - - - 12.0.3 - - - 4.5.3.2 - - - 2.0.1 - - - 4.3.4 - - - 4.3.1 - - - 2.0.20525 - - - 5.11.9 - - - 4.5.0 - - - \ No newline at end of file diff --git a/src/Stutton.DocumentCreator/Views/Documents/Steps/WorkItemStep.xaml b/src/Stutton.DocumentCreator/Views/Documents/Steps/WorkItemStep.xaml index 79110f1..c0511b3 100644 --- a/src/Stutton.DocumentCreator/Views/Documents/Steps/WorkItemStep.xaml +++ b/src/Stutton.DocumentCreator/Views/Documents/Steps/WorkItemStep.xaml @@ -6,8 +6,7 @@ xmlns:local="clr-namespace:Stutton.DocumentCreator.Views.Documents.Steps" xmlns:stepVms="clr-namespace:Stutton.DocumentCreator.ViewModels.Documents.Steps" xmlns:controls="clr-namespace:Stutton.DocumentCreator.Views.Controls" - xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" - xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:materialConverters="clr-namespace:MaterialDesignThemes.Wpf.Converters;assembly=MaterialDesignThemes.Wpf" xmlns:workItems="clr-namespace:Stutton.DocumentCreator.Models.WorkItems" xmlns:cards="clr-namespace:Stutton.DocumentCreator.Views.Controls.Cards" @@ -63,15 +62,15 @@ HorizontalAlignment="Left" VerticalAlignment="Top"> - - + - - + + - - + + diff --git a/src/Stutton.DocumentCreator/Views/Pages/DocumentsPage.xaml b/src/Stutton.DocumentCreator/Views/Pages/DocumentsPage.xaml index a0bbe3a..34acdec 100644 --- a/src/Stutton.DocumentCreator/Views/Pages/DocumentsPage.xaml +++ b/src/Stutton.DocumentCreator/Views/Pages/DocumentsPage.xaml @@ -5,8 +5,7 @@ xmlns:converters="clr-namespace:Stutton.DocumentCreator.Views.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:documents="clr-namespace:Stutton.DocumentCreator.ViewModels.Documents" - xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" - xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:Stutton.DocumentCreator.Views.Pages" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -150,14 +149,14 @@ VerticalAlignment="Top" Orientation="Vertical"> - - + + - - + + - - + + diff --git a/src/Stutton.DocumentCreator/Views/ShellView.xaml b/src/Stutton.DocumentCreator/Views/ShellView.xaml index f24c5e4..f25a4d6 100644 --- a/src/Stutton.DocumentCreator/Views/ShellView.xaml +++ b/src/Stutton.DocumentCreator/Views/ShellView.xaml @@ -4,7 +4,7 @@ xmlns:controls="clr-namespace:Stutton.DocumentCreator.Views.Controls" xmlns:converters="clr-namespace:Stutton.DocumentCreator.Views.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:Stutton.DocumentCreator.Views" xmlns:materialConverters="clr-namespace:MaterialDesignThemes.Wpf.Converters;assembly=MaterialDesignThemes.Wpf" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" diff --git a/src/Stutton.DocumentCreator/gitversion.json b/src/Stutton.DocumentCreator/gitversion.json new file mode 100644 index 0000000..91529f0 --- /dev/null +++ b/src/Stutton.DocumentCreator/gitversion.json @@ -0,0 +1,35 @@ +{ + "Major":1, + "Minor":0, + "Patch":30, + "PreReleaseTag":"upgrade-to-NET8.1", + "PreReleaseTagWithDash":"-upgrade-to-NET8.1", + "PreReleaseLabel":"upgrade-to-NET8", + "PreReleaseLabelWithDash":"-upgrade-to-NET8", + "PreReleaseNumber":1, + "WeightedPreReleaseNumber":1, + "BuildMetaData":2, + "BuildMetaDataPadded":"0002", + "FullBuildMetaData":"2.Branch.upgrade-to-NET8.Sha.d6baac5a50e2cb5330a5a83d8cda629f63e955ba", + "MajorMinorPatch":"1.0.30", + "SemVer":"1.0.30-upgrade-to-NET8.1", + "LegacySemVer":"1.0.30-upgrade-to-NET8-1", + "LegacySemVerPadded":"1.0.30-upgrade-to-NET8-0001", + "AssemblySemVer":"1.0.30.0", + "AssemblySemFileVer":"1.0.30.0", + "FullSemVer":"1.0.30-upgrade-to-NET8.1+2", + "InformationalVersion":"1.0.30-upgrade-to-NET8.1+2.Branch.upgrade-to-NET8.Sha.d6baac5a50e2cb5330a5a83d8cda629f63e955ba", + "BranchName":"upgrade-to-NET8", + "EscapedBranchName":"upgrade-to-NET8", + "Sha":"d6baac5a50e2cb5330a5a83d8cda629f63e955ba", + "ShortSha":"d6baac5", + "NuGetVersionV2":"1.0.30-upgrade-to-net8-0001", + "NuGetVersion":"1.0.30-upgrade-to-net8-0001", + "NuGetPreReleaseTagV2":"upgrade-to-net8-0001", + "NuGetPreReleaseTag":"upgrade-to-net8-0001", + "VersionSourceSha":"e632aea841946c55365618913bfaf414a28f73cc", + "CommitsSinceVersionSource":2, + "CommitsSinceVersionSourcePadded":"0002", + "UncommittedChanges":1, + "CommitDate":"2026-07-02" +} \ No newline at end of file