🐛 Fix JSON serialization caused issue

This commit is contained in:
2025-07-25 02:58:13 +08:00
parent f2f6b192d6
commit d5fb00a8a9
12 changed files with 231 additions and 52 deletions

View File

@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations.Schema;
using DysonNetwork.Shared.Data; using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Proto;
using Google.Protobuf; using Google.Protobuf;
using Newtonsoft.Json;
using NodaTime; using NodaTime;
using NodaTime.Serialization.Protobuf; using NodaTime.Serialization.Protobuf;
@@ -119,11 +118,11 @@ public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
UploadedAt = UploadedAt?.ToTimestamp(), UploadedAt = UploadedAt?.ToTimestamp(),
// Convert file metadata // Convert file metadata
FileMeta = ByteString.CopyFromUtf8( FileMeta = ByteString.CopyFromUtf8(
JsonConvert.SerializeObject(FileMeta, GrpcTypeHelper.SerializerSettings) System.Text.Json.JsonSerializer.Serialize(FileMeta, GrpcTypeHelper.SerializerOptions)
), ),
// Convert user metadata // Convert user metadata
UserMeta = ByteString.CopyFromUtf8( UserMeta = ByteString.CopyFromUtf8(
JsonConvert.SerializeObject(UserMeta, GrpcTypeHelper.SerializerSettings) System.Text.Json.JsonSerializer.Serialize(UserMeta, GrpcTypeHelper.SerializerOptions)
) )
}; };

View File

@@ -1,7 +1,7 @@
{ {
"Debug": true, "Debug": true,
"BaseUrl": "http://localhost:5071", "BaseUrl": "http://localhost:5071",
"GatewayUrl": "http://10.126.126.1:5094", "GatewayUrl": "http://localhost:5094",
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",

View File

@@ -1,5 +1,6 @@
{ {
"LocalMode": true, "LocalMode": true,
"CaCert": "../Certificates/ca.crt",
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",

View File

@@ -1,6 +1,6 @@
{ {
"Debug": true, "Debug": true,
"BaseUrl": "http://10.126.126.1:5216", "BaseUrl": "http://localhost:5216",
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",

View File

@@ -1,7 +1,9 @@
using Newtonsoft.Json; using System.Text.Json;
using Newtonsoft.Json.Serialization; using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using DysonNetwork.Shared.Data;
using NodaTime; using NodaTime;
using NodaTime.Serialization.JsonNet; using NodaTime.Serialization.SystemTextJson;
using StackExchange.Redis; using StackExchange.Redis;
namespace DysonNetwork.Shared.Cache; namespace DysonNetwork.Shared.Cache;
@@ -186,7 +188,7 @@ public class RedisDistributedLock : IDistributedLock
public class CacheServiceRedis : ICacheService public class CacheServiceRedis : ICacheService
{ {
private readonly IDatabase _database; private readonly IDatabase _database;
private readonly JsonSerializerSettings _serializerSettings; private readonly JsonSerializerOptions _jsonOptions;
// Global prefix for all cache keys // Global prefix for all cache keys
public const string GlobalKeyPrefix = "dyson:"; public const string GlobalKeyPrefix = "dyson:";
@@ -200,18 +202,17 @@ public class CacheServiceRedis : ICacheService
var rds = redis ?? throw new ArgumentNullException(nameof(redis)); var rds = redis ?? throw new ArgumentNullException(nameof(redis));
_database = rds.GetDatabase(); _database = rds.GetDatabase();
// Configure Newtonsoft.Json with proper NodaTime serialization // Configure System.Text.Json with proper NodaTime serialization
_serializerSettings = new JsonSerializerSettings _jsonOptions = new JsonSerializerOptions
{ {
ContractResolver = new CamelCasePropertyNamesContractResolver(), TypeInfoResolver = new DefaultJsonTypeInfoResolver
PreserveReferencesHandling = PreserveReferencesHandling.None, {
NullValueHandling = NullValueHandling.Include, Modifiers = { JsonExtensions.UnignoreAllProperties() },
DateParseHandling = DateParseHandling.None, },
ReferenceLoopHandling = ReferenceLoopHandling.Ignore ReferenceHandler = ReferenceHandler.Preserve,
}; };
_jsonOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
// Configure NodaTime serializers _jsonOptions.PropertyNameCaseInsensitive = true;
_serializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
} }
public async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null) public async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null)
@@ -220,7 +221,7 @@ public class CacheServiceRedis : ICacheService
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key)); throw new ArgumentException("Key cannot be null or empty", nameof(key));
var serializedValue = JsonConvert.SerializeObject(value, _serializerSettings); var serializedValue = JsonSerializer.Serialize(value, _jsonOptions);
return await _database.StringSetAsync(key, serializedValue, expiry); return await _database.StringSetAsync(key, serializedValue, expiry);
} }
@@ -235,8 +236,8 @@ public class CacheServiceRedis : ICacheService
if (value.IsNullOrEmpty) if (value.IsNullOrEmpty)
return default; return default;
// For NodaTime serialization, use the configured serializer settings // For NodaTime serialization, use the configured JSON options
return JsonConvert.DeserializeObject<T>(value!, _serializerSettings); return JsonSerializer.Deserialize<T>(value!, _jsonOptions);
} }
public async Task<(bool found, T? value)> GetAsyncWithStatus<T>(string key) public async Task<(bool found, T? value)> GetAsyncWithStatus<T>(string key)
@@ -250,8 +251,8 @@ public class CacheServiceRedis : ICacheService
if (value.IsNullOrEmpty) if (value.IsNullOrEmpty)
return (false, default); return (false, default);
// For NodaTime serialization, use the configured serializer settings // For NodaTime serialization, use the configured JSON options
return (true, JsonConvert.DeserializeObject<T>(value!, _serializerSettings)); return (true, JsonSerializer.Deserialize<T>(value!, _jsonOptions));
} }
public async Task<bool> RemoveAsync(string key) public async Task<bool> RemoveAsync(string key)

