Проверка MVC с другой ViewModel

Я написал шаблон T4, который автоматически генерирует все проверки следующим образом:

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Email).NotEmpty();
        RuleFor(x => x.Email).Length(0, 150).WithMessage("Email can not exceed 150 characters");
        RuleFor(x => x.Password).NotEmpty();
        RuleFor(x => x.Password).Length(0, 50).WithMessage("Password can not exceed 50 characters");
        RuleFor(x => x.Name).NotEmpty();
        RuleFor(x => x.Name).Length(0, 100).WithMessage("Name can not exceed 100 characters");
        RuleFor(x => x.PhoneNumber).Length(0, 50).WithMessage("PhoneNumber can not exceed 50 characters");
        RuleFor(x => x.Address).Length(0, 50).WithMessage("Address can not exceed 50 characters");
        RuleFor(x => x.Postcode).Length(0, 50).WithMessage("Postcode can not exceed 50 characters");
        RuleFor(x => x.City).Length(0, 50).WithMessage("City can not exceed 50 characters");
        RuleFor(x => x.Country).Length(0, 100).WithMessage("Country can not exceed 100 characters");
        RuleFor(x => x.UserRoleId).NotNull();
    }
}

Теперь у меня есть ViewModel, где я хочу использовать эти проверки как таковые:

[Validator(typeof(UserValidator))]
public class RegisterModel
{
    public string Email { get; set; }

    [DataType(DataType.Password)]
    public string Password { get; set; }

    [Compare("Password"), Display(Name = "Confirm Password"), DataType(DataType.Password)]
    public string ConfirmPassword { get; set; }

    public string Name { get; set; }

    [Display(Name = "Phone Number")]
    public string PhoneNumber { get; set; }
    public string Address { get; set; }
    public string Postcode { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

Мой класс отличается от того, что используется в AbstractValidator, у меня есть класс RegisterModel.

Когда я запускаю, я получаю следующую ошибку:

Невозможно привести объект типа «Web.Models.RegisterModel» к типу «DAL.User».

... что имеет смысл, поскольку это не тот же тип.

Я также пытался использовать этот способ:

public class RegisterModel
{
    [Validator(typeof(UserValidator))]
    public User UserDetails { get; set; }

    [Compare("Password"), Display(Name = "Confirm Password"), DataType(DataType.Password)]
    public string ConfirmPassword { get; set; }
}

Но не может использоваться в этом, поскольку валидатор является атрибутом уровня класса, а не атрибутом свойства.

Можно ли каким-либо образом использовать в моделях существующие правила, созданные для моих классов сущностей?

Кто-нибудь пробовал что-то подобное? Или есть другие идеи на этот счет?


person Umair    schedule 15.07.2014    source источник
comment
Чего вы хотите достичь? Если вы хотите повторно использовать класс UserValidator, я бы посоветовал вам не ожидать, что класс User будет общим типом, а будет интерфейс IUser, который определяет свойства, общие для обоих. Поскольку похоже, что реальный пользователь имеет больше/другие свойства (например, UserRoleId), которые вы можете добавить либо к другому интерфейсу, либо в валидаторе, проверьте эти другие интерфейсы и выполните пользовательскую проверку, например. идентификатор роли пользователя.   -  person Eleasar    schedule 16.07.2014
comment
Я хочу использовать те же валидаторы для класса модели, не переписывая их, и, если возможно, было бы хорошо, если бы я мог дать какие-либо дополнительные атрибуты также его свойствам. Большинство из них будут общими, но да, UserRoleId не будет указан в представлении, поэтому будет отображаться ошибка, которую я не хочу. Не могу использовать интерфейсы или изменить класс сущности, созданный EF.   -  person Umair    schedule 16.07.2014


Ответы (2)


Очевидно, что одним из решений было бы наследование от класса User:

[Validator(typeof(UserValidator))]
public class RegisterModel : User
{
    [Compare("Password"), Display(Name = "Confirm Password"), DataType(DataType.Password)]
    public string ConfirmPassword { get; set; }
}

Это имеет смысл, если модель регистрации расширяет пользователя.

person LukLed    schedule 15.07.2014
comment
Как правило, вы не хотите, чтобы ваши модели представления наследуют ваши модели сущностей. - person CodeCaster; 16.07.2014
comment
@CodeCaster: обычно я не хочу, чтобы мои модели представлений имели что-то общее с моделями сущностей, включая валидаторы, и все же мы здесь с вопросом, заданным Umair. Это решение его проблемы. Если бы это было сделано правильно, то не было бы этого вопроса на первом месте. - person LukLed; 16.07.2014
comment
Это одно из возможных решений, но оно также будет включать те проверки свойств, которые я не хочу отображать в представлении, и все равно будет проверяться и выдавать ошибку, даже если это не требуется, если только нет способа игнорировать эти ошибки проверки в плавная проверка. - person Umair; 16.07.2014

Хорошо, тогда на основе ваших комментариев и EF создайте для вас классы:

EF создаст частичные классы. Если они находятся в пространстве имен «MyProject.Core», просто добавьте в какое-то место следующий почти пустой класс и используйте то же пространство имен:

public partial class User : IUserModel
{
    /* nothing goes in here */
}

public interface IUserModel
{
   /*all common properties go here*/
}

[Обязательные] атрибуты и т. д. могут жить только в модели (представления), а не в интерфейсе.

Затем вам нужно настроить шаблон T4, чтобы использовать не «Пользователь», а «IUserModel».

person Eleasar    schedule 16.07.2014