1

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?

2
  • 1
    What do you want to achieve? If you want to reuse the UserValidator class then i would suggest you do not expect a "User" class as the generic type but IUser interface that defines the properties that are common to both. As it looks like the real user has more/different properties (e.g. UserRoleId) those you could add to either another interface and in the validator check for those other interfaces and execute custom validation for e.g. user role id. Commented Jul 15, 2014 at 22:04
  • I want to use the same validators for the model class, without re-writing them, and if possible, would be good if I can give any additional attributes also to its properties. Most of them will be common, but yes the UserRoleId will not be specified in the view, hence it will be displayed an error which I don't want to. Cant really go with interfaces or change the entity class as its generated by EF. Commented Jul 16, 2014 at 18:15

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

You generally do not want to let your view models inherit your entity models.
@CodeCaster: I generally do not want my view models have anything in common with entity models, including validators, and still we are here with question asked by Umair. This is solution to his problem. If it was done properly, there wouldn't be this question in first place.
This is one possible solution, but it will also include those property validations which I don't want to display in the view, and still will be validated and throw error even if not required, unless there is a way to ignore those validation errors in fluentvalidation.
1

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"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.