views:

87

answers:

3

I would like to use DataAnnotations for basic client and server-side validation of my MVC ViewModels. My ViewModel looks like this:

public class MyViewModel
{
    public Client Client1 { get; set; }
    public Client Client2 { get; set; }
    public Product Product { get; set; }
}

So I would like to check that both client objects have a name and telephone number, the product object has a valid numeric price, etc.

The problem I have is that both Client and Product are proxy types generated by Visual Studio from a web service, so I can't directly add the annotation attributes to their required properties.

I've read about using the MetadataType attribute to specify the meta data in an alternative class (with duplicate properties), but in this case I can't even add that attribute to the Client and Product classes.

Or can I? In the Web References folder where my VS solution is saved, there is a folder for the web service namespace containing a file called Reference.cs, which contains the VS generated code for the proxy types.

If I add the metadata to the classes in here, will this work—or is messing about with the generated code a really bad idea? Or is there just a simpler, cleaner way to do this?

A: 

Modifying the generated code would work, so long as you don't regenerate it and write over your modifications. Other than the chance of losing your work if someone generates the reference, there isn't a reason you can't add the metadata references to the proxy classes.

The other alternative is using custom validation, or create a model that you then map the fields to the proxy objects. Creating a model that isn't based on the Client object would be your safest method.

Benjamin Anderson
A: 

I think it would be cleaner to create a model and then map the fields using AutoMapper and/or Model Generator Helper ( http://modelhelper.codeplex.com/ ).

Juan Tarquino
A: 

After a bit of hunting I found that this is actually remarkably simple—it was just a case of my not knowing exactly what to search for!

You don't actually need to add the MetadataType attribute to the original class definition: you can add it to an empty partial class of the same type (make sure your partial class is in the same namespace as the original type).

Then you just create a "buddy" class containing your validation rules as you would normally:

using System.ComponentModel.DataAnnotations;

namespace WebServiceNamespace
{
    [MetadataType(typeof(ClientMetaData))]
    public partial class Client
    {
    }

    public class ClientMetaData
    {
        [Required(ErrorMessage = "Please enter a name")]
        public string Name { get; set; }

        [Required(ErrorMessage="Please enter a telephone Number")]
        public string Telephone { get; set; }
    }
}

This works perfectly with the standard Model Binding and requires no access to the original code for the type, so you can easily set up validation rules with DataAnnotations, even for types which aren't part of your code base.

Mark B