ASP.NET MVC,ORM and ViewModels

Since I am active on asp.net/mvc I find many peoples asking about

  1. One to many relationship .
  2. Dropdownlist
  3. How to use MVC with other ORM frameworks instead of Linq To Sql(L2S) ?
  4. What is a ViewModel and what is his purpose ?

For answering,I have made a small application with MVC2 in order to detail my answer.

First the problem :

You have Employees and Department.Each Employee belongs to an Department (let’s forget the fact that the employee can belong for a final date to the Department or any other life ideas)

The request is to create and view Employees .(forget delete,update – if I will have time and/or by general request,I will do this also this)

The database:

image

The beginning of the application :

First Layer,Data Access Layer
I use EF 3.5 (not 4.0 with POCO style – because is not ready yet) and make an edmx file and let EF put his classes.
You can use also ADO.NET with StoredProc,L2S,NHibernate or any other ORM you want.
Second Layer,Business Logic :
This is the layer where the logic should intervene (e.g.,the name should be not null ).

Here is the list for Employee :

namespace BusinessLogic

{

    /// <summary>

    /// TODO : add IDataErroInfo in order to validate

    /// TODO : add the department

    /// </summary>

    public class Employee

    {

        public long ID;

        public string Name { get; set; }

        public Department Department{ get; set; }

        public void SaveNew()

        {

            //TODO : validate before save

            //TODO : automapper

            using (DAL_EF.testsEntities te = new DAL_EF.testsEntities("name=myconnection"))

            {

                DAL_EF.Employee e = new DAL_EF.Employee();

                e.Name = this.Name;

                //TODO : what if dept. deleted ?

                e.Department =te.Department.Where(d=>d.ID== this.Department.ID).FirstOrDefault();

                te.AddToEmployee(e);

                te.SaveChanges();

            }

        }

    }

    public class EmployeeList : List<Employee >

    {

        public void Load()

        {

            using (DAL_EF.testsEntities te = new DAL_EF.testsEntities("name=myconnection"))

            {

                foreach (var emp in te.Employee.Include("Department"))

                {

                    //TODO : use automapper

                    Employee e=new Employee() { ID = emp.ID,Name = emp.Name };

                    e.Department=new Department(){ ID=emp.Department.ID,Name=emp.Department.Name};

                    this.Add(e);

                }

            }

        }

    }

}

Please pay attention for Load procedure in EmployeeList : it uses the first layer,DAL,but it can use any ORM framework.

Third layer,ViewModel:

Because all the views for employees will need a select list for department ( either for sorting,creating or updating) I have put a base ViewModel class that retrieves the list of Departments:

namespace MVCAppEmp.Classes
{
    public class ViewModelEmployee
    {
        public static SelectList ListOfDepartments
        {
            get
            {
                //TODO : put this into cache to not load every time
                DepartmentList dl = new DepartmentList();
                dl.Load();
                return dl.SelectFromList(x => x.ID.ToString(),y => y.Name);
            }
        }
    }
    public class ViewModelEmployeeCreate : ViewModelEmployee
    {
        public Employee emp=new Employee();
    }
    public class ViewModelEmployeeList : ViewModelEmployee
    {
        public EmployeeList employees;
        public void Load()
        {
            employees = new EmployeeList();
            employees.Load();
        }
    }
}


Fourth Layer,MVC itself – view and controller :

<% =Html.ValidationSummary() %>
<% using (Html.BeginForm())
   { %>
    <h2>Create</h2>
    List of departments :
    <% =Html.DropDownList("DepartmentID",MVCAppEmp.Classes.ViewModelEmployee.ListOfDepartments)%>
    <%=Html.EditorFor(model => model.emp)%>
<input type="submit" value="create" />
<%} %>

and the controller

// POST: /Employee/Create
       // TODO: make a binding for employees
       [HttpPost]
       public ActionResult Create(Employee emp,long DepartmentID)
       {
           try
           {

               emp.Department = new Department() { ID = DepartmentID };
               emp.SaveNew();
               return RedirectToAction("Index");
           }
           catch(Exception ex)
           {
               ModelState.AddModelError("",ex.Message);
               return View(new ViewModelEmployeeCreate(){emp=emp});
           }
       }

