Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I log HTTP requests when using Refit in .net core?

I want to use Refit to query an API. First thing, I need to obtain an access token which is a POST request returning a status 400. I have no idea what causes the problem, thus I would like to see the actual raw request that is being sent to the API. Unfortunately, I haven't managed to get this to work and most likely I will need it more often during development.

I found this handsome logger and thought I could use it in my program.cs as a DelegatingHandler like this:

builder.Services.AddRefitClient<IVismaConnect>().ConfigureHttpClient(config =>
{
    config.BaseAddress = new Uri("https://ENDPOINT");
    config.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "SOMECREDENTIALSTHATEVENTUALLYWILLBEREADFROMACONFIGFILE");
    config.DefaultRequestHeaders.TryAddWithoutValidation("content-type", "application/x-www-form-urlencoded");
}).AddHttpMessageHandler<HttpLoggingHandler>();

Now I get a fancy error message telling me that "No service for type ...HttpLoggingHandler has been registered":

enter image description here

So I googled a bit and found a hint that I need to register the HttpLoggingHandler as a Singleton, thus I put this line right above my code in program.cs (tried it below as well, did not make any difference):

builder.Services.AddTransient<HttpLoggingHandler>();

Now I get another exception saying that "The 'InnerHandler' property must be null. 'DelegatingHandler' instances provided to 'HttpMessageHandlerBuilder' must not be reused or cached":

enter image description here

After more googling I found some documentation about HTTP logging in ASP.NET core from Microsoft.

That did not change anything, the exception still popped up, so I tried just the MS suggestion without the HttpLoggingHandler I tried earlier, but that did not generate any output whatsoever.

Any suggestions on how to properly log the raw requests Refit sends to a server would be highly appreciated. See below the full program.cs file:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
});

// Add services to the container.

builder.Services.AddTransient<HttpLoggingHandler>();

builder.Services.AddRefitClient<IVismaConnect>().ConfigureHttpClient(config =>
{
    config.BaseAddress = new Uri("https://ENDPOINT");
    config.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "SOMECREDENTIALSTHATEVENTUALLYWILLBEREADFROMACONFIGFILE");
    config.DefaultRequestHeaders.TryAddWithoutValidation("content-type", "application/x-www-form-urlencoded");
}); //.AddHttpMessageHandler<HttpLoggingHandler>();

builder.Configuration
    .SetBasePath(Environment.CurrentDirectory)
    .AddJsonFile("appsettings.json", true)
    .AddUserSecrets(Assembly.GetExecutingAssembly(), true)
    .AddEnvironmentVariables()
    .Build();


ConfigurationManager configuration = builder.Configuration;
C.Instance.SetConfiguration(configuration);


builder.Logging.ClearProviders();
builder.Logging.AddConfiguration(configuration).AddConsole().AddDebug().AddSimpleConsole();

IWebHostEnvironment environment = builder.Environment;


// Add services to the container.
builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      builder =>
                      {
                          builder.WithOrigins("*").AllowAnyMethod().AllowAnyHeader();
                      });
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpLogging();

app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
    new string[] { "My Response Header Value" };

await next();
});

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html"); ;

app.Run();
like image 256
Aileron79 Avatar asked Apr 10 '26 00:04

Aileron79


1 Answers

Removing constructor from your custom handler should do it. The current implementation of the handler always initialise itself with the parameterised constructor, which makes InnerHandler not null.

like image 56
tia Avatar answered Apr 12 '26 06:04

tia