Umair
Umair

Reputation: 5481

MVC validation of with a different ViewModel

I have written a T4 template which automatically generates all the validations like this:

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();
    }
}

Now I have a ViewModel where I want to use these validations as such:

[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; }
}

My class is different from the one used in AbstractValidator, I have a RegisterModel class.

When I run I get the following error:

Unable to cast object of type 'Web.Models.RegisterModel' to type 'DAL.User'.

...which makes sense as its not the same type.

I also tried using this way:

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; }
}

But can not use in this was as validator is a class level attribute and not property attribute.

Is there any way I can use existing Rules generated for my entity classes in the models?

Anyone tried something similar? Or have any other ideas of this?

Upvotes: 1

Views: 523

Answers (2)

Eleasar
Eleasar

Reputation: 536

Ok - then based on your comments and EF creating the classes for you:

EF will create partial classes. If those live in the namespace "MyProject.Core" simply add the following almost empty class at some place and use the same namespace:

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

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

The [Required] attributes etc. can only live on the (View) Model and not on the interface.

Then you have to adjust your T4 template to not use "User" but "IUserModel"

Upvotes: 1

LukLed
LukLed

Reputation: 31842

Obviously one of the solutions would be to inherit from User class:

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

This makes sense if registration model extends user.

Upvotes: 1

Related Questions