簡體   English   中英

自定義驗證屬性未在 Model 上驗證 - WebAPI C# 和 JSON

[英]Custom Validation Attribute not validating on Model - WebAPI C# and JSON

我創建了一個 Model 和一個自定義驗證屬性,以確保該值大於零。 我遇到的問題是自定義屬性的構造函數被命中,但 IsValid 覆蓋永遠不會被命中。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class GreaterThanZeroAttribute : ValidationAttribute
{
    /// <summary>
    /// Ensures that the value is greater than zero.
    /// </summary>
    public GreaterThanZeroAttribute()
        : base("The value {0} must be greater than 0.")
    {
    }

    public override bool IsValid(object value)
    {
        bool isValueLong = long.TryParse(value?.ToString(), out long longValue);

        if (isValueLong && longValue > 0)
            return true;
        else
            return false;
    }
}
public class ApplicationModel
{
    [Required]
    public string Name { get; set; }

    [GreaterThanZero]
    public IEnumerable<string> AssignedUserGroupIDs { get; set; }
}

現在,客戶端將在 JSON 中設置AssignedUserGroupIDs 我想驗證該集合中的每個 ID 是否大於零。

這是請求的示例 JSON:

{ 
    "name": "Test Application",
    "assignedUserGroupIDs": [ "1", "-1001" ] 
} 

對於它的價值,我使用 JsonOptions 來使用駝峰式大小寫作為屬性名稱並將字符串轉換為枚舉。 我之所以提到這一點,是因為我不確定 Json 是否會導致任何問題。

public static IServiceCollection AddWebApiServices(this IServiceCollection services)
{
    _ = services ?? throw new ArgumentNullException(nameof(services));

    Setup.AddServices(services);
    services.AddMvcCore(ConfigureDefaults)
        .AddJsonFormatters()
        .AddJsonOptions(options =>
        {
            options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            options.SerializerSettings.Converters.Add(new StringEnumConverter());
        })
        .AddCors("*")
        .AddControllers();

    return services;
}

這是 Controller:

        [HttpPost]
        [Route("applications")]
        [EnableCors(PolicyName = CorsPolicies.Default)]
        public IActionResult CreateApplication([FromBody] ApplicationModel postModel)
        {
            List<long> assignedUserGroups = new List<long>();

            foreach (string stringUserGroupID in postModel.AssignedUserGroupIDs)
            {
                assignedUserGroups.Add(Convert.ToInt64(stringUserGroupID));
            }
            
            // business logic here...

            return new JsonResult(applicationID);
        }

如果您想驗證集合中的每個 ID 是否大於零,則需要將該value強制轉換為IEnumerable ,然后遍歷列表中的每個項目:

/*
 * Changes:
 * 1. Rename to CollectionGreaterThanZero to better reflect this validation is
 *    against a collection.
 * 2. Change AttributeUsage to include Field, as there is a backing field behind
 *    AssignedUserGroupIDs { get; set; }, and when the data comes in, the backing
 *    field gets set. That's when you want to run your validation.
 * 3. Set AllowMultiple=false as there is no point to run this validation multiple
 *    times on the same property or field.
*/

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,  AllowMultiple = false)]
public class CollectionGreaterThanZeroAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        // This will case the value to IEnumerable silently.
        var enumerable = value as IEnumerable;
        if (enumerable != null)
        {
            foreach (var item in enumerable)
            {
                bool isLong = long.TryParse(item?.ToString(), out long longValue);
                if (!isLong)
                {
                    return false;
                }
            }

            // I don't know if you consider an empty collection as a valid 
            // collection or not in your domain.
            return true;
        }

        return false;
    }
}

顯示它被擊中的屏幕截圖:

在此處輸入圖像描述

暫無
暫無

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

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