0

I'm trying to implement Client-Side validation to my DB First project in Entity Framework 5.

I noticed this question and I've seen various other links that describe this MetaDataType attribute. However, I'm not 100% sure how to set this up.

I see under my .edmx all of the partial classes that get setup that match the table names and the columns in the table.

namespace Professional.DAL
{
    using System;
    using System.Collections.Generic;

    public partial class LeaderList
    {
        public LeaderList()
        {
            this.Answers = new HashSet<Answer>();
        }

        public int LeaderKey { get; set; }
        public string ID { get; set; }
        public string AccountName { get; set; }
        public long SchoolKey { get; set; }
        public Nullable<int> SchoolYear { get; set; }

        public virtual School School { get; set; }
        public virtual ICollection<Answer> Answers { get; set; }
    }
}

The part I need clarification on is do I create another partial class with the same name in my Models folder (for example) that has this MetaDataType attribute:

[MetadataType(typeof(LeaderList.Metadata))]
public partial class LeaderList
{
    private sealed class LeaderList
    {
        [Required(ErrorMessage = "* required")]
        public string ID { get; set; }
        [Required(ErrorMessage = "* required")]
        public string AccountName { get; set; }
        [Required(ErrorMessage = "* required")]
        public Nullable<int> SchoolYear { get; set; }
        [Required(ErrorMessage = "* required")]
        public virtual School School { get; set; }
        [Required(ErrorMessage = "* required")]
        public virtual ICollection<Answer> Answers { get; set; }
    }

    // Add other similar properties here...
}

Is that what I'm supposed to do? I'm trying to understand this so I can implement it in my next project (as my current project I only did server side validation).

Any links or books for further research is welcomed and appreciated.

Community
  • 1
  • 1
webdad3
  • 8,893
  • 30
  • 121
  • 223
  • That's it. You don't need the required attribute on the collection though. That will be added automatically by the model binder if any Answers are returned by the view. – Max Feb 26 '14 at 16:03

1 Answers1

1

You need to add a metadata class for each of your entity types and a partial class upon which to place the attribute. eg:

public class Employee
{
    [Required(ErrorMessage = "* required")]
    public int Id { get; set; }

    [Required(ErrorMessage = "* required")]
    public string EmployeeString { get; set; }
    ...
}

[MetadataType(typeof(EmployeeEntitiesMetadata))]
public partial class Employee
{
}

This then allows you to set up client validation using html helpers:

@Html.EditorFor(model => model.EmployeeString)

(for Razor)

This will then set up validation using the unobtrusive JavaScript library bundled with MVC. If you look at the generated html you can see that it works with 'data-val' attributes.

Max
  • 721
  • 5
  • 8
  • what goes in the partial class Employee? Also how do I wire all of these new metadata classes so my view can do the validation with them? – webdad3 Feb 26 '14 at 15:36
  • Nothing needs to go on the employee class. It is just to hold the attribute. You then match the properties on the metadata class to those on the original generated employee class. – Max Feb 26 '14 at 15:43
  • Thanks for the response. But what if I have a view model that contains multiple entities? – webdad3 Feb 26 '14 at 15:50
  • Personally I don't like this approach as I find it leads to tight coupling between the database and the viewmodel. I would recommend keeping your view model unrelated to your entities and mapping exactly the data you need for the view model. Then you can (if you choose this method for client side validation) add the validation attributes directly to the view model. I also find that this makes it easier to create more efficient linq queries (but that is a separate issue). – Max Feb 26 '14 at 15:55