Respawnsive / Apizr

Refit based web api client management, but resilient (retry, connectivity, cache, auth, log, priority, etc...)
https://www.apizr.net
Apache License 2.0
140 stars 12 forks source link

DistributedCacheHandler throws exception when CacheType = string as it doesn't handle null's properly #19

Closed SOFSPEEL closed 5 months ago

SOFSPEEL commented 5 months ago

The following code:

services.AddApizrManagerFor<IBlackbaudSrApi>(optionsBuilder =>
            optionsBuilder
                .WithRefitSettings(new RefitSettings { ContentSerializer = new XmlContentSerializer() })
                .WithBaseAddress(sp =>
                {
                    var config = sp.GetService<BlackbaudConfiguration>();
                    return new UriBuilder(config.Header.RootUrl).Uri;
                })
                .AddDelegatingHandler<BlackbaudMessageSrHandler>(sp => sp.GetService<BlackbaudMessageSrHandler>())
                // .WithAkavacheCacheHandler()
                .WithCacheHandler<DistributedCacheHandler<string>>()
                .WithLogging());

        services.AddDistributedMemoryCache();

results in the following exception:

System.ArgumentNullException : Value cannot be null. (Parameter 'content')
   at System.ArgumentNullException.Throw(String paramName)
   at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
   at System.Net.Http.StringContent.GetContentByteArray(String content, Encoding encoding)
   at System.Net.Http.StringContent..ctor(String content, Encoding encoding, String mediaType)
   at Apizr.SerializationExtensions.FromJsonStringAsync[T](String str, IHttpContentSerializer contentSerializer, CancellationToken cancellationToken)
   at Apizr.DistributedCacheHandler`1.GetAsync[TData](String key, CancellationToken cancellationToken)
   at Apizr.ApizrManager`1.ExecuteAsync[TApiData](Expression`1 executeApiMethod, Action`1 optionsBuilder)

I think the fix is:

https://github.com/Respawnsive/Apizr/blob/master/Apizr/Src/Caching/Apizr.Extensions.Microsoft.Caching/SerializationExtensions.cs#L45


internal static async Task<T> FromJsonStringAsync<T>(this string str, IHttpContentSerializer contentSerializer, CancellationToken cancellationToken = default)
    {
        //todo: add this null protection
        if (str == null)
        {
            return default;
        }

        var content = new StringContent(str, Encoding.UTF8, "application/json");
        return await contentSerializer.FromHttpContentAsync<T>(content, cancellationToken);
    }
JeremyBP commented 5 months ago

Thanks for reporting it. I'll investigate & fix it these days while I'm about to push the v6-pre3

JeremyBP commented 5 months ago

Just pushed the preview 3 on NuGet including a fix for it. Let me know if it does actually fix it for you.

SOFSPEEL commented 5 months ago

@JeremyBP it did fix the distributed cache for me.