I have an ASP.net Core 3.1 web api project. In one of my controllers, I have a Post method that accepts a request object that contains an array of objects. I have done this same thing in ASP.Net using .Net Framework and in ASP.Net Core 2.1 with no problem. However, in 3.1 The array is not getting bound when calling the api method.
[HttpPost(), Route("{id}/Answers")]
[ProducesResponseType(typeof(QuestionaireAnswerModel), StatusCodes.Status201Created)]
public async Task<IActionResult> PostAnswers(int id, QuestionaireAnswerRequestModel request) {
try
{
if (ModelState.IsValid)
{
if (request.Answers == null || request.Answers.Count < 1)
return BadRequest("Answers are required.");
var result = await _service.CreateQuestionaireAnswersAsync(id, request);
return Created($"https://blah/api/{result.Id}", result);
}
else { return BadRequest(ModelState); }
}
catch (Exception ex)
{
var message = $"An error occurred posting answers for Questionnaire. Questionnaire Id: {id}, UserName: {request.UserName}";
_logger.LogError(ex, message);
return StatusCode(StatusCodes.Status500InternalServerError, message);
}
}
c# models
public class QuestionaireAnswerRequestModel
{
public string UserName { get; set; }
public IEnumerable<QuestionAnswerRequestModel> Answers;
}
public class QuestionAnswerRequestModel
{
public int QuestionId { get; set; }
public bool Answer { get; set; }
}
Sample request used in postman to test {
"userName": "testuser",
"answers": [{
"questionId": 1,
"answer": "false"
}]
}
Trying to debug and the answers list is always null. I have tried using an array and List type instead of IEnumerable with no luck. I know they changed the serializer in 3.1 but not sure why an array is not able to serialize? Does Anyone know the answer? here is my startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var connection = Configuration.GetConnectionString("HealthScreeningConnection");
services.AddEntityFrameworkSqlServer()
.AddEntityFrameworkProxies()
.AddDbContextPool<HealthScreeningContext>((serviceProvider, options) => {
options.UseSqlServer(connection).UseInternalServiceProvider(serviceProvider);
options.UseLazyLoadingProxies();
});
services.AddScoped<IQuestionareService, QuestionaireService>();
services.AddScoped<IAccountService, AccountService>();
services.AddControllers();
services.AddCors(opts => {
opts.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var nlogFilePath = "nlog.config";
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
nlogFilePath = $"nlog.{env.EnvironmentName}.config";
}
NLog.LogManager.LoadConfiguration(nlogFilePath);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}