Failed to construct 'Request': Request with GET/HEAD method cannot have body
please, I need your help. I'm learning to develop APIs, so I created an Asp.Net core 6 Api using VS2022 version 17.26. when I tried to test my API through Swager I got an error message "Failed to construct 'Request': Request with GET/HEAD method cannot have body".
I tried postman and I got another error message:
{
"errors": {
"": [
"A non-empty request body is required."
],
"request": [
"The request field is required."
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-8dc5d67e871061e09d8d264769b31a9f-52123737ebab3abc-00"
I struggled for the last 5 days trying to figure out the issue with no luck.
This is my program file code:
var CORS_POLICY = "CorsPolicy";
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("Logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
// Add services to the container.
builder.Services.AddControllers(options =>
{
options.ReturnHttpNotAcceptable = true;
}).AddNewtonsoftJson()
.AddXmlDataContractSerializerFormatters();
// add DbContext
builder.Services.AddDbContext<AppDbContext>(options =>
options
.UseSqlServer(builder.Configuration.GetConnectionString("DataConnectionString"),
sqlServerOptionsAction: sqloptions =>
{
sqloptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(5),
errorNumbersToAdd: null);
}));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Call UseServiceProviderFactory on the Host sub property
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterMediatR(typeof(Program).Assembly);
containerBuilder.RegisterModule<ApplicationModule>();
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(CORS_POLICY);
app.UseHttpsRedirection();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API");
});
app.MapControllers();
app.Run();
I could not reach the endpoint.
I want to mention that I’m using (Ardalis.ApiEndpoints) package and I have created two endpoints Create and List. So, When I run the API and test Create EndPoint it works fine but when I run the List EndPoint I got the error. I think it could be a routing issue not sure about that.
Folder: \Endpoints \City
Create EndPoint:
namespace EA.Api.CityEndpoints
{
public class Create : EndpointBaseAsync
.WithRequest<CreateCityCommand>
.WithActionResult<CreateCityCommandResponse>
{
private readonly IMediator _mediator;
public Create(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
[HttpPost(CreateCityCommand.Route)] //"api/cities"
[SwaggerOperation(
Summary = "Creates a new City",
Description = "Creates a new City",
OperationId = "cities.Create",
Tags = new[] { "CityEndpoints" })
]
public override async Task<ActionResult<CreateCityCommandResponse>>
HandleAsync([FromQuery] CreateCityCommand request, CancellationToken cancellationToken = default)
{
var response = await _mediator.Send(request);
return Ok(response);
}
}
}
List EndPoint:
namespace EA.Api.CityEndpoints
{
public class List : EndpointBaseAsync
.WithRequest<GetCitiesListQuery>
.WithActionResult<List<CitiesListVm>>
{
private readonly IMediator _mediator;
public List(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
[HttpGet(GetCitiesListQuery.Route)] //"api/cities"
[SwaggerOperation(
Summary = "List Cities",
Description = "List Cities",
OperationId = "cities.List",
Tags = new[] { "CityEndpoints" })
]
public override async Task<ActionResult<List<CitiesListVm>>> HandleAsync(GetCitiesListQuery request,
CancellationToken cancellationToken = default)
{
var dtos = await _mediator.Send(new GetCitiesListQuery());
return Ok(dtos);
}
}
}
I figure out the cause of the problem but still tried to solve it. The problem occurs due to the use of MediatR. So when I removed the GetCitiesListQuery from the List Endpoint and make it Without a Request and Without a response, the endpoint work fine. Putting them back I got the same issue.
I don’t know why but let me explain how I’m using it. Maybe someone can help and direct me to what I’m doing wrong here.
My solution contains the following apps:
Asp.net Core Api
Packages used for Api 1.MediatR 2.Ardalis.ApiEndpoints 3.Autofac.Extensions.DependencyInjection
Class Library EA.Application which contain my Commands and Handlers classes for Request\Response messages.
Packages used for Class Library 1.Autofac 2.MediatR.Extensions.Autofac.DependencyInjecti
I have a class in my Class Libaray with the name ApplicationModule contains all of the command and Handler classes which I registered during app startup in program file.
public class ApplicationModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<GetCitiesListQuery>().AsImplementedInterfaces();
builder.RegisterType<GetCitiesListQueryHandler>().AsImplementedInterfaces();
}
}
public class GetCitiesListQuery : IRequest<List<CitiesListVm>>
{
public const string Route = "/cities";
}
public class GetCitiesListQueryHandler : IRequestHandler<GetCitiesListQuery, List<CitiesListVm>>
{
public async Task<List<CitiesListVm>> Handle(GetCitiesListQuery request, CancellationToken cancellationToken)
{
var allCities = (await _cityRepository.ListAllAsync()).OrderBy(x => x.CityNameEng);
return _mapper.Map<List<CitiesListVm>>(allCities);
}
}
public class CitiesListVm
{
public int CityId { get; set; }
public string CityNameEng { get; set; } = string.Empty;
public string CityNameArb { get; set; } = string.Empty;
}
Please, if someone knows the issue let me know.
Comments
Post a Comment