View File

@@ -1,6 +1,6 @@
using System.Text.Json;
using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Proto;
using Google.Protobuf; using Google.Protobuf;
using Newtonsoft.Json;
namespace DysonNetwork.Shared.Data; namespace DysonNetwork.Shared.Data;
@@ -42,14 +42,20 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
{ {
Id = proto.Id, Id = proto.Id,
Name = proto.Name, Name = proto.Name,
FileMeta = JsonConvert.DeserializeObject<Dictionary<string, object?>>( FileMeta = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
proto.FileMeta.ToStringUtf8(), proto.FileMeta.ToStringUtf8(),
GrpcTypeHelper.SerializerSettings GrpcTypeHelper.SerializerOptions
) ?? [], )?.ToDictionary(
UserMeta = JsonConvert.DeserializeObject<Dictionary<string, object?>>( kvp => kvp.Key,
kvp => kvp.Value.ValueKind == JsonValueKind.Undefined ? null : kvp.Value.Deserialize<object?>(GrpcTypeHelper.SerializerOptions)
) ?? new Dictionary<string, object?>(),
UserMeta = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
proto.UserMeta.ToStringUtf8(), proto.UserMeta.ToStringUtf8(),
GrpcTypeHelper.SerializerSettings GrpcTypeHelper.SerializerOptions
) ?? [], )?.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.ValueKind == JsonValueKind.Undefined ? null : kvp.Value.Deserialize<object?>(GrpcTypeHelper.SerializerOptions)
) ?? new Dictionary<string, object?>(),
MimeType = proto.MimeType, MimeType = proto.MimeType,
Hash = proto.Hash, Hash = proto.Hash,
Size = proto.Size, Size = proto.Size,
@@ -76,12 +82,12 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
// Convert file metadata // Convert file metadata
proto.FileMeta = ByteString.CopyFromUtf8( proto.FileMeta = ByteString.CopyFromUtf8(
JsonConvert.SerializeObject(FileMeta, GrpcTypeHelper.SerializerSettings) JsonSerializer.Serialize(FileMeta, GrpcTypeHelper.SerializerOptions)
); );
// Convert user metadata // Convert user metadata
proto.UserMeta = ByteString.CopyFromUtf8( proto.UserMeta = ByteString.CopyFromUtf8(
JsonConvert.SerializeObject(UserMeta, GrpcTypeHelper.SerializerSettings) JsonSerializer.Serialize(UserMeta, GrpcTypeHelper.SerializerOptions)
); );
return proto; return proto;

