【发布时间】:2021-06-09 02:55:22
【问题描述】:
我正在尝试使用 FluentValidation nuget 包验证请求。我正在使用一个具有多个文本框字段的 winform,如下面的方法所示。当用户单击确认按钮时,系统将尝试使用文本框中的数据参数创建我的车辆类的新实例。我想使用验证检查器来查看他们创建的车辆实例是否有效。我遇到的问题是,当有一个文本框需要转换为 in 或 decimal 以创建实例时,我收到错误消息 Input string was not in a correct format. 有没有办法可以传递 int/decimal 值在我检查验证它们之前作为字符串,然后将它们作为正确的形式传回?
这是我的按钮点击方法:
protected override void CheckInputFields()
{
string registration = textBoxRegistrationNumber.Text;
string make = textBoxMake.Text;
string model = textBoxModel.Text;
string year = textBoxYear.Text;
string cost = textBoxHireCost.Text;
ValidationAddVehicle validator = new ValidationAddVehicle();
//The issue is here. When the cost or year fields are empty, it cant convert them to decimal/int.
//Which means that the validation checker cannot do the .NotEmpty() method
ValidationResult results = validator.Validate(Vehicle.New(registration, make, model, Convert.ToDecimal(cost), Convert.ToInt32(year)));
if (results.IsValid == false)
{
foreach (ValidationFailure error in results.Errors)
MessageBox.Show($"{error.PropertyName} : {error.ErrorMessage}");
return;
}
else
{
MessageBox.Show("Success");
return;
}
}
这是我创建车辆的方法:
public static Vehicle New(string registration, string make, string model, decimal cost, int year)
{
return new Vehicle
{
Registration = registration,
Model = model,
Make = make,
Year = year,
Cost = cost
};
}
这是我的验证检查器:
public class ValidationAddVehicle : AbstractValidator<Vehicle>
{
public ValidationAddVehicle()
{
//Registration
RuleFor(v => v.Registration)
.Cascade(CascadeMode.Stop)
.NotEmpty().WithMessage("{PropertyName} is empty")
.Length(2, 10).WithMessage("Length ({TotalLength}) of {PropertyName} is invalid")
.Must(IsValidRegistration).WithMessage("{PropertyName} contains invalid characters")
.Must(Exists).WithMessage("{PropertyName} already exists");
//Make
RuleFor(v => v.Make)
.Cascade(CascadeMode.Stop)
.NotEmpty().WithMessage("{PropertyName} is empty")
.Length(1, 50).WithMessage("Length ({TotalLength}) of {PropertyName} is invalid")
.Must(IsValidMake).WithMessage("{PropertyName} contains invalid characters");
//Model
RuleFor(v => v.Model)
.Cascade(CascadeMode.Stop)
.NotEmpty().WithMessage("{PropertyName} is empty")
.Length(1, 50).WithMessage("Length ({TotalLength}) of {PropertyName} is invalid")
.Must(IsValidModel).WithMessage("{PropertyName} contains invalid characters");
//Cost
RuleFor(v => v.Cost)
.Cascade(CascadeMode.Stop)
.NotEmpty().WithMessage("{PropertyName} is empty")
.Must(IsValidCost).WithMessage("{PropertyName} contains invalid characters")
.Must(CostValue).WithMessage("{PropertyName} must be greater than zero");
//Year
RuleFor(v => v.Year)
.Cascade(CascadeMode.Stop)
.NotEmpty().WithMessage("{PropertyName} is empty")
.Must(IsValidYear).WithMessage("{PropertryName} is an invalid value")
.Must(Range).WithMessage("{PropertryName} must be between 1886 and {DateTime.Now.AddYears(1).ToString()}");
}
protected bool IsValidRegistration(string registration) => String.Concat(registration.Where(r => !Char.IsWhiteSpace(r))) != "" && registration.All(Char.IsLetterOrDigit);
protected bool Exists(string registration) => !Business.VehicleList.Any(x => x.Registration == registration);
protected bool IsValidMake(string make) => String.Concat(make.Where(m => !Char.IsWhiteSpace(m))) != "" && make.All(Char.IsLetter);
protected bool IsValidModel(string model) => String.Concat(model.Where(m => !Char.IsWhiteSpace(m))) != "" && model.All(Char.IsLetterOrDigit);
protected bool IsValidCost(decimal cost) => String.Concat(cost.ToString().Where(c => !Char.IsWhiteSpace(c))) != "" && Regex.IsMatch(cost.ToString(), @"^-?[0-9]*\.?[0-9]+$");
protected bool CostValue(decimal cost) => cost > 0;
protected bool IsValidYear(int year) => String.Concat(year.ToString().Where(y => !Char.IsWhiteSpace(y))) != "" && Regex.IsMatch(year.ToString(), @"^[0-9]");
protected bool Range(int year) => year.ToString().Length == 4 && Convert.ToDateTime($"{year},1,1") <= DateTime.Now.AddYears(1) && year >= 1886;
}
有没有一种方法可以首先将成本和年份作为字符串传递给车辆类,检查有效性,然后将它们转换为正确的数据类型,或者我可以使用另一种方法来实现这一点?
【问题讨论】:
-
一种方法是在类上为
YearString添加一个额外的属性,并在您的验证中使用它,但我更愿意在用户输入时验证文本框和只允许接受的字符(数字、逗号、句号...等),然后应用您的流利验证
标签: c# winforms validation fluentvalidation