title: Referencing an MVC model via WCF using DataAnnotations
body: <p>I am using WCF in ASP.Net 4.0 with EntityFramework 4.1 and MVC3 with Razor.</p>
  
  <p>The DataAnnotations work fine in the following scenario:</p>
  
  <p>Having the POCO class in another DLL with EF and then filling the model with a direct call from my presentation tier. If I try and edit an email address on the front end grid and purposely put in a bogus email, the DataAnnotation error <strong>appears</strong> for that property.</p>
  
  <p>However, if I use the approach with a <strong>WCF</strong> middle tier call (instead of a direct call), the data comes back and gets updated just fine except for the fact that <strong>the DataAnnotations don't work in this kind of scenario</strong>. If I try and edit an email address on the front end grid and purposely put in a bogus email, the DataAnnotation <strong>does not</strong> appear for that property.</p>
  
  <p><strong>How can I get it to work with using WCF? There must be some kind of WCF attribute I'm missing where it is not recognizing the DataAnnotations.</strong></p>
  
  <p>Below, is the pertinent code:</p>
  
  <p><strong>2 tier scenario:</strong></p>
  
  <p><strong>Model</strong></p>
  
  <pre><code> using System;
  using System.Collections.Generic;
  //using System.ServiceModel;
  //using System.Runtime.Serialization;
  using System.ComponentModel.DataAnnotations;
  using DataAnnotationsExtensions;
  
  namespace YeagerTechModel
  {
      public class Customer
      {
          public Customer()
          {
              this.Projects = new HashSet&lt;Project&gt;();
          }
  
  
          public short CustomerID { get; set; }
  
  
          [Required]
          [StringLength(50)]
          [DataType(DataType.EmailAddress)]
          [Email]
          public string Email { get; set; }
  
  
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string Company { get; set; }
  
  
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string FirstName { get; set; }
  
  
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string LastName { get; set; }
  
  
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string Address1 { get; set; }
  
  
          [StringLength(50)]
          [DataType(DataType.Text)]
          public string Address2 { get; set; }
  
  
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string City { get; set; }
  
  
          [StringLength(2, MinimumLength = 2, ErrorMessage = "Must have a length of 2.")]
          [DataType(DataType.Text)]
          public string State { get; set; }
  
  
          [StringLength(10)]
          [DataType(DataType.Text)]
          [RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Zip")]
          public string Zip { get; set; }
  
  
          [StringLength(12)]
          [DataType(DataType.PhoneNumber)]
          [RegularExpression(@"^\s*([\(]?)\[?\s*\d{3}\s*\]?[\)]?\s*[\-]?[\.]?\s*\d{3}\s*[\-]?[\.]?\s*\d{4}$", ErrorMessage = "Invalid Phone")]
          public string HomePhone { get; set; }
  
  
          [StringLength(12)]
          [DataType(DataType.PhoneNumber)]
          [RegularExpression(@"^\s*([\(]?)\[?\s*\d{3}\s*\]?[\)]?\s*[\-]?[\.]?\s*\d{3}\s*[\-]?[\.]?\s*\d{4}$", ErrorMessage = "Invalid Phone")]
          public string CellPhone { get; set; }
  
  
          [StringLength(100)]
          [DataType(DataType.Url)]
          [Url]
          public string Website { get; set; }
  
  
          [StringLength(50)]
          [DataType(DataType.EmailAddress)]
          [Email]
          public string IMAddress { get; set; }
  
  
          public System.DateTime CreatedDate { get; set; }
  
  
          public Nullable&lt;System.DateTime&gt; UpdatedDate { get; set; }
  
  
          public virtual ICollection&lt;Project&gt; Projects { get; set; }
      }
  } 
  </code></pre>
  
  <p><strong>Controller:</strong> </p>
  
  <pre><code>[GridAction]
          public ActionResult Index()
          {
              ViewData["ErrCode"] = string.Empty;
  
              if (HttpContext.User.IsInRole("Admin"))
              {
                  try
                  {
                      //IEnumerable&lt;YeagerTechWcfService.Customer&gt; customerList = db.GetCustomers();
  
                      //IEnumerable&lt;YeagerTechModel.Customer&gt; customerList = db.GetCustomers();
                      DbContext.Configuration.ProxyCreationEnabled = false;
                      IEnumerable&lt;Customer&gt; customerList = DbContext.Customers.Where(p =&gt; p.CustomerID &gt; 0);
  
                      if (DbContext.Database.Connection != null)
                      {
                          if (DbContext.Database.Connection.State != System.Data.ConnectionState.Closed)
                          {
                              DbContext.Database.Connection.Close();
                              DbContext.Database.Connection.Dispose();
                          }
                      }
  
                      return View(new GridModel&lt;YeagerTechModel.Customer&gt;
                      {
                          Data = customerList
  
                      });
                  }
                  catch (Exception ex)
                  {
                      throw ex;
                  }
              }
              else
              {
                  //HttpCookie cn = Request.Cookies["strCookieName"];
                  //if (cn != null)
                  //{
                  //    YeagerTechWcfService.Customer cust = db.GetCustomerID(Convert.ToInt16(cn.Value),false);
  
                  //    if (cust != null)
                  //    {
                  //        return View(new GridModel&lt;YeagerTechWcfService.Customer&gt;
                  //        {
                  //            //Data = cust
                  //        });
                  //    }
                  //    else
                  //        return View(new GridModel&lt;YeagerTechWcfService.Customer&gt;());
                  //}
                  //else
                  //{
                  //    TempData["ErrCode"] = "CustView";
                  return RedirectToAction("Index", "Home");
                  //}
              }
          }
  </code></pre>
  
  <p><strong>View:</strong> </p>
  
  <pre><code>@model Telerik.Web.Mvc.GridModel&lt;YeagerTechModel.Customer&gt;
  @{
      ViewBag.Title = "Customer Index";
  }
  &lt;h2&gt;
      Customer Index&lt;/h2&gt;
  @(  Html.Telerik().Grid&lt;YeagerTechModel.Customer&gt;(Model.Data)
        .Name("Customers")
              .DataKeys(dataKeys =&gt; dataKeys.Add(o =&gt; o.CustomerID)
                                              .RouteKey("CustomerID"))
                  .ToolBar(commands =&gt; commands.Insert().ButtonType(GridButtonType.Text).ImageHtmlAttributes(new { style = "margin-left:0" }))
        .Columns(columns =&gt;
              {
                  columns.Bound(o =&gt; o.CustomerID).Hidden(true);
                  columns.Command(commands =&gt;
                  {
                      commands.Edit().ButtonType(GridButtonType.Text);
                  }).Width(200).Title("Command");
                  columns.Bound(o =&gt; o.Email).Width(200).Filterable(false);
                  columns.Bound(o =&gt; o.Company).Width(200).Filterable(false);
                  columns.Bound(o =&gt; o.FirstName).Width(100).Title("FName").Filterable(false);
                  columns.Bound(o =&gt; o.LastName).Width(100).Title("LName").Filterable(false);
                  columns.Bound(o =&gt; o.Address1).Width(200).Title("Addr1").Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.Address2).Width(100).Title("Addr2").Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.City).Width(100);
                  columns.Bound(o =&gt; o.State).Width(40).Title("ST");
                  columns.Bound(o =&gt; o.Zip).Width(60);
                  columns.Bound(o =&gt; o.HomePhone).Width(120).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.CellPhone).Width(120).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.Website).Width(100).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.IMAddress).Width(100).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.CreatedDate).Format("{0:MM/dd/yyyy}").ReadOnly(true).Width(120).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.UpdatedDate).Format("{0:MM/dd/yyyy}").ReadOnly(true).Width(120).Filterable(false).Sortable(false);
              }).DataBinding(dataBinding =&gt;
                  dataBinding.Ajax()
                          .Insert("_InsertAjaxEditing", "Customer")
                          .Update("_SaveAjaxEditing", "Customer"))
      .Editable(editing =&gt; editing.Mode(GridEditMode.InLine))
      .Pageable()
      .Sortable()
      .Filterable()
      .Scrollable()
   )
  </code></pre>
  
  <p><strong>NTier scenario 
  Model:</strong> </p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ServiceModel;
  using System.Runtime.Serialization;
  using System.ComponentModel.DataAnnotations;
  using DataAnnotationsExtensions;
  
  namespace YeagerTechModel
  {
      [Serializable]
      [DataContract(IsReference = true)]
      public class Customer
      {
          public Customer()
          {
              this.Projects = new HashSet&lt;Project&gt;();
          }
  
          [DataMember]
          public short CustomerID { get; set; }
  
          [DataMember]
          [Required]
          [StringLength(50)]
          [DataType(DataType.EmailAddress)]
          [Email]
          public string Email { get; set; }
  
          [DataMember]
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string Company { get; set; }
  
          [DataMember]
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string FirstName { get; set; }
  
          [DataMember]
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string LastName { get; set; }
  
          [DataMember]
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string Address1 { get; set; }
  
          [DataMember]
          [StringLength(50)]
          [DataType(DataType.Text)]
          public string Address2 { get; set; }
  
          [DataMember]
          [StringLength(50, MinimumLength = 3, ErrorMessage = "Must have a minimum length of 3.")]
          [DataType(DataType.Text)]
          public string City { get; set; }
  
          [DataMember]
          [StringLength(2, MinimumLength = 2, ErrorMessage = "Must have a length of 2.")]
          [DataType(DataType.Text)]
          public string State { get; set; }
  
          [DataMember]
          [StringLength(10)]
          [DataType(DataType.Text)]
          [RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Zip")]
          public string Zip { get; set; }
  
          [DataMember]
          [StringLength(12)]
          [DataType(DataType.PhoneNumber)]
          [RegularExpression(@"^\s*([\(]?)\[?\s*\d{3}\s*\]?[\)]?\s*[\-]?[\.]?\s*\d{3}\s*[\-]?[\.]?\s*\d{4}$", ErrorMessage = "Invalid Phone")]
          public string HomePhone { get; set; }
  
          [DataMember]
          [StringLength(12)]
          [DataType(DataType.PhoneNumber)]
          [RegularExpression(@"^\s*([\(]?)\[?\s*\d{3}\s*\]?[\)]?\s*[\-]?[\.]?\s*\d{3}\s*[\-]?[\.]?\s*\d{4}$", ErrorMessage = "Invalid Phone")]
          public string CellPhone { get; set; }
  
          [DataMember]
          [StringLength(100)]
          [DataType(DataType.Url)]
          [Url]
          public string Website { get; set; }
  
          [DataMember]
          [StringLength(50)]
          [DataType(DataType.EmailAddress)]
          [Email]
          public string IMAddress { get; set; }
  
          [DataMember]
          public System.DateTime CreatedDate { get; set; }
  
          [DataMember]
          public Nullable&lt;System.DateTime&gt; UpdatedDate { get; set; }
  
          [DataMember]
          public virtual ICollection&lt;Project&gt; Projects { get; set; }
      }
  }
  </code></pre>
  
  <p><strong>WCF Call:</strong> </p>
  
  <pre><code>public IEnumerable&lt;Customer&gt; GetCustomers()
          {
              YeagerTechEntities DbContext = new YeagerTechEntities();
  
              DbContext.Configuration.ProxyCreationEnabled = false;
  
              IQueryable&lt;Customer&gt; customer = DbContext.Customers.Where(p =&gt; p.CustomerID &gt; 0);
  
              CloseConnection(DbContext);
  
              return customer;
          }
  </code></pre>
  
  <p><strong>Controller:</strong> </p>
  
  <pre><code>[GridAction]
          public ActionResult Index()
          {
              ViewData["ErrCode"] = string.Empty;
  
              if (HttpContext.User.IsInRole("Admin"))
              {
                  try
                  {
                      IEnumerable&lt;YeagerTechWcfService.Customer&gt; customerList = db.GetCustomers();
  
                      return View(new GridModel&lt;YeagerTechWcfService.Customer&gt;
                      {
                          Data = customerList
                      });
                  }
                  catch (Exception ex)
                  {
                      throw ex;
                  }
              }
              else
              {
                  return RedirectToAction("Index", "Home");
              }
          }
  </code></pre>
  
  <p><strong>View:</strong> </p>
  
  <pre><code>@model Telerik.Web.Mvc.GridModel&lt;YeagerTech.YeagerTechWcfService.Customer&gt;
  @{
      ViewBag.Title = "Customer Index";
  }
  &lt;h2&gt;
      Customer Index&lt;/h2&gt;
  @(  Html.Telerik().Grid&lt;YeagerTech.YeagerTechWcfService.Customer&gt;(Model.Data)
        .Name("Customers")
              .DataKeys(dataKeys =&gt; dataKeys.Add(o =&gt; o.CustomerID)
                                              .RouteKey("CustomerID"))
                  .ToolBar(commands =&gt; commands.Insert().ButtonType(GridButtonType.Text).ImageHtmlAttributes(new { style = "margin-left:0" }))
        .Columns(columns =&gt;
              {
                  columns.Bound(o =&gt; o.CustomerID).Hidden(true);
                  columns.Command(commands =&gt;
                  {
                      commands.Edit().ButtonType(GridButtonType.Text);
                  }).Width(200).Title("Command");
                  columns.Bound(o =&gt; o.Email).Width(200).Filterable(false);
                  columns.Bound(o =&gt; o.Company).Width(200).Filterable(false);
                  columns.Bound(o =&gt; o.FirstName).Width(100).Title("FName").Filterable(false);
                  columns.Bound(o =&gt; o.LastName).Width(100).Title("LName").Filterable(false);
                  columns.Bound(o =&gt; o.Address1).Width(200).Title("Addr1").Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.Address2).Width(100).Title("Addr2").Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.City).Width(100);
                  columns.Bound(o =&gt; o.State).Width(40).Title("ST");
                  columns.Bound(o =&gt; o.Zip).Width(60);
                  columns.Bound(o =&gt; o.HomePhone).Width(120).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.CellPhone).Width(120).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.Website).Width(100).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.IMAddress).Width(100).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.CreatedDate).Format("{0:MM/dd/yyyy}").ReadOnly(true).Width(120).Filterable(false).Sortable(false);
                  columns.Bound(o =&gt; o.UpdatedDate).Format("{0:MM/dd/yyyy}").ReadOnly(true).Width(120).Filterable(false).Sortable(false);
              }).DataBinding(dataBinding =&gt;
                  dataBinding.Ajax()
                          .Insert("_InsertAjaxEditing", "Customer")
                          .Update("_SaveAjaxEditing", "Customer"))
      .Editable(editing =&gt; editing.Mode(GridEditMode.InLine))
      .Pageable()
      .Sortable()
      .Filterable()
      .Scrollable()
   )
  </code></pre>