So to answer the questions :

  1. One to many relationship – easy to do,most difficult to program
  2. Dropdownlist – easy – just transform a list into a select list,provided you have all data belongs
  3. How to use MVC with other ORM frameworks instead of Linq To Sql(L2S) ? Does not matter ! Just create your BusinessLogic and use that ORM!
  4. What is a ViewModel and what is his purpose ? To fill the data for GUI that BusinessLogic does not comply and transfer data to BusinessLogic. Reciprocally too!

You will find attached the application and the sql to create the database :

For MVC2  /MVC 3
http://msprogrammer.serviciipeweb.ro/wp-content/uploads/ASP.NETMVCORMandViewModels_135E/emp.zip

For MVC 4

http://msprogrammer.serviciipeweb.ro/wp-content/uploads/ASP.NETMVCORMandViewModels_135E/empMVC4.zip

What to do next,in order to familiarize yourself :
1. Make the update of the employees .Create view,save.
2. Filter the list of the employees on department. Search for all employees beginning with A that belong to IT department.
3. Search for TODO’s : there are part of other tutorials – but it will help you in MVC (and other!) development

This post have a continuation here:

http://msprogrammer.serviciipeweb.ro/2010/07/05/asp-net-mvc-and-dos-re-using-the-viewmodels/


Posted

in

,

by

Comments

17 responses to “ASP.NET MVC,ORM and ViewModels”

  1. […] This post was mentioned on Twitter by ignatandrei, Larry King. Larry King said: ASP.NET MVC , ORM and ViewModels « A Programmer with Microsoft tools http://bit.ly/dcp1Jn #MVC […]

  2. Mr. D Avatar
    Mr. D

    Hi, Great blog by the way. I’m working with MVC 2 and EF 4 with POCO. For some reason I’m getting this error message: Mapping and metadata information could not be found for EntityType ‘NorthwindMvcPoco.Models.Category’.

    I upload my project in Rapidshare: http://rapidshare.com/files/372303498/NorthwindMvcPoco.rar.html
    Please check out the project and help me out. I use VS 2010 and SQL Server 2008. I’m using Northwind as my database.

  3. markp3rry Avatar

    Really useful information – simple example of the different layers in an MVC project. The way you store your business logic in a custom class is the way that I have been doing things too and it’s good to know that I’m on the right track – thanks for your response to http://forums.asp.net/p/1758603/4779940.aspx/1?Re+Class+design+101

  4. mona Avatar
    mona

    Can u please tell me, where we use model view and view model? what ia the difference between them?

    Thanks

    1. Andrei Ignat Avatar
      Andrei Ignat

      Usually, Model is database Model ( mapping table in code)
      ViewModel is the Model of the View – see example in this post.

  5. Deepak Avatar

    Hi,

    I was trying understand your code here. I have one issue;
    In layer 3 line 10, where is the DepartmentList class? What is inside it?

    public static SelectList ListOfDepartments
    {
    get
    {
    //TODO : put this into cache to not load every time
    DepartmentList dl = new DepartmentList(); x.ID.ToString(), y => y.Name);
    }

    Also, can you suggest me best way to show dropdownlist based on foreign key in Razor?

    Thanks,
    Deepak.

  6. Danny Avatar

    First off, good article. We have been arguing to do the same thing (because we are making a transition from C#.NET desktop to web ASP.NET MVC).

    Our question is, how do you support automatic paging/sorting this way via EF?

    1. Andrei Ignat Avatar
      Andrei Ignat

      Search for Troy Goode Paging

  7. Hélder Avatar

    Hi Andrei, great article.

    Could you provide the example forVisual Studio 2012, The MCV project is reporting incompatible.

    Best Regards
    Hélder

    1. Andrei Ignat Avatar
      Andrei Ignat

      Update with VS2012, MVC4

    2. Andrei Ignat Avatar
      Andrei Ignat

      Provided

  8. Paul Avatar
    Paul

    Hi,
    In the business logic layer I can see that using (DAL_EF.testsEntities te = new DAL_EF.testsEntities(“name=myconnection”)). I am planning to make the DLL of the business logic layer and use it in the UI. How will you pass “myconnection” which is in the web.config to the busieness logic layer via DLL?
    Thanks,
    Paul

    1. Andrei Ignat Avatar
      Andrei Ignat

      via a new property – or parameter to the function

  9. Venkannababu Ryali Avatar

    how to make communication b/w model and controller while using ADO.net code in our model…?

    1. Andrei Ignat Avatar
      Andrei Ignat

      The Model of the View can call various ADO.NET functions.

Leave a Reply

Your email address will not be published. Required fields are marked *