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