fix: restore PNG embed entries + handle numeric Case.number from EspoCRM

Two issues surfaced from the addin log:

1) The four Klear ribbon PNGs were not in the assembly manifest
   (Available resources listed only the XMLs and Properties.Resources).
   The EmbeddedResource entries for Images got dropped from
   OutlookAddin.csproj during a previous rebase. Re-add them in the same
   spot they had before.

2) MatchingService failed for one of the contacts with:
     System.Text.Json.JsonException at $.list[0].number
     Cannot get the value of a token type Number as a string.
   EspoCRM emits Case.number as a JSON number on installs that use
   auto-increment, and as a string when a custom case-code format is
   configured. Add a small FlexibleStringConverter that reads either
   token type into the same string field, and attach it to
   CaseEntity.Number.

Tests: 39 passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
PointStar
2026-05-11 18:57:13 +03:00
parent f794fbc37a
commit 414f71706a
3 changed files with 65 additions and 2 deletions
@@ -0,0 +1,46 @@
using System;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MarcusLaw.OutlookAddin.Core.Json
{
/// <summary>
/// Reads a JSON value as <see cref="string"/> when the source might be
/// either a string OR a number (or null). EspoCRM exposes fields such
/// as Case.number sometimes as JSON numbers (auto-increment) and
/// sometimes as JSON strings (custom case codes) depending on field
/// configuration; with a plain <c>string?</c> property the deserializer
/// would throw on the numeric form.
/// </summary>
public sealed class FlexibleStringConverter : JsonConverter<string?>
{
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.Null:
return null;
case JsonTokenType.String:
return reader.GetString();
case JsonTokenType.Number:
if (reader.TryGetInt64(out var l)) return l.ToString(CultureInfo.InvariantCulture);
if (reader.TryGetDouble(out var d)) return d.ToString("R", CultureInfo.InvariantCulture);
return reader.GetDecimal().ToString(CultureInfo.InvariantCulture);
case JsonTokenType.True:
return "true";
case JsonTokenType.False:
return "false";
default:
reader.Skip();
return null;
}
}
public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
{
if (value == null) writer.WriteNullValue();
else writer.WriteStringValue(value);
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using MarcusLaw.OutlookAddin.Core.Json;
namespace MarcusLaw.OutlookAddin.Core.Models
{
@@ -12,7 +13,11 @@ namespace MarcusLaw.OutlookAddin.Core.Models
[JsonPropertyName("name")]
public string? Name { get; set; }
// EspoCRM serializes the case number as a JSON number on some
// installs (auto-increment column) and as a string on others
// (custom case-code formatter). Accept both.
[JsonPropertyName("number")]
[JsonConverter(typeof(FlexibleStringConverter))]
public string? Number { get; set; }
[JsonPropertyName("status")]
+14 -2
View File
@@ -36,7 +36,7 @@
<PublishUrl>C:\Users\Chaim\source\repos\OutlookAddin\Publish\</PublishUrl>
<InstallUrl>\\192.168.10.97\Projects\LegalCRM\Add-in\</InstallUrl>
<TargetCulture>en</TargetCulture>
<ApplicationVersion>1.0.0.2</ApplicationVersion>
<ApplicationVersion>1.0.0.4</ApplicationVersion>
<AutoIncrementApplicationRevision>true</AutoIncrementApplicationRevision>
<UpdateEnabled>true</UpdateEnabled>
<UpdateInterval>7</UpdateInterval>
@@ -258,6 +258,18 @@
<EmbeddedResource Include="Ribbon\InspectorRibbon.xml">
<LogicalName>OutlookAddin.Ribbon.InspectorRibbon.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Images\klear-file.png">
<LogicalName>OutlookAddin.Images.klear-file.png</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Images\klear-sidebar.png">
<LogicalName>OutlookAddin.Images.klear-sidebar.png</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Images\klear-settings.png">
<LogicalName>OutlookAddin.Images.klear-settings.png</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Images\klear-compose.png">
<LogicalName>OutlookAddin.Images.klear-compose.png</LogicalName>
</EmbeddedResource>
<Compile Include="Services\AddInHost.cs">
<SubType>Code</SubType>
</Compile>
@@ -347,7 +359,7 @@
<FlavorProperties GUID="{BAA0C2D2-18E2-41B9-852F-F413020CAA33}">
<ProjectProperties HostName="Outlook" HostPackage="{29A7B9D7-A7F1-4328-8EF0-6B2D1A56B2C1}" OfficeVersion="15.0" VstxVersion="4.0" ApplicationType="Outlook" Language="cs" TemplatesPath="" DebugInfoExeName="#Software\Microsoft\Office\16.0\Outlook\InstallRoot\Path#outlook.exe" AddItemTemplatesGuid="{A58A78EB-1C92-4DDD-80CF-E8BD872ABFC4}" />
<Host Name="Outlook" GeneratedCodeNamespace="OutlookAddin" PublishedHash="69C324AB27932AA2FBF2B7EA72250886FF164DE6" IconIndex="0">
<HostItem Name="ThisAddIn" Code="ThisAddIn.cs" CanonicalName="AddIn" CanActivate="false" IconIndex="1" Blueprint="ThisAddIn.Designer.xml" GeneratedCode="ThisAddIn.Designer.cs" PublishedHash="87E42D3CE323366A3FA072C634F27C3D6B959662" />
<HostItem Name="ThisAddIn" Code="ThisAddIn.cs" CanonicalName="AddIn" PublishedHash="87E42D3CE323366A3FA072C634F27C3D6B959662" CanActivate="false" IconIndex="1" Blueprint="ThisAddIn.Designer.xml" GeneratedCode="ThisAddIn.Designer.cs" />
</Host>
</FlavorProperties>
</VisualStudio>