我正在尝试使用" FluentValidation"来实现自定义验证。进入一个WebApi项目。
所以,在我的Controller的动作方法(POST)中,我使用基类(Person)作为参数:
[Route("persons/compute")] public HttpResponseMessage Compute(Person person) { ... }
从nuget我已经安装了" FluentValidation和FluentValidation.WebApi"包。
我有以下代码:
[Serializable]
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CNP { get; set; } //unique identifier
}
[Serializable]
[Validator(typeof(StudentValidator))]
public class Student : Person
{
public string CollegeName { get; set; }
}
验证器类是:
public abstract class PersonValidator<T>: AbstractValidator<T> where T : Person
{
protected abstract PersonClassType PersonClassType { get; }
public PersonValidator()
{
Custom(p => {
if (string.IsNullOrEmpty(p.CNP))
{
return new ValidationFailure("Insured.UniqueIdentifier", "CNP/CUI obligatoriu!");
}
else
{
decimal cnp;
bool isCNP = (p.CNP.Length == 13 && decimal.TryParse(p.CNP, out cnp));
if (!isCNP)
{
return new ValidationFailure("Insured.UniqueIdentifier", "CNP invalid!");
}
}
return null;
});
}
}
派生类的Validator是:
public class StudentValidator : PersonValidator<Student>
{
public StudentValidator ()
{
Custom(p => {
if (string.IsNullOrEmpty(p.CollegeName))
{
return new ValidationFailure("ekfjekfj", "College Name mandatory!");
}
return null;
});
}
protected override PersonClassType PersonClassType
{
get
{
return PersonClassType.Student;
}
}
}
[DataContract]
public enum PersonClassType
{
None = int.MinValue,
Student = 1,
Employee = 2
}
在Global.asax.cs中,在Application_Start()中,我添加了:
FluentValidationModelValidatorProvider.Configure(GlobalConfiguration.Configuration);
我需要什么?:在action方法中,在控制器中,使用类型基类(Person)的参数对子项/派生(例如:学生,员工等)的classess进行验证身体(POST)。因此,需要知道切换到正确的验证器。 我想这个问题可以通过&#34; Factory&#34;来解决。或者&#34; DepencyInjection&#34;,但我不知道如何。 我希望能让自己清楚。 我的appollogize,但我的英语并不完美。
我很感激一个明确的解决方案,因为我试图用Factory实现,但我没有管理。如果需要,我可以用我的代码发送zip文件。 非常感谢提前!
答案 0 :(得分:1)
为了解决这个问题,我创建了以下类:
public class ValidatorBase<TBase> : AbstractValidator<TBase>
{
public void MapDerivedValidator<TType, TValidatorType>()
where TValidatorType : IEnumerable<IValidationRule>, IValidator<TType>, new()
where TType: TBase
{
When(t => t.GetType() == typeof(TType), () => AddDerivedRules<TValidatorType>());
}
private void AddDerivedRules<T>()
where T : IEnumerable<IValidationRule>, new()
{
IEnumerable<IValidationRule> validator = new T();
foreach (var rule in validator)
{
this.AddRule(rule);
}
}
}
要使用它,请将Person验证器更改为继承ValidatorBase(将AbstractValidator<Person>
替换为ValidatorBase<Person>
)。
现在,当您为Person验证设置规则时,请添加以下行:
MapDerivedValidator<Student, StudentValidator>
StudentValidator可以像往常一样继承AbstractValidator<Student>
。
我们在这里做的基本上是有条件地包括在基类的验证器(PersonValidator)中来自派生类的规则&#39;验证类型匹配时验证器(StudentValidator)。
答案 1 :(得分:0)
为了对其他人有用,基于Jon解决方案的更新代码将是:
[Route("persons/compute")]
public HttpResponseMessage Compute([FromBody]Person person)
{...}
在Global.asax.cs中:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
JsonSerializerSettings serializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
serializerSettings.TypeNameHandling = TypeNameHandling.All;
serializerSettings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
serializerSettings.FloatParseHandling = FloatParseHandling.Decimal;
FluentValidationModelValidatorProvider.Configure(GlobalConfiguration.Configuration);
}
添加类:ValidatorBase(参见上面的Jon回答)
更新PersonValidator.cs如下:
public PersonValidator()
{
MapDerivedValidator<Student, StudentValidator>();
MapDerivedValidator<Employee, EmployeeValidator>();
//.... other derived classes
...
}
public class StudentValidator : ValidatorBase<Student>
{ ...}
谢谢Jon!