Вы можете использовать конструктор валидатора вместо RuleSet в качестве обходного пути для этой проблемы.Просто создайте перечисление внутри класса валидатора и затем используйте его значение при создании валидатора.
Таким образом, корректные правила будут активированы в зависимости от того, какой режим установлен в конструкторе.
public class UserValidator : AbstractValidator<User>
{
public enum Mode
{
Create,
Edit
}
public UserValidator()
{
// Default rules...
}
public UserValidator(UserValidator.Mode mode)
: this()
{
if (mode == Mode.Edit)
{
// Rules for Edit...
RuleFor(so => so.SomeMember)
.SetValidator(
new SomeMemberValidator(SomeMemberValidator.Mode.SomeMode))
}
if (mode == Mode.Create)
{
// Rules for Create...
RuleFor(so => so.SomeMember)
.SetValidator(
new SomeMemberValidator())
}
}
}
Я думаюна самом деле это более гибкий метод, чем использование RuleSet.
Существует только одна небольшая проблема, связанная с интеграцией FluentValidation MVC: User
класс не может иметь атрибут [Validator(typeof(UserValidator))]
, потому что UserValidator будет создан с использованием конструктора по умолчанию, передможет делать все что угодно в методе контроллера.
Validator должен быть создан и вызван вручную.Вот так например:
public class UserController : Controller
{
[HttpPost]
public ActionResult Create(User userData)
{
var validator = new UserValidator(UserValidator.Mode.Create);
if (ValidateWrapper(validator, userData, this.ModelState))
{
// Put userData in database...
}
else
{
// ValidateWrapper added errors from UserValidator to ModelState.
return View();
}
}
private static bool ValidateWrapper<T>(FluentValidation.AbstractValidator<T> validator, T data, ModelStateDictionary modelState)
{
var validationResult = validator.Validate(data);
if (!validationResult.IsValid)
{
foreach (var error in validationResult.Errors)
modelState.AddModelError(error.PropertyName, error.ErrorMessage);
return false;
}
return true;
}
}