So, I have my controller with a create method in it:
[Authorize]
[Route("[controller]")]
[ApiController]
public class ConversionsController : ControllerBase
{
private readonly IGenericService<Conversion> _conversionService;
public ConversionsController(IGenericService<Conversion> conversionService) => _conversionService = conversionService;
/// <summary>
/// Creates a new conversion
/// </summary>
/// <param name="conversion">The conversion</param>
/// <returns></returns>
[HttpPost]
[ProducesResponseType(typeof(Conversion), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync(ConversionViewModel conversion)
{
if (conversion == null) return BadRequest();
if (!ModelState.IsValid) return BadRequest(ModelState);
var request = ModelFactory.Create(conversion);
_conversionService.Create(request);
await _conversionService.SaveChangesAsync();
return Created(nameof(Get), new Sxp.Web.ActionResult<Conversion>(request, string.Format(Resources.EntityCreated, "conversion")));
}
}
As you can see, if there is no model it will return a bad request (which works).
But the next line stating if (!ModelState.IsValid)
never works. It always returns valid even with a required property at null.
I have written a test, which always fails:
[Test]
public async Task ReturnBadRequestIfNullRequiredProperty()
{
// Assemble
var services = ConversionsControllerContext.GivenServices();
var controller = services.WhenCreateController();
// Act
var actionResult = await controller.CreateAsync(new ConversionViewModel());
var badRequestResult = actionResult as BadRequestResult;
// Assert
badRequestResult.Should().NotBeNull();
badRequestResult?.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
}
As you can see here, I just pass a CategoryViewModel
with no properties set at all, but it fails.
The view model looks like this:
public class ConversionViewModel
{
public int Id { get; set; }
[Range(1, int.MaxValue, ErrorMessageResourceName = "RangeErrorMessage", ErrorMessageResourceType = typeof(Resources))] public int FeedId { get; set; }
[Required(ErrorMessageResourceName = "RequiredErrorMessage", ErrorMessageResourceType = typeof(Resources)), StringLength(100, ErrorMessageResourceName = "StringLengthErrorMessage", ErrorMessageResourceType = typeof(Resources))] public string Name { get; set; }
[Required(ErrorMessageResourceName = "RequiredErrorMessage", ErrorMessageResourceType = typeof(Resources)), StringLength(100, ErrorMessageResourceName = "StringLengthErrorMessage", ErrorMessageResourceType = typeof(Resources))] public string FieldName { get; set; }
[Required(ErrorMessageResourceName = "RequiredErrorMessage", ErrorMessageResourceType = typeof(Resources)), StringLength(100, ErrorMessageResourceName = "StringLengthErrorMessage", ErrorMessageResourceType = typeof(Resources))] public string Expression { get; set; }
public double Value { get; set; }
public MathOperator MathOperator { get; set; }
public FilterOperator FilterOperator { get; set; }
}
The only other thing I can think of, is I disabled automatic state validation:
.ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; });
Which I thought allowed me to handle it within the controller.
Has anyone come across this before?
Aucun commentaire:
Enregistrer un commentaire