簡體   English   中英

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

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

所以,我的 controller 里面有一個 create 方法:

[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")));
    }
}

如您所見,如果沒有 model 它將返回錯誤請求(有效)。

但是下一行說明if (.ModelState.IsValid)永遠不會起作用。 即使在null處具有必需的屬性,它也始終返回有效。

我寫了一個測試,總是失敗:

[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);
}

正如您在此處看到的,我只是傳遞了一個沒有設置任何屬性的CategoryViewModel ,但它失敗了。

視圖 model 如下所示:

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; }
}

我能想到的唯一另一件事是我禁用了自動 state 驗證:

.ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; });

我認為這讓我可以在 controller 內處理它。

有沒有人遇到過這個?

您正在運行單元測試而不是端到端集成測試,因此在執行測試時某些框架問題未運行。

這些數據注釋屬性是元數據,僅在運行時由框架識別,而不是在隔離單元測試期間,因為它們在應用程序運行時由 model 綁定器實際讀取。

如果打算讓框架驗證 model,則需要進行集成測試。

ASP.NET 內核中的參考集成測試

否則,在安排測試時,被測對象(控制器)必須手動更新其ModelState ,以便在執行時表現出預期的行為。

通過使用AddModelError添加錯誤來測試無效的 model state,如下面的測試所示:

[Test]
public async Task ReturnBadRequestIfNullRequiredProperty() {
    // Arrange / Assemble
    var services = ConversionsControllerContext.GivenServices();
    var controller = services.WhenCreateController();
    controller.ModelState.AddModelError("Name","Name required"); //<-- Invalidate model state
    //...other desired errors.

    // Act
    var actionResult = await controller.CreateAsync(new ConversionViewModel());
    var badRequestResult = actionResult as BadRequestResult;

    // Assert
    badRequestResult.Should().NotBeNull();
    badRequestResult?.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
}

參考測試 ASP.NET 內核中的 controller 邏輯

如果您使用services.AddMvcCore而不是services.AddMvc然后添加

services.AddDataAnnotations();

到 Startup.ConfigureServices 方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM