locked
DataAnnotations with EntityFramework (Database First) method not working RRS feed

  • Question


  • Decker, I've modified the code in my model (which is on a separate tier) with metadata hoping this will resolve the issue, but it didn't. It's as if the DataAnnotations from the model are not being picked up? Why???

    When viewing the page source, I should be seeing something like the following:

    data-val-required="The User name field is required."

    However, all I see is the fiollowing:

    <div class="editor-label">
      <label for="Email">Email</label>
      </div>
      <div class="editor-field">
      <input id="Email" name="Email" type="text" value="" />
      <span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>
      </div>

     

    When looking at the model for standard account log in, I have the following:

    YeagerTech.Models.LogOnModel
    

     

    The above is defined in the following Models folder on the root of the website inside the AccountModels.cs file:

        public class LogOnModel
        {
            [Required]
            [Display(Name = "User name")]
            public string UserName { get; set; }
     
            [Required]
            [DataType(DataType.Password)]
            [Display(Name = "Password")]
            public string Password { get; set; }
     
            [Display(Name = "Remember me?")]
            public bool RememberMe { get; set; }
        }
    
    The above (while the model is on the website front end and not in another tier) works fine and has the required attributes set up in the page source fine.
    What do I need to do to in order to perform data validation with the EF DataBaseFirst method where my model resides on another tier?

    My web.config file is set up as follows:

    <appSettings>
        <add key="ClientValidationEnabled" value="true" />
        <add key="UnobtrusiveJavaScriptEnabled" value="true" />
      </appSettings>
    

    On the front-end, I have my view set up as follows:

    @model YeagerTech.YeagerTechWcfService.Customer
     
    @{
        ViewBag.Title = "Create Customer";
    }
     
    <h2>Create</h2>
     
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
     
    @using (Ajax.BeginForm("Create", "Customer", new AjaxOptions { HttpMethod = "POST"}))
    {
        @Html.ValidationSummary(true, "Create was unsuccessful. Please correct the errors and try again.") 
        <fieldset>
            <legend>Customer</legend>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Email)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Email)
                @Html.ValidationMessageFor(model => model.Email)
            </div>
    

    The definition for YeagerTech.YeagerTechWcfService.Customer is set up as follows (inside the Reference.cs file)

    [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] [System.Runtime.Serialization.DataContractAttribute(Name="Customer", Namespace="http://schemas.datacontract.org/2004/07/YeagerTechModel")] [System.SerializableAttribute()] public partial class Customer : YeagerTech.YeagerTechWcfService.CustomerDA { }

    My model is setup as follows inside the above service:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.ServiceModel;
    using System.Runtime.Serialization;
     
    namespace YeagerTechModel
    {
        [Serializable]
        [DataContract]
        [MetadataType(typeof(CustomerDA))]
        public partial class Customer : CustomerDA
        {
            public Customer()
            {
                this.Projects = new HashSet<Project>();
            }
        }
     
        [Serializable]
        [DataContract]
        public class CustomerDA 
        {  
            [DataMember]
            public short CustomerID { get; set; }
     
            [Required]
            [StringLength(50)]
            [DataType(DataType.EmailAddress)]
            [DataMember]
            public string Email { get; set; }
    

     

    Base DbContext class

    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
     
    namespace YeagerTechModel
    {
        public partial class YeagerTechEntities : DbContext
        {
            public YeagerTechEntities()
                : base("name=YeagerTechEntities")
            {
            }
     
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                throw new UnintentionalCodeFirstException();
            }
     
            public DbSet<Customer> Customers { get; set; }
        }
    }
    • Edited by Bill_Yeager Friday, September 9, 2011 7:02 PM submittal
    Friday, September 9, 2011 7:01 PM

Answers

  • Hi Bill,

    Sorry for my careless and wrong directions. I'm new to MVC and after doing some research, DataAnnotations supports DatabaseFirst method. I try to repro your scenario, unfortunately I could not as I'm not good at it.

    1. I  add an entity(Employees) into my MVC project by EF .edmx Wizard.

    2. Add a partial class Employees:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;
    
    namespace MVCValidation.Models
    {
        [MetadataType(typeof(Employees_Validate))]
        public partial class Employees
        {
        }
        public class Employees_Validate
        {
            [StringLength(2,ErrorMessage="Must be under 50")]
            [Required(ErrorMessage="Name is request")]
            public string Name { get; set; }
        }
    }
    

    3. I add Controller for the typed Employees and related Views:

    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Employees</legend>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
    
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }
    

    It works on my computer.
    Based on your post, I found there is WCFService, I'm not sure about that, thanks for understanding.

    BTW, I followed this link: Model Validation, would you please feel free to send a demo project to me: Alan

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Bill_Yeager Sunday, September 25, 2011 12:55 AM
    Wednesday, September 21, 2011 9:48 AM

