jeudi 24 octobre 2019

Return BadRequest with null required property in model .net core web api

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