嵌套类中手动调用ModelState验证失败

时间:2019-03-15 07:29:15

标签: c# validation model-view-controller

所以,我有一堂课

public class Inventory
{
    [Required]
    public Routing Routing { get; set; }
    [Required]
    public List<Items> Items { get; set; }
}

并且,Routing和Items是具有自己的验证参数的单个类。

public class Routing 
{
    [Required]
    public string SenderId { get; set; }
    [Required]
    public string ReceiverId { get; set; }
    public string PartnerId { get; set; }
    [Required]
    public string MessageType { get; set; }
}

现在,我在Web API中使用模型验证,效果很好。

public async Task<IActionResult> Post([FromBody] Inventory request, [FromQuery(Name = "CorrelationId")] string correlationId)
{
    ....
    // Working just fine, validating the incoming request schema as defined by Inventory class
}

如果用户/消费者使用错误的模式发送POST请求,它将在HTTP级别失败并显示400 BAD请求,并且控制甚至不在Post方法主体内。我希望控件进入Post方法中。

现在,我正在进行手动验证

public async Task<IActionResult> Post([FromBody] string request, [FromQuery(Name = "CorrelationId")] string correlationId)
{
    Inventory obj = JsonConvert.DeserializeObject<Inventory>(request);
    var context = new ValidationContext(obj, serviceProvider: null, items: null);
    var validationResults = new List<ValidationResult>();
    bool isValid = Validator.TryValidateObject(obj, context, validationResults); 

    if (!isValid)
    {
        // Valid even if I omit some parameters of nested classes Routing or Items 
        foreach (var validationResult in validationResults)
        {
            Console.WriteLine(validationResult.ErrorMessage);
        }
    }
} 

现在,例如,如果我从SenderId类中省略了一个Routing,则在上面的手动验证中显示“有效”。

我想要什么:-Post方法内的架构/模型验证,如果无效,请列出Post方法内的所有错误。

1 个答案:

答案 0 :(得分:0)

如果您真的想要那种设计,那么就必须

  1. 在您的客户中,您需要将其作为文本/纯文本传递。例如:
  

POST / api / values?correlationId = 123 HTTP / 1.1主机:localhost:5551   内容类型:文本/纯文本缓存控制:无缓存邮递员令牌:   b766b3d6-9478-43b1-b49c-2677e0b08dec {“路由”:{“ senderId”:   “ 123”,“ receiverId”:“ 456”,“ partnerId”:“ 777”,“ messageType”:   “ 888”},“ items”:[]}

  1. 在asp.net核心中,您需要接受文本/纯文本

    公共类TextPlainInputFormatter:TextInputFormatter {     公共TextPlainInputFormatter()     {         SupportedMediaTypes.Add(“ text / plain”);         SupportedEncodings.Add(UTF8EncodingWithoutBOM);     }

    protected override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }
    
    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
    {
        string data = null;
        using (var streamReader = context.ReaderFactory(context.HttpContext.Request.Body, encoding))
        {
            data = await streamReader.ReadToEndAsync();
        }
        return InputFormatterResult.Success(data);
    }
    

    }

  2. 添加TextPlainInputFormatter:

    services.AddMvc(options => {options.InputFormatters.Add(new TextPlainInputFormatter());});