Question How to prepare ViewModel for tables from EF when I work with Mata Data Library project?

Elad

Member
Joined
Feb 15, 2020
Messages
20
Programming Experience
1-3
Hello
I have a problem that I build in a separate project classes that EF creates for me from a SQL server, with two or more tables and I add the refernce to an MVC project so the way Contrlloer knows to associate the object of the table -when the user enters values let's put in boxes Text in a particular view and the form returned to Action using HttpPost- should be defined in a model model named after the class itself (which the EF created in the separate project) as prtial and set in square brackets [MetadataType (typeof on that class)].
The point I want Action that captures the content that the user enters will contain fields that do not actually exist in a particular table on which I define MetadataType. Although in the following code you can see that I define data anontion on specific fields that fit another table.
My question is how do I know to build in such a ViewModel mode when there is
MetadataType?


C#:
//Library project
//With the classes EF created for
namespace MaterialLibrary.Models
{
    using System;
    using System.Collections.Generic;

    public partial class tbUser
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2994:DoNotCallOverridableMethodsInConstructors")]
        public tbUser()
        {
            this.tbVolunteerInfoes = new HashSet<tbVolunteerInfo>();
        }

        public int Id { get; set; }
        public string strFirstName { get; set; }
        public string strLastName { get; set; }
        public string strEmail { get; set; }
        public string strPassword { get; set; }
        public int Age { get; set; }
        public System.DateTime Date_Registration { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2707:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tbVolunteerInfo> tbVolunteerInfoes { get; set; }
    }
}
//Table 2 which EF Carting
   public partial class tbVolunteerInfo
    {
        public int Id { get; set; }
        public bool Mode_Active { get; set; }
        public int HowDaysActivities { get; set; }
        public int Day { get; set; }
        public virtual tbUser tbUser { get; set; }
}
    }
}


//Now
//I will show the MataData model in MVC in-model

namespace VolMVC4.MaterialLibrary
{
    [MetadataType(typeof(tbVolunteerInfoMetaData))]
    public partial class tbVolunteerInfo
    {
    }
    public class tbVolunteerInfoMetaData
    {
   
        [Required(ErrorMessage = "required fname")]
        [Display(Name = "first name")]
        public string strFirstName { get; set; }

        [Required(ErrorMessage = "required lname")]
        [Display(Name = "Last Name")]
        public string strLastName { get; set; }
        [Required(ErrorMessage = "required city")]
        [Display(Name = "City")]
        public string strCity { get; set; }
        [Required(ErrorMessage = "required address")]
        [Display(Name = "Address")]
        //Such a field does not exist in the original table  tbVolunteerInfo but in another table
        public string strAddress { get; set; }
        [Required(ErrorMessage = "required phone")]
        [Display(Name = "Phone")]
        [DataType(DataType.PhoneNumber)]
        [RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Invalid phone")]
        //Also the field it does not originally exist
        public string strPhone { get; set; }

        [Required(ErrorMessage = "required Email")]
        [RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "Invalid Email")]
        [Display(Name = "Email")]
        public string strEmail { get; set; }
        [Required]
        [StringLength(18, ErrorMessage = "password between {0}  and {2}", MinimumLength = 6)]
        //[RegularExpression(@"^((?=.*[a-z])(?=.*[A-Z])(?=.*\d)).+$")]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { set; get; }

        public System.DateTime DateRegistration { get; set; }

        [Required(ErrorMessage = "required Age)]
        [Display(Name = "Age")]
        [Range(19, 44, ErrorMessage = "Age must between 19 and 42")]
        public int Age { get; set; }
    

    }

}

//And Contrlloer

namespace VolMVC4.Controllers
{
    public class HomeController : Controller
    {
   
        public ActionResult SignUp()
        {
            string[] names;
            ViewBag.CountryList = new SelectList(new int[] { 1, 2, 3, 4, 5 });
            using (MaterialDbEntities MatDb = new MaterialDbEntities())
            {
                var qusCities = from s in MatDb.tbCities select s.strCity;
                names = qusCities.ToArray();
            }
            Array.Sort(names);
            ViewBag.CitiesList = new SelectList(names);
        }
        [HttpPost]
       //Here I want to get more fields that do not actually exist in the tbVolunteerInfo table
        public ActionResult SignUp(tbVolunteerInfo tb)
        {
        
            if (ModelState.IsValid)
            {
                using (MaterialDbEntities MatDb = new MaterialDbEntities())
                {

                        MatDb.tbVolunteers.Add(tb);
                        MatDb.SaveChanges();
              
                }
         
          }

            return View();
        }
    
    }
}
//And View SignUp
@model VolunteesMVC4.MaterialLibrary.tbVolunteerInfoMetaData

@{
    ViewBag.Title = "SignUp";
}

<h2>SignUp</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>tbVolunteerInfoMetaData</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    

