fix(sidebar): resolve MatchingService live + settings "סגור" label
Sidebar lookups threw ObjectDisposedException on the EspoCrmClient's HttpClient after any settings save. TryInitializeCrm rebuilds the CRM stack (new HttpClient + MatchingService) and disposes the old HttpClient, but the long-lived sidebar ReadingPaneViewModel had captured the old MatchingService and kept calling into the disposed client. ReadingPaneViewModel now resolves the MatchingService live on each lookup via a Func<IMatchingService?> provider (() => host.MatchingService), so it always uses the current stack and degrades gracefully (shows "not configured") when none exists. SidebarController no longer captures a snapshot. Also: rename the Settings dialog's bottom button from "ביטול" to "סגור". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -152,7 +152,7 @@
|
||||
MinWidth="100" />
|
||||
<Button Command="{Binding CancelCommand}"
|
||||
IsCancel="True"
|
||||
Content="ביטול"
|
||||
Content="סגור"
|
||||
Padding="20,5"
|
||||
MinWidth="100" />
|
||||
</StackPanel>
|
||||
|
||||
@@ -27,7 +27,12 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
||||
|
||||
public sealed partial class ReadingPaneViewModel : ObservableObject
|
||||
{
|
||||
private readonly IMatchingService _matchingService;
|
||||
// Resolved live on each lookup rather than captured once: the host
|
||||
// rebuilds the CRM stack (new HttpClient + MatchingService) whenever
|
||||
// settings are saved and disposes the old HttpClient. A captured
|
||||
// snapshot would then call into a disposed HttpClient and throw
|
||||
// ObjectDisposedException on every sidebar lookup.
|
||||
private readonly Func<IMatchingService?> _matchingServiceProvider;
|
||||
private readonly ILogger _logger;
|
||||
private CancellationTokenSource? _activeLookup;
|
||||
// Stashes the ambiguous MatchResult while the user is drilling into
|
||||
@@ -94,9 +99,9 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
||||
/// </summary>
|
||||
public event EventHandler<string>? OpenInBrowserRequested;
|
||||
|
||||
public ReadingPaneViewModel(IMatchingService matchingService, ILogger logger)
|
||||
public ReadingPaneViewModel(Func<IMatchingService?> matchingServiceProvider, ILogger logger)
|
||||
{
|
||||
_matchingService = matchingService ?? throw new ArgumentNullException(nameof(matchingService));
|
||||
_matchingServiceProvider = matchingServiceProvider ?? throw new ArgumentNullException(nameof(matchingServiceProvider));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
@@ -162,12 +167,20 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
||||
_ambiguousReturnTarget = null;
|
||||
State = ReadingPaneState.Loading;
|
||||
|
||||
var svc = _matchingServiceProvider();
|
||||
if (svc == null)
|
||||
{
|
||||
ErrorMessage = "התוסף עדיין לא מוגדר. עדכן בהגדרות.";
|
||||
State = ReadingPaneState.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
_activeLookup = cts;
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _matchingService.LookupAsync(senderEmail, cts.Token).ConfigureAwait(true);
|
||||
var result = await svc.LookupAsync(senderEmail, cts.Token).ConfigureAwait(true);
|
||||
if (cts.IsCancellationRequested) return;
|
||||
|
||||
if (result == null)
|
||||
@@ -296,6 +309,14 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
||||
{
|
||||
if (candidate == null || string.IsNullOrWhiteSpace(candidate.Id)) return;
|
||||
|
||||
var svc = _matchingServiceProvider();
|
||||
if (svc == null)
|
||||
{
|
||||
ErrorMessage = "התוסף עדיין לא מוגדר. עדכן בהגדרות.";
|
||||
State = ReadingPaneState.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
CancelInFlight();
|
||||
var cts = new CancellationTokenSource();
|
||||
_activeLookup = cts;
|
||||
@@ -310,7 +331,7 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _matchingService.LookupContactAsync(candidate.Id, rememberedEmail, cts.Token).ConfigureAwait(true);
|
||||
var result = await svc.LookupContactAsync(candidate.Id, rememberedEmail, cts.Token).ConfigureAwait(true);
|
||||
if (cts.IsCancellationRequested) return;
|
||||
|
||||
if (result == null || result.Contact == null)
|
||||
|
||||
@@ -33,6 +33,6 @@ using System.Security;
|
||||
// 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.2.16.0")]
|
||||
[assembly: AssemblyFileVersion("1.2.16.0")]
|
||||
[assembly: AssemblyVersion("1.2.17.0")]
|
||||
[assembly: AssemblyFileVersion("1.2.17.0")]
|
||||
|
||||
|
||||
@@ -367,7 +367,6 @@ namespace OutlookAddin.Services
|
||||
_sidebarController = new SidebarController(
|
||||
taskPanes,
|
||||
_outlookApp,
|
||||
MatchingService!,
|
||||
this,
|
||||
System.Windows.Threading.Dispatcher.CurrentDispatcher,
|
||||
Logger);
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace OutlookAddin.Services
|
||||
|
||||
private readonly CustomTaskPaneCollection _taskPanes;
|
||||
private readonly Outlook.Application _app;
|
||||
private readonly IMatchingService _matchingService;
|
||||
private readonly AddInHost _host;
|
||||
private readonly Dispatcher _dispatcher;
|
||||
private readonly ILogger _logger;
|
||||
@@ -38,14 +37,12 @@ namespace OutlookAddin.Services
|
||||
public SidebarController(
|
||||
CustomTaskPaneCollection taskPanes,
|
||||
Outlook.Application app,
|
||||
IMatchingService matchingService,
|
||||
AddInHost host,
|
||||
Dispatcher dispatcher,
|
||||
ILogger logger)
|
||||
{
|
||||
_taskPanes = taskPanes ?? throw new ArgumentNullException(nameof(taskPanes));
|
||||
_app = app ?? throw new ArgumentNullException(nameof(app));
|
||||
_matchingService = matchingService ?? throw new ArgumentNullException(nameof(matchingService));
|
||||
_host = host ?? throw new ArgumentNullException(nameof(host));
|
||||
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
@@ -83,7 +80,7 @@ namespace OutlookAddin.Services
|
||||
if (_bindings.ContainsKey(key)) return;
|
||||
|
||||
var view = new ReadingPaneView();
|
||||
var vm = new ReadingPaneViewModel(_matchingService, _logger)
|
||||
var vm = new ReadingPaneViewModel(() => _host.MatchingService, _logger)
|
||||
{
|
||||
EspoCrmBaseUrl = _host.Settings.EspoCrmUrl
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user