Question

This seems like a simple one but I have a feeling that the Framework won't let me do what I want it to do.

Let's say I have 3 pages - one that asks for firstname/lastname, one that asks for phone number, and one that lets you edit both:

public class NameModel
{
public string FName {get;set;}
public string LName {get;set;}
}

public class PhoneModel 
{
public string Phone { get; set;}
}

public string NamePhoneModel
{
public string FName {get;set;}
public string LName {get;set;}
public string Phone {get;set;}
}

How I'm validating these models at the moment is that i have two interfaces INameModel and IPhoneModel which have all the validation attributes. I use [MetadataType(typeof(INameModel))] on NameModel and [MetadataType(typeof(IPhoneModel))] on PhoneModel.

What I really want to do is use both interfaces on NamePhoneModel so I don't have to re-type all the validation attributes. Keep in mind this is a simple solution, the real-world project is a lot more complicated than this - in the example above it would be simple to inherit, but think about that there might be additional properties on NameModel that won't exist in NamePhoneModel, or to get more complicated, there might be a property for Email that exists in NameModel and another page, say EmailModel

It doesn't feel like the right way to simply have to duplicate all those rules - there must be a better/proper way??

Was it helpful?

Solution 2

So the solution I had to go with was creating classes within my classes:

public string NamePhoneModel : IValidationObject
{
    [MetadataType(typeof(INameModel))]
    public class NM : INameModel
    {
        public string FName {get;set;}
        public string LName {get;set;}
    }
    [MetadataType(typeof(IPhoneModel))]
    public class PM : IPhoneModel
    {
        public string Phone {get;set;}    
    }
    public NM N { get; set; }
    public PM P { get; set; }
    public NamePhoneModel()
    {
        this.N = new NM();
        this.P = new PM();
    }
}

OTHER TIPS

Set them up as types that your models use, or create you can create a generic ViewModel that you reuse, and just throw away any unused property validation errors in the appropriate actions. Setting them up as types:

public class Name
{
    public string First {get;set;}
    public string Last {get;set;}
}

public class Phone
{
    public string Number { get; set;}
}

public class NamePhoneModel
{
    public Name Name {get;set;}
    public Phone Phone {get;set;}
}
public class PhoneModel
{
    public Phone Phone {get;set;}
}
public class NameModel
{
    public Name Name {get;set;}
}

Generic ViewModel:

public class ViewModel
{
    public string First {get;set;}
    public string Last {get;set;}
    public string Phone {get;set;}

}

[HttpPost]
public ActionResult EditPhone(ViewModel model)
{
    ModelState["First"].Errors.Clear();
    ModelState["Last"].Errors.Clear();
    if (ModelState.IsValid)
    {
        // Validate Phone
    }
}

[HttpPost]
public ActionResult EditName(ViewModel model)
{
    ModelState["Phone"].Errors.Clear();
    if (ModelState.IsValid)
    {
        // Validate Names
    }
}

[HttpPost]
public ActionResult EditBoth(ViewModel model)
{
    if (ModelState.IsValid)
    {
        // Validate All
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top