[英]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.