    <div class="form-group">
        @Html.LabelFor(model => model.strFirstName, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.strFirstName, new { htmlAttributes = new { @class = "form-control", placeholder = "First Name" } })
            @Html.ValidationMessageFor(model => model.strFirstName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.strLastName, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.strLastName, new { htmlAttributes = new { @class = "form-control", placeholder = "Last Name" } })
            @Html.ValidationMessageFor(model => model.strLastName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.strCity, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.DropDownListFor(m => m.strCity, (SelectList)ViewBag.CitiesList, "select city", new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.strCity, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.strAddress, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.strAddress, new { htmlAttributes = new { @class = "form-control", placeholder = "Address" } })
            @Html.ValidationMessageFor(model => model.strAddress, "", new { @class = "text-danger" })
        </div>
    </div>


    <div class="form-group">
        @Html.LabelFor(model => model.strPhone, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.strPhone, new { htmlAttributes = new { @class = "form-control", placeholder = "Phone" } })
            @Html.ValidationMessageFor(model => model.strPhone, "", new { @class = "text-danger" })
        </div>
    </div>



    <div class="form-group">
        @Html.LabelFor(model => model.strEmail, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.strEmail, new { htmlAttributes = new { @class = "form-control", placeholder = "Email" } })
            @Html.ValidationMessageFor(model => model.strEmail, "", new { @class = "text-danger" })
        </div>
    </div>



    <div class="form-group">
        @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control", placeholder = "Insert password" } })
            @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
        </div>
    </div>



    <div class="form-group">
        @Html.LabelFor(model => model.HowDaysActivities, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.DropDownListFor(m => m.HowDaysActivities, (SelectList)ViewBag.CountryList, "Select in list", new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.HowDaysActivities, "", new { @class = "text-danger" })
        </div>
    </div>



    <div class="form-group">
        @Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md" })
        <div class="col-md-15">
            @Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control", placeholder = "Age" } })
            @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
 
Last edited:
Personally, I run as fast and as far away as I can from Entity Framework as I can due to its quirks and bugs. Yes EF 6 and higher is much better than the abomination that was EF 1.0 and EF 2.0, but it's still an odd beast. I think you also just made things even harder for yourself by choosing Database First EF rather than Code First EF. Hopefully someone else can jump in on this thread and offer some help. Good luck!

The thing to keep in mind is that the purpose of a view model is to provide an facade for the view and controller to talk to the actual data model. Recall that the Facade design pattern's main purpose is to making things easier to work with -- it will take care of hiding some complexity behind it's external facing interface. So instead of just living with the EF generated classes, you can create your own view model that provides the interface that your view needs and functionality that view and/or controller needs.
 
I think I found a solution,
It's a simple set-in action that is returned via Post that will get the climb
tbVolunteerInfoMetaData and how much I kept all the fields.
So that was a maybe stupid question, but the question is whether this is actually the right way to do things?
C#:
        [HttpPost]
       //Here I want to get more fields that do not actually exist in the tbVolunteerInfo table
        public ActionResult SignUp(tbVolunteerInfoMetaData tb)
        {
       
            if (ModelState.IsValid)
            {
                using (MaterialDbEntities MatDb = new MaterialDbEntities())
                {

                        MatDb.tbVolunteers.Add(tb);
                        MatDb.SaveChanges();
             
                }
       
          }

            return View();
        }
 
Last edited by a moderator:
Personally, I run as fast and as far away as I can from Entity Framework as I can due to its quirks and bugs. Yes EF 6 and higher is much better than the abomination that was EF 1.0 and EF 2.0, but it's still an odd beast. I think you also just made things even harder for yourself by choosing Database First EF rather than Code First EF. Hopefully someone else can jump in on this thread and offer some help. Good luck!

The thing to keep in mind is that the purpose of a view model is to provide an facade for the view and controller to talk to the actual data model. Recall that the Facade design pattern's main purpose is to making things easier to work with -- it will take care of hiding some complexity behind it's external facing interface. So instead of just living with the EF generated classes, you can create your own view model that provides the interface that your view needs and functionality that view and/or controller needs.

I think I found a solution, It's a simple set-in action that is returned via Post that will get the climb tbVolunteerInfoMetaData and how much I kept all the fields. So that was a maybe stupid question, but the question is whether this is actually the right way to do things? Even though you said yourself that you are not using EF:
 [HttpPost]

       //Here I want to get more fields that do not actually exist in the tbVolunteerInfo table

        public ActionResult SignUp(tbVolunteerInfoMetaData tb)

        {

        

            if (ModelState.IsValid)

            {

                using (MaterialDbEntities MatDb = new MaterialDbEntities())

                {



                        MatDb.tbVolunteers.Add(tb);

                        MatDb.SaveChanges();

              

                }

        

          }



            return View();

        }
 
Please do not delete posts without a valid reason for doing so.

If you have a problem with how you wrote your post, then edit it instead.
 
Back
Top Bottom