View File

@@ -0,0 +1,152 @@
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
namespace DysonNetwork.Shared.Data;
public static class JsonExtensions
{
public static Action<JsonTypeInfo> UnignoreAllProperties() =>
typeInfo =>
{
if (typeInfo.Kind == JsonTypeInfoKind.Object)
// [JsonIgnore] is implemented by setting ShouldSerialize to a function that returns false.
foreach (var property in typeInfo.Properties.Where(ShouldUnignore))
{
property.Get ??= CreatePropertyGetter(property);
property.Set ??= CreatePropertySetter(property);
if (property.Get != null)
property.ShouldSerialize = null;
}
};
public static Action<JsonTypeInfo> UnignoreAllProperties(Type type) =>
typeInfo =>
{
if (type.IsAssignableFrom(typeInfo.Type) && typeInfo.Kind == JsonTypeInfoKind.Object)
// [JsonIgnore] is implemented by setting ShouldSerialize to a function that returns false.
foreach (var property in typeInfo.Properties.Where(ShouldUnignore))
{
property.Get ??= CreatePropertyGetter(property);
property.Set ??= CreatePropertySetter(property);
if (property.Get != null)
property.ShouldSerialize = null;
}
};
public static Action<JsonTypeInfo> UnignoreProperties(Type type, params string[] properties) =>
typeInfo =>
{
if (type.IsAssignableFrom(typeInfo.Type) && typeInfo.Kind == JsonTypeInfoKind.Object)
// [JsonIgnore] is implemented by setting ShouldSerialize to a function that returns false.
foreach (var property in typeInfo.Properties.Where(p => ShouldUnignore(p, properties)))
{
property.Get ??= CreatePropertyGetter(property);
property.Set ??= CreatePropertySetter(property);
if (property.Get != null)
property.ShouldSerialize = null;
}
};
public static Action<JsonTypeInfo> UnignorePropertiesForDeserialize(Type type, params string[] properties) =>
typeInfo =>
{
if (type.IsAssignableFrom(typeInfo.Type) && typeInfo.Kind == JsonTypeInfoKind.Object)
// [JsonIgnore] is implemented by setting ShouldSerialize to a function that returns false.
foreach (var property in typeInfo.Properties.Where(p => ShouldUnignore(p, properties)))
{
property.Set ??= CreatePropertySetter(property);
}
};
static bool ShouldUnignore(JsonPropertyInfo property) =>
property.ShouldSerialize != null &&
property.AttributeProvider?.IsDefined(typeof(JsonIgnoreAttribute), true) == true;
static bool ShouldUnignore(JsonPropertyInfo property, string[] properties) =>
property.ShouldSerialize != null &&
property.AttributeProvider?.IsDefined(typeof(JsonIgnoreAttribute), true) == true &&
properties.Contains(property.GetMemberName());
// CreateGetter() and CreateSetter() taken from this answer https://stackoverflow.com/a/76296944/3744182
// To https://stackoverflow.com/questions/61869393/get-net-core-jsonserializer-to-serialize-private-members
delegate TValue RefFunc<TObject, TValue>(ref TObject arg);
static Func<object, object?>? CreatePropertyGetter(JsonPropertyInfo property) =>
property.GetPropertyInfo() is { } info && info.ReflectedType != null && info.GetGetMethod() is { } getMethod
? CreateGetter(info.ReflectedType, getMethod)
: null;
static Func<object, object?>? CreateGetter(Type type, MethodInfo? method)
{
if (method == null)
return null;
var myMethod = typeof(JsonExtensions).GetMethod(nameof(JsonExtensions.CreateGetterGeneric),
BindingFlags.NonPublic | BindingFlags.Static)!;
return (Func<object, object?>)(myMethod.MakeGenericMethod(new[] { type, method.ReturnType })
.Invoke(null, new[] { method })!);
}
static Func<object, object?> CreateGetterGeneric<TObject, TValue>(MethodInfo method)
{
if (method == null)
throw new ArgumentNullException();
if (typeof(TObject).IsValueType)
{
// https://stackoverflow.com/questions/4326736/how-can-i-create-an-open-delegate-from-a-structs-instance-method
// https://stackoverflow.com/questions/1212346/uncurrying-an-instance-method-in-net/1212396#1212396
var func = (RefFunc<TObject, TValue>)Delegate.CreateDelegate(typeof(RefFunc<TObject, TValue>), null,
method);
return (o) =>
{
var tObj = (TObject)o;
return func(ref tObj);
};
}
else
{
var func = (Func<TObject, TValue>)Delegate.CreateDelegate(typeof(Func<TObject, TValue>), method);
return (o) => func((TObject)o);
}
}
static Action<object, object?>? CreatePropertySetter(JsonPropertyInfo property) =>
property.GetPropertyInfo() is { } info && info.ReflectedType != null && info.GetSetMethod() is { } setMethod
? CreateSetter(info.ReflectedType, setMethod)
: null;
static Action<object, object?>? CreateSetter(Type type, MethodInfo? method)
{
if (method == null)
return null;
var myMethod = typeof(JsonExtensions).GetMethod(nameof(JsonExtensions.CreateSetterGeneric),
BindingFlags.NonPublic | BindingFlags.Static)!;
return (Action<object, object?>)(myMethod
.MakeGenericMethod(new[] { type, method.GetParameters().Single().ParameterType })
.Invoke(null, new[] { method })!);
}
static Action<object, object?>? CreateSetterGeneric<TObject, TValue>(MethodInfo method)
{
if (method == null)
throw new ArgumentNullException();
if (typeof(TObject).IsValueType)
{
// TODO: find a performant way to do this. Possibilities:
// Box<T> from Microsoft.Toolkit.HighPerformance
// https://stackoverflow.com/questions/18937935/how-to-mutate-a-boxed-struct-using-il
return (o, v) => method.Invoke(o, new[] { v });
}
else
{
var func = (Action<TObject, TValue?>)Delegate.CreateDelegate(typeof(Action<TObject, TValue?>), method);
return (o, v) => func((TObject)o, (TValue?)v);
}
}
static PropertyInfo? GetPropertyInfo(this JsonPropertyInfo property) =>
(property.AttributeProvider as PropertyInfo);
static string? GetMemberName(this JsonPropertyInfo property) => (property.AttributeProvider as MemberInfo)?.Name;
}

