验证发送到Web API控制器的模型

时间:2015-06-30 08:15:16

标签: c# validation asp.net-web-api

在调用Web API服务时,我需要将以下类属性发送到其控制器方法:

public class FindBookingRequestModel 
{
    public string ReservationNumber { get; set; }
    public string CreditCardNumber { get; set; }
    public string EmailAddress { get; set; }
    public string Origin { get; set; }
    public string Destination { get; set; }
    public DateTime? StartDate { get; set; }
}

根据用例,我有三个场景,我需要验证发送到web api控制器的模型,并确保填充以下类属性,否则我需要抛出BadRequest异常。

  1. 用例:

    {
        "ReservationNumber": "WERTSDFFSDF",
        "CreditCardNumber" : "3333"
    }   
    
  2. 用例

    {
        "ReservationNumber" : "WERTSDFFSDF",
        "EmailAddress" : "somene@gmail",
        "Origin" : "FRA",
        "Destination" : "MUN"
    }
    
  3. 用例

    {
        "StartDate" : "2015-12-15",
        "EmailAddress" : "somene@gmail",
        "Origin" : "FRA",
        "Destination" : "MUN"
    }
    
  4. 因此,如果我们将此模型发送给控制器,则应该是错误的:

    {
        "ReservationNumber": "WERTSDFFSDF",
        "Origin" : "FRA",
    } 
    

    或者这个:

    {
        "EmailAddress" : "somene@gmail",
         "StartDate" : "2015-12-15",
    }
    

    确保按照上述用例中的说明传递字段的最有效方法是什么?

1 个答案:

答案 0 :(得分:0)

您可以实施IValidatableObject来执行跨属性验证,也可能也值得考虑单个属性值验证。

我建议尽可能使用正则表达式来表示属性值(只有在属性值不为null时才会运行它们,因为所有有效类型都没有任何必填字段,请避免使用[Required]属性)然后使用Validate方法进行交叉属性验证:

public class FindBookingRequestModel : IValidatableObject
{
    [RegularExpression("[A-Z]+")]
    public string ReservationNumber { get; set; }

    [RegularExpression("...")] // Find a regex online
    public string CreditCardNumber { get; set; }

    [RegularExpression("...")] // Find a regex online
    public string EmailAddress { get; set; }

    [RegularExpression("[A-Z]{3}")]
    public string Origin { get; set; }

    [RegularExpression("[A-Z]{3}")]
    public string Destination { get; set; }

    public DateTime? StartDate { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrWhiteSpace(this.ReservationNumber) 
            && !string.IsNullOrWhiteSpace(this.Origin))
        {
            yield return new ValidationResult(
                "You cannot search using Reservation Number and Origin", 
                new[] { "ReservationNumber", "Origin" });
        }

        if (!string.IsNullOrWhiteSpace(this.EmailAddress) 
            && this.StartDate != null)
        {
            yield return new ValidationResult(
                "You cannot search using Email Address and Start Date", 
                new[] { "EmailAddress", "StartDate" });
        }

        yield break;
    }
}

如果有太多无效组合,你可以这样做:

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrWhiteSpace(this.ReservationNumber) 
            && !string.IsNullOrWhiteSpace(this.CreditCardNumber)
            && this.EmailAddress == null
            && this.Origin == null
            && this.Destination == null
            && this.StartDate == null)
        {
            // OK - Only reservation number and credit card number specified
            yield break;
        }

        /// ...

        yield return new ValidationResult(
            "Invalid combination of search terms");
    }