All replies

  • Hi Bill,

    Welcome!

    To tell you truth, I'm not good at MVC, But I found a blog here: EF4.1 Validation. Thanks for understanding.

    --------------

    The validation doesn’t automatically get passed back into the view which is why the additional code that uses ModelState.AddModelError is being used. This ensures that the error details make it to the view which will then use the ValidationMessageFor Htmlhelper to display the error.

    --------------

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, September 12, 2011 8:33 AM
  • That link is only for CodeFirst database creation.

    I need to know how to do it for DataBaseFirst methodology.


    Bill Yeager
    Monday, September 12, 2011 8:40 PM
  • Hi Bill,

    -------------------------------

    If you have an existing database then you don’t need database location or initialization. Here is the process to follow for using Code First against an existing database:

    1. Define the classes that make up you domain model
    2. Define a derived DbContext and use the Fluent API and/or DataAnnotations to tell Code First how your classes map to your database
    3. Add a connection string to you app/web.config file that has the same name as your derived context and points to your database
    4. Switch off the initialization functionality for your context by registering null:
          Database.SetInitializer<ProductCatalog>(null);

    -------------------------------

     Working with Existing Databases code first

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, September 15, 2011 8:04 AM
  • Hi,

    I am writing to check the status of the issue on your side. Would you mind letting us know the result of the suggestions?

    If you need further assistance, please feel free to let me know. I will be more than happy to be of assistance.

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, September 19, 2011 7:41 AM
  • I have not received an answer yet how to do DataAnnotations with EntityFramework using the DatabaseFirst method.

    This is a straight forward question which should require a straight forward answer provided by Microsoft and the Entity Framework team.

    I am at the point now where I am at the end of my rope and extremely frustrated that I can't find a simple answer to this simple question.


    Bill Yeager
    Monday, September 19, 2011 4:41 PM
  • Hi Bill,

    Sorry for my careless and wrong directions. I'm new to MVC and after doing some research, DataAnnotations supports DatabaseFirst method. I try to repro your scenario, unfortunately I could not as I'm not good at it.

    1. I  add an entity(Employees) into my MVC project by EF .edmx Wizard.

    2. Add a partial class Employees:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;
    
    namespace MVCValidation.Models
    {
        [MetadataType(typeof(Employees_Validate))]
        public partial class Employees
        {
        }
        public class Employees_Validate
        {
            [StringLength(2,ErrorMessage="Must be under 50")]
            [Required(ErrorMessage="Name is request")]
            public string Name { get; set; }
        }
    }
    

    3. I add Controller for the typed Employees and related Views:

    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Employees</legend>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
    
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }
    

    It works on my computer.
    Based on your post, I found there is WCFService, I'm not sure about that, thanks for understanding.

    BTW, I followed this link: Model Validation, would you please feel free to send a demo project to me: Alan

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Bill_Yeager Sunday, September 25, 2011 12:55 AM
    Wednesday, September 21, 2011 9:48 AM
  • Hello Bill.

    You have a strongly typed View. 

    @model YeagerTech.YeagerTechWcfService.Customer

    The type of the Model is

    YeagerTech.YeagerTechWcfService.Customer

     

    But DataAnnotation attributes are applied to the class

    YeagerTechModel.Customer

     

    Perhaps this is the cause of the issue.

     

    Regards

    Wednesday, September 21, 2011 10:13 AM
  • Thanks....

    This is what I was more or less looking for. However, it doesn't work if you are using a data model class in an N-tiered environment. If you have your model class on the presnetation layer, it will work as advertised.

    What I have is a Customer object in my WCF service which is in a Data Contract. I was trying to implement the DataAnnotations with this class, but it doesn't work with N-Tier.

    So, what I did was implement a DataAnnotations model on the presentation layer and if it passes, I place the data in my WCF Customer object to pass to my WCF service.


    Bill Yeager
    Sunday, September 25, 2011 12:55 AM
  • Hi Bill,

    I am in the same boat as you. I have the seperate DAL ( Data Access Layer) and PL ( Presentation Layer). In my DAL, I created the EDMX with existing database and created MVC UI using the Entity Models of DAL in PL. Now I am also wondering what would be the best way of doing validation. I do not want  to create seperate Metadata partial class, as it is gonna be as good as writing the model class again.

    Did you figure out the solution for this?

    Thanks

    NS

    Saturday, December 3, 2011 5:49 AM
  • Saturday, December 3, 2011 6:03 PM