View File

@@ -26,6 +26,7 @@
<PackageReference Include="NodaTime" Version="3.2.2" /> <PackageReference Include="NodaTime" Version="3.2.2" />
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.2.0" /> <PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.2.0" />
<PackageReference Include="NodaTime.Serialization.Protobuf" Version="2.0.2" /> <PackageReference Include="NodaTime.Serialization.Protobuf" Version="2.0.2" />
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.41" /> <PackageReference Include="StackExchange.Redis" Version="2.8.41" />
<PackageReference Include="System.Net.Http" Version="4.3.4" /> <PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup> </ItemGroup>

View File

@@ -1,20 +1,26 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Google.Protobuf.Collections; using Google.Protobuf.Collections;
using Google.Protobuf.WellKnownTypes; using Google.Protobuf.WellKnownTypes;
using DysonNetwork.Shared.Data;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using JsonSerializer = System.Text.Json.JsonSerializer;
namespace DysonNetwork.Shared.Proto; namespace DysonNetwork.Shared.Proto;
public abstract class GrpcTypeHelper public abstract class GrpcTypeHelper
{ {
public static readonly JsonSerializerSettings SerializerSettings = new() public static readonly JsonSerializerOptions SerializerOptions = new()
{ {
ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }, PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
PreserveReferencesHandling = PreserveReferencesHandling.None, DefaultIgnoreCondition = JsonIgnoreCondition.Never,
NullValueHandling = NullValueHandling.Include, PropertyNameCaseInsensitive = true,
DateParseHandling = DateParseHandling.None TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { JsonExtensions.UnignoreAllProperties() }
}
}; };
public static MapField<string, Value> ConvertToValueMap(Dictionary<string, object> source) public static MapField<string, Value> ConvertToValueMap(Dictionary<string, object> source)
@@ -31,7 +37,7 @@ public abstract class GrpcTypeHelper
double d => Value.ForNumber(d), double d => Value.ForNumber(d),
bool b => Value.ForBool(b), bool b => Value.ForBool(b),
null => Value.ForNull(), null => Value.ForNull(),
_ => Value.ForString(JsonConvert.SerializeObject(kvp.Value, SerializerSettings)) // fallback to JSON string _ => Value.ForString(JsonSerializer.Serialize(kvp.Value, SerializerOptions)) // fallback to JSON string
}; };
} }
return result; return result;
@@ -49,7 +55,7 @@ public abstract class GrpcTypeHelper
try try
{ {
// Try to parse as JSON object or primitive // Try to parse as JSON object or primitive
result[kvp.Key] = JsonConvert.DeserializeObject(value.StringValue, SerializerSettings); result[kvp.Key] = JsonNode.Parse(value.StringValue)?.AsObject() ?? JsonObject.Create(new JsonElement());
} }
catch catch
{ {
@@ -67,10 +73,22 @@ public abstract class GrpcTypeHelper
result[kvp.Key] = null; result[kvp.Key] = null;
break; break;
case Value.KindOneofCase.StructValue: case Value.KindOneofCase.StructValue:
result[kvp.Key] = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value.StructValue.Fields.ToDictionary(f => f.Key, f => ConvertValueToObject(f.Value)), SerializerSettings)); result[kvp.Key] = JsonSerializer.Deserialize<JsonElement>(
JsonSerializer.Serialize(
value.StructValue.Fields.ToDictionary(f => f.Key, f => ConvertValueToObject(f.Value)),
SerializerOptions
),
SerializerOptions
);
break; break;
case Value.KindOneofCase.ListValue: case Value.KindOneofCase.ListValue:
result[kvp.Key] = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value.ListValue.Values.Select(ConvertValueToObject).ToList(), SerializerSettings), SerializerSettings); result[kvp.Key] = JsonSerializer.Deserialize<JsonElement>(
JsonSerializer.Serialize(
value.ListValue.Values.Select(ConvertValueToObject).ToList(),
SerializerOptions
),
SerializerOptions
);
break; break;
default: default:
result[kvp.Key] = null; result[kvp.Key] = null;
@@ -88,7 +106,7 @@ public abstract class GrpcTypeHelper
Value.KindOneofCase.NumberValue => value.NumberValue, Value.KindOneofCase.NumberValue => value.NumberValue,
Value.KindOneofCase.BoolValue => value.BoolValue, Value.KindOneofCase.BoolValue => value.BoolValue,
Value.KindOneofCase.NullValue => null, Value.KindOneofCase.NullValue => null,
_ => JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value, SerializerSettings)) _ => JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(value, SerializerOptions), SerializerOptions)
}; };
} }
@@ -96,8 +114,8 @@ public abstract class GrpcTypeHelper
{ {
return value.KindCase switch return value.KindCase switch
{ {
Value.KindOneofCase.StringValue => JsonConvert.DeserializeObject<T>(value.StringValue, SerializerSettings), Value.KindOneofCase.StringValue => JsonSerializer.Deserialize<T>(value.StringValue, SerializerOptions),
_ => JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(value, SerializerSettings)) _ => JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(value, SerializerOptions), SerializerOptions)
}; };
} }
@@ -112,7 +130,7 @@ public abstract class GrpcTypeHelper
double d => Value.ForNumber(d), double d => Value.ForNumber(d),
bool b => Value.ForBool(b), bool b => Value.ForBool(b),
null => Value.ForNull(), null => Value.ForNull(),
_ => Value.ForString(JsonConvert.SerializeObject(obj, SerializerSettings)) // fallback to JSON string _ => Value.ForString(JsonSerializer.Serialize(obj, SerializerOptions)) // fallback to JSON string
}; };
} }
@@ -123,7 +141,7 @@ public abstract class GrpcTypeHelper
return obj switch return obj switch
{ {
null => Value.ForNull(), null => Value.ForNull(),
_ => Value.ForString(JsonConvert.SerializeObject(obj, SerializerSettings)) _ => Value.ForString(JsonSerializer.Serialize(obj, SerializerOptions))
}; };
} }
} }

