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":

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":

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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With