1

I am trying to get cache working on my API call but every time I do a request it goes straight into my lookup service code.

I have two services, stock and productlookup. The stock calls the productlookup to check to see if there is a product available for the stock.

To reduce the load on the lookup service I wanted to cache the requests to ease the load on the lookup service because the same request will be performed quite a few times. The problem is that even with the caching in place the code in the lookup is still being performed.

My setup code on my lookup service:

app.MapGet("/{ClientCode}/Stock/Lookup/{Sku}", Get)
   .WithApiVersionSet(vs)
   .Produces<LocationAdjustDto>(StatusCodes.Status200OK)
   .Produces<LocationAdjustDto>(StatusCodes.Status404NotFound)
   .WithSummary("Get Request.")
   .WithOpenApi()
   .MapToApiVersion(1)
   .CacheOutput();

public async Task<IResult> Get(IStockService stockService, IValidator<StockLookupRequest> validator, 
 [AsParameters] StockLookupRequest lookupRequest)
{}

My Program.cs file:

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddEnvironmentVariables();
builder.Host.UseSerilog((context, configuration) =>     configuration.ReadFrom.Configuration(context.Configuration));
builder.Services.AddHealthChecks();
builder.Services.AddIdentityAuthentication(builder.Configuration, false);
builder.Services.AddUrlSegmentApiVersioning();
builder.Services.AddRepositories(builder.Configuration);
builder.Services.AddLookupService();
builder.Services.AddCarter();
builder.Services.AddOpenApi();
builder.Services.AddAuthorization();
builder.Services.AddOutputCache();

var app = builder.Build();

app.MapCarter();
app.UseOutputCache();
app.UseAuthorization();
app.Run();

We also do have a RequireAuthorization();.

Also calling the Lookup service using the GET request through Bruno doesn't work either.

1 Answer 1

2

I found out the issue. It relates to the Authorization so it never caches. Adding a custom policy which I found somewhere else allows me to handle the authorization header.

code for reference

public class OutputCachePolicy : IOutputCachePolicy
{

    public static readonly OutputCachePolicy Instance = new();

    private OutputCachePolicy()
    {
    }

    ValueTask IOutputCachePolicy.CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        var attemptOutputCaching = AttemptOutputCaching(context);
        context.EnableOutputCaching = true;
        context.AllowCacheLookup = attemptOutputCaching;
        context.AllowCacheStorage = attemptOutputCaching;
        context.AllowLocking = true;

        // Vary by any query by default
        context.CacheVaryByRules.QueryKeys = "*";
        return ValueTask.CompletedTask;
    }
    // this never gets hit when Authorization is present
    ValueTask IOutputCachePolicy.ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        return ValueTask.CompletedTask;
    }

    ValueTask IOutputCachePolicy.ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        var response = context.HttpContext.Response;
        context.AllowCacheStorage = true;

        return ValueTask.CompletedTask;
    }

    private static bool AttemptOutputCaching(OutputCacheContext context)
    {
        // Check if the current request fulfills the requirements to be cached

        var request = context.HttpContext.Request;

        // Verify the method
        if (!HttpMethods.IsGet(request.Method) && !HttpMethods.IsHead(request.Method))
        {
            return false;
        }

        // Verify existence of authorization headers
        //if (!StringValues.IsNullOrEmpty(request.Headers.Authorization) || request.HttpContext.User?.Identity?.IsAuthenticated == true)
        //{
        //    return false;
        //}
        return true;
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.