View File

@@ -281,7 +281,6 @@ public class PostController(
try try
{ {
post = await ps.PostAsync( post = await ps.PostAsync(
currentUser,
post, post,
attachments: request.Attachments, attachments: request.Attachments,
tags: request.Tags, tags: request.Tags,

View File

@@ -72,7 +72,6 @@ public partial class PostService(
} }
public async Task<Post> PostAsync( public async Task<Post> PostAsync(
Account user,
Post post, Post post,
List<string>? attachments = null, List<string>? attachments = null,
List<string>? tags = null, List<string>? tags = null,

View File

@@ -65,7 +65,10 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIServiceCollectionQuartzConfigurator_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F1edbd6e24d7b430fabce72177269baa19200_003F67_003Faee36f5b_003FIServiceCollectionQuartzConfigurator_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIServiceCollectionQuartzConfigurator_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F1edbd6e24d7b430fabce72177269baa19200_003F67_003Faee36f5b_003FIServiceCollectionQuartzConfigurator_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIStringLocalizerFactory_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6aa8ac544afb487082402c1fa422910f2e00_003F7f_003F8e728ed6_003FIStringLocalizerFactory_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIStringLocalizerFactory_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6aa8ac544afb487082402c1fa422910f2e00_003F7f_003F8e728ed6_003FIStringLocalizerFactory_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AITusStore_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8bb08a178b5b43c5bac20a5a54159a5b2a800_003Fb1_003F7e861de5_003FITusStore_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AITusStore_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8bb08a178b5b43c5bac20a5a54159a5b2a800_003Fb1_003F7e861de5_003FITusStore_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonIgnoreCondition_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F80b40ae0ee1c48a5b065caa3311685c119a400_003Fc3_003F848024ce_003FJsonIgnoreCondition_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonSerializerOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5703920a18f94462b4354fab05326e6519a200_003F35_003F8536fc49_003FJsonSerializerOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonSerializerOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5703920a18f94462b4354fab05326e6519a200_003F35_003F8536fc49_003FJsonSerializerOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonSerializerOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F80b40ae0ee1c48a5b065caa3311685c119a400_003F0a_003F55e3f48f_003FJsonSerializerOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonSerializerSettings_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7e62198beab24380bbac29171862d1d8adf10_003Fc6_003Ff11655a1_003FJsonSerializerSettings_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtBearerExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ff611a1225a3445458f2ca3f102eed5bdcd10_003F07_003F030df6ba_003FJwtBearerExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtBearerExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ff611a1225a3445458f2ca3f102eed5bdcd10_003F07_003F030df6ba_003FJwtBearerExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtSecurityTokenHandler_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F19f907d47c6f4a2ea68238bf22de133a16600_003Fa0_003F66d8c35f_003FJwtSecurityTokenHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtSecurityTokenHandler_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F19f907d47c6f4a2ea68238bf22de133a16600_003Fa0_003F66d8c35f_003FJwtSecurityTokenHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtSecurityTokenHandler_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F477051138f1f40de9077b7b1cdc55c6215fb0_003Ff5_003Fd716e016_003FJwtSecurityTokenHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtSecurityTokenHandler_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F477051138f1f40de9077b7b1cdc55c6215fb0_003Ff5_003Fd716e016_003FJwtSecurityTokenHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>