Building a LOB application with MVC 5 – Part 2 – Models and Generic Repository

In the previous part of building line of business application with MVC 5, we introduced MVC and created the solution structure

if you didn’t read the first 2 parts, please go ahead and read it from the below links

  1. Building a LOB application with MVC 5 – Part 0
  2. Building a LOB application with MVC 5 – Part 1

In this part, we will introduce Models and build the needed business entities in our business application, we will also explain how to save the data using Entity Framework, below are the exact topics we are going to discuss about models:

  1. Developing Models
  2. Using Display and Edit Data Annotations on Properties
  3. Validating User Input with Data Annotations
  4. What Are Model Binders?
  5. Entity Framework 6

 

Developing Models

Every software project has a model, this model may or may not map exactly to a database, the model is a collection of classes and relationships between these classes, every class has some properties, these properties can be primitives like int, string, Boolean, or it can be complex like Customer, Order ..

In our application, the model will be as below

Models

To add the model to your visual studio solution, add the following classes to the AppointmentManager.Models, after you are done, your models project should look like the following.

NB: I have added the code for main classes only, the rest are very simple and can be added by looking at the class diagram

 

Models Project

  1. BusinessEntity, this is the base class that all model entities will inherit from, it contains some common properties between all classes like ID, Creation date and last modification date, the settings of these properties will be done in one place in our repository to minimize the effort needed
    public abstract class BusinessEntity
        {
            public int ID { get; set; }
    
            public DateTime CreationDate { get; set; }
    
            public DateTime LastModificationDate { get; set; }
    
            public User CreatedBy { get; set; }
    
            public User LastModifiedBy { get; set; }
        }
     
  2. ValueObject, this is the base for all model objects that have no identity, unlike entities that have an ID that distinguish it from other entities, value objects have no ID, it is identified by its value, ex: a Money class has no ID, only the amount identities it, in our case, a TimeSlot has no ID, it can be identified by the start time and duration
    public class ValueObject<T>
        {
            T Value { get; set; }
        }
     
  3. User
    public class User : BusinessEntity
        {
            public bool IsActive { get; set; }
    
            public string FirstName { get; set; }
    
            public string LastName { get; set; }
    
            public string EmailAddress { get; set; }
    
            public string MobileNumber { get; set; }
        }
     
  4. Customer
     public class Customer : User
        {
            public string Address { get; set; }
    
            public virtual ICollection<Appointment> Appointments { get; set; }
    
            public virtual ICollection<CustomerProfile> Profiles { get; set; }
    
        }
     
  5. CustomerProfile
    public class CustomerProfile : BusinessEntity
        {
            public string Name { get; set; }
    
            public string CustomerID { get; set; }
    
            public int ServiceTypeID { get; set; }
    
            public ServiceType ServiceType { get; set; }
    
            public virtual Customer Customer { get; set; }
    
            public virtual ICollection<CustomerProfileAttribute> Attributes { get; set; }
        }
     
  6. Service
    public class Service : BusinessEntity
        {
            public string Name { get; set; }
    
            public string Description { get; set; }
    
            public int ServiceTypeID { get; set; }
    
            public virtual ServiceType ServiceType { get; set; }
        }
     
  7. ServiceProvider
          public class ServiceProvider : User
            {
                public string Title { get; set; }
    
                public string StreetAddress1 { get; set; }
    
                public string StreetAddress2 { get; set; }
    
                public string City { get; set; }
    
                public string State { get; set; }
    
                public string CountryID { get; set; }
    
                public string ZipCode { get; set; }
    
                public string BusinessTelephoneNumber { get; set; }
    
                public string WebSite { get; set; }
    
                public string TaxIdentificationNumber { get; set; }
    
                public string LicenseNumber { get; set; }
    
                public bool IsAvailableSaturday { get; set; }
    
                public bool IsAvailableSunday { get; set; }
    
                public bool IsAvailableMonday { get; set; }
    
                public bool IsAvailableTuesday { get; set; }
    
                public bool IsAvailableWednesday { get; set; }
    
                public bool IsAvailableThursday { get; set; }
    
                public bool IsAvailableFriday { get; set; }
    
                public virtual Country Country { get; set; }
    
                public virtual ICollection<Appointment> Appointments { get; set; }
    
                public virtual ICollection<ServiceType> ServiceTypes { get; set; }
    
                public virtual ICollection<TimeSlot> Availability { get; set; }
    
                public virtual ICollection<ServiceProviderReview> Reviews { get; set; }
            }
     
  8. ServiceProviderReview
    public class ServiceProviderReview : BusinessEntity
        {
            public string ServiceProviderID { get; set; }
    
            public int Rating { get; set; }
    
            public int AppointmentId { get; set; }
    
            public string CustomerId { get; set; }
    
            public string Comment { get; set; }
    
            public virtual ServiceProvider ServiceProvider { get; set; }
    
            public virtual Appointment Appointment { get; set; }
    
            public virtual Customer Customer { get; set; }
        }
     
  9. TimeSlot
     public class TimeSlot : ValueObject<TimePeriod>
        {
            public TimePeriod Value
            {
                get; set;
            }
        }
    
        public class TimePeriod
        {
            public DateTime StartTime { get; set; }
    
            public int DurationInMinutes { get; set; }
        }
     
  10. Appointment
    public class Appointment : BusinessEntity
        {
            public int ServiceProviderID { get; set; }
    
            public int CustomerID { get; set; }
    
            public int CustomerProfileId { get; set; }
    
            public int AppointmentStatusId { get; set; }
    
            public int TimeSlotId { get; set; }
    
            public DateTime AppointmentTime { get; set; }
    
            public int DurationInMinutes { get; set; }
    
            public bool IsPaidByProvider { get; set; }
    
            public AppointmentStatus AppointmentStatus { get; set; }
    
            public Customer Customer { get; set; }
    
            public ICollection<Service> Services { get; set; }
    
            public ServiceProvider ServiceProvider { get; set; }
    
            public CustomerProfile CustomerProfile { get; set; }
    
            public TimeSlot TimeSlot { get; set; }
    
            public ServiceProviderReview CustomerReview { get; set; }
        }
    

Now, we defined our model, lets define how will we store the model objects into the database using the Repository layer defined in the AppointmentManager.Repository project, we will be using SQL Server as a persistence medium.

As we know, we should always program against interfaces and also we should not repeat our selves, this is why we will create a generic Repository that will abstract the CRUD operations.

Create a new interface called IRepository in the AppointmentManager.Repository project and add the following code to it.

 public interface IRepository<T, K> where T : class
    {
        T Add(T item);

        bool Update(T item);

        bool DeleteByID(K id);

        bool Delete(T item);

        T GetByID(K id);

        IQueryable<T> GetAll();

        IQueryable<T> GetAll(Expression<Func<T, K>> orderBy);

        IQueryable<T> GetAll(int pageIndex, int pageSize);

        IQueryable<T> GetAll(int pageIndex, int pageSize, Expression<Func<T, K>> orderBy);

        IQueryable<T> Find(Expression<Func<T, bool>> predicate);

        IQueryable<T> Find(Expression<Func<T, bool>> predicate, int pageIndex, int pageSize, Expression<Func<T, K>> orderBy);
    }

As you can see, this interface has all the data access logic you may need in most of the business cases, also all methods returns IQueryable which allows the caller to add extra filtering.

As we explained in Part 1, the data access layer will be called by the service/business logic layer , so we need also a generic service layer that will call the data access layer generic repository.

To do that, create a new interface in the AppointmentManager.Services project and name it IService

 
public interface IService<T, K> where T : class
    {
        T Add(T item);

        bool Update(T item);

        bool DeleteByID(K id);

        bool Delete(T item);

        T GetByID(K id);

        IQueryable<T> GetAll();

        IQueryable<T> GetAll(Expression<Func<T, K>> orderBy);

        IQueryable<T> GetAll(int pageIndex, int pageSize);

        IQueryable<T> GetAll(int pageIndex, int pageSize, Expression<Func<T, K>> orderBy);

        IQueryable<T> Find(Expression<Func<T, bool>> predicate);

        IQueryable<T> Find(Expression<Func<T, bool>> predicate, int pageIndex, int pageSize, Expression<Func<T, K>> orderBy);
    }
 

Now, in the same project, create a new class and name it BaseService and make it inherits the IService class, make sure to add a reference to AppointmentManager.Repository

public class BaseService<T, K> : IService<T, K> where T : class
    {
        private IRepository<T, K> _repository;

        public BaseService(IRepository<T, K> repository)
        {
            this._repository = repository;
        }

        public T Add(T item)
        {
            return _repository.Add(item);
        }

        public bool Delete(T item)
        {
            return _repository.Delete(item);
        }

        public bool DeleteByID(K id)
        {
            return _repository.DeleteByID(id);
        }

        public IQueryable<T> Find(Expression<Func<T, bool>> predicate)
        {
            return _repository.Find(predicate);
        }

        public IQueryable<T> Find(Expression<Func<T, bool>> predicate, int pageIndex, int pageSize, Expression<Func<T, K>> orderBy)
        {
            return _repository.Find(predicate, pageIndex, pageSize, orderBy);
        }

        public IQueryable<T> GetAll()
        {
            return _repository.GetAll();
        }

        public IQueryable<T> GetAll(Expression<Func<T, K>> orderBy)
        {
            return _repository.GetAll(orderBy);
        }

        public IQueryable<T> GetAll(int pageIndex, int pageSize)
        {
            return _repository.GetAll(pageIndex, pageSize);
        }

        public IQueryable<T> GetAll(int pageIndex, int pageSize, Expression<Func<T, K>> orderBy)
        {
            return _repository.GetAll(pageIndex, pageSize, orderBy);
        }

        public T GetByID(K id)
        {
            return _repository.GetByID(id);
        }

        public bool Update(T item)
        {
            return _repository.Update(item);
        }
    }

So far, We have a base service to be used for our business logic, a base interface to be used in our data access layer.
Still we didn’t write any code to save our entities into the database as this will require EntityFramework which will be introduced in the next part.

You can get the full source code from GitHub Repository https://github.com/haitham-shaddad/AppointmentManager
Advertisements

Building a LOB application with MVC 5 – Part 1

In the previous part of building line of business application with MVC 5, we have setup the project on TFS Online, added the user stories and introduced the application business, if you didn’t read it already, please go ahead and read it from the below link

Building a LOB application with MVC 5 – Part 0

After you are done, The project backlog should be similar to the below screenshot

backlog full.PNG

In this part, we will start with an introduction to MVC, Create the solution structure and go through the moving parts.

Introduction to MVC

For many years we have been using Web Forms, Creating pages, user controls and custom dynamic controls, but when the project size gets bigger, it gets complicated and the whole framework was also tied to .Net framework release which was slow.

In 2009, Microsoft released the first version of MVC and it was not tied to .Net framework release cycle which made the release cycle of MVC much faster.

Now we have MVC 5.2 and in few months we should have MVC 6 which is a complete rewrite of MVC, but we won’t talk about it in this series.

MVC makes it easier to maintain a larger project and a large team, and as we will see, you can divide the project into sub-projects using something called Areas.

MVC has 3 main components

  1. Models

    Contains your model classes, DTO, and your business services, normally the business logic layer will be in a different assembly

  2. Views

   This is how your model and content will be represented, MVC can render your data in HTML view, JSON, Stream or even file.

  1. Controllers

The controller will accept the user request, acting as a front end dispatcher, validate the user input, call the business logic and choose what view to use in order to render the data

You can read more about MVC through Microsoft official site http://www.asp.net/mvc

Create Solution structure

Now, lets open Visual Studio and create the project structure, you will notice that we will create a lot of projects, and I will explain what is the usage of each one.

  1. Open visual studio as Administrator, I am using VS 2015 Enterprise, But if you have VS 2013, it should be the same experience
  2. Click View Menu-> Team Explorer in order to link the project to TFS
  3. Click the green icon > Manage Connections > Connect to Team ProjectTFS Browser
  4. In the popup, click Servers -> Add
  5. Enter the link for your visual studio account, ex: https://%5Byouraccount%5D.visualstudio.com
  6. Visual studio will authenticate you and add the server to the list of TFS servers
  7. Make sure the server is selected in the “Select team foundation server” drop down
  8. Select the team project from the list on the right, in our case it is Appointment Manager
  9. Click ConnectTFS Servers.png
  10. Once the dialog is closed, you will find the server name and below it there will be a list of projects you already have, click the Appointment ManagerTFS Select Project
  11. Once the project is selected, it will ask you to clone the project into your local machine, click on “Clone this repository” link and choose a folder on your H.D and click Cloneclone project.PNG
  12. Once the project is cloned to your local work-space, you will click on the “New” link under the Solutions in the screenshot above, this will open the New VS project dialog
  13. Type blank in the search text box and find the “Blank Solution” template, Enter the name as “Appointment Manager”, the location will be the folder that you chose when you cloned the project, keep it as isnew project dialog
  14. Now from the menu, click View -> Solution Explorer
  15. Right click the Solution and select Add->New Project
  16. Select Windows from the left tree, and Class Library from the list of project templates
  17. Enter the name for the project as AppointmentManager.Models, we will explain later what is this used for, once the project is created, delete the default class Class1.cs
  18. Repeast Steps 14 till 17 for the following projects
    1. AppointmentManager.Repository
    2. AppointmentManager.Repository.EntityFramework
    3. AppointmentManager.Services
    4. AppointmentManager.CrossCutting
  19. Add another project but in this time select web from the left tree, and “Asp.Net Web Application”, name the project AppointmentManager.Web
  20. Another dialog will open, select MVC and keep the Authentication as Individual User Accounts for now, your screen should be similar to this new web project dialog.png

 

By this, you have created the solution structure, I will explain below what will each project be used for

Solution Structure in Details

Now, you should see something like the below in your visual studio solution, I will explain now what each project will be used forsolution structure.PNG

AppointmentManager.CrossCutting

This project will contain all the classes that will be used across all layers, ex: Logging, caching, security and any other utility classes

AppointmentManager.Models

This project will contain all entity classes related to our bunsiness, these classes will be mainly plain old CLR objects (POCO), it has no business logic, just the properties in each class and any other attributes like Required, Length.

Sample of these classes are: Appointment, ServiceProvider, Booking..

AppointmentManager.Repository

This project will contain everything related to data access layer, however it won’t contain a specific implementation, here will be only the abstraction, ex: IAppointmentRepostitory will describe all methods needed for the appointment data access

AppointmentManager.Repository.EntityFramework

This will contain the implementation for the interfaces defined in AppointmentManager.Repository project using Entity Framework, this will make it easy for us later to change the implementation to other ORM or data access

AppointmentManager.Services

This will contain all the business logic layer code, any data access will be delegated to the repository layer.

AppointmentManager.Web

This project will contain all the UI stuff, like MVC Views, JavaScript, CSS, Bundeling, Configuration, and User request handling and validation

This layer will call the service layer to handle any business logic layer.

So the flow will be as the below diagramLogical diagram.png

 

So far, we have created the project structure, explained what is each part and if you set the startup project to AppointmentManager.Web and run the project, you will have a web application running with the default template.

In the next series, we will start adding some functionality to the application and will discuss more about the web project structure

You can get the full source code from GitHub Repository https://github.com/haitham-shaddad/AppointmentManager

Building a LOB application with MVC 5 – Part 0

There are a lot of tutorials and blog posts about MVC, Web API and other Asp.Net technologies, but it has been always a problem getting all these parts together in once place and utilize it to build something bigger.

In this post, I will start a series where we will introduce and build a complete functioning lin of business web application using Asp.Net MVC 5, I will start with introducing the business behind the application, and in each part, we will introduce a new feature of MVC and use it to build a new feature in our LOB application, this will allow us to know how to use MVC in practical example and we will also go deep dive in each feature to build more advanced features.

Introduction to the LOB Application

The application we are going to build together is called Appointment Manager, it will be a flexible application that allows users to register either as service provider or consumer, below are the list of features for each role

  1. Service providers. ex:doctors, mechanics, carpenters
    1.  Check his Calendar
    2. View appointment details
    3. View ratings for his work
    4. Select which services he provides
    5. Manage his available time slots for each service
  2. Service consumers
    1. Browse service categories
    2. Browse service providers in a specific category
    3. View specific service provider details, history and rating
    4. Book an appointment
    5. Check his Calendar
    6. Rate a service Provider
  3. Admin
    1. Manage Service Categories
    2. Manage Attribute for each service category, ex: Mechanic category will have Car model, Year and his services will include Oil change, A/C, …
  4. Shared Features
    1. Register
    2. Login, Logout
    3. Edit Profile

By the end of this series we will have the application built and we will have full knowledge of MVC 5 framework

Introdction to the Technical Part

In each part, we will introduce a key component in MVC and use it to build another feature in the application, below are the features we are going to discuss in MVC

  1. Introduction to MVC
  2. Models
  3. View
  4. Controllers
  5. Routing
  6. Localization
  7. Bootstrap
  8. EntityFramework
  9. Identity and Security
  10. Bootstrap
  11. SignalR

Setting up ALM

Since this will be a real business application, we want to apply everything we do in the real life, and the first thing is to decide about how are we going to manage the application life-cycle management, fortunately, Microsoft offers a full platform for that;TFS, In our series, I will use Team services or TFS Online with GitHub as our source code repository, You can also use TFS on premise, Microsoft offers TFS express for free, you can download and install it and use it through the series

I will start by creating the project and then enter the list of features into a user stories.

Since TFS online support Git, I will use it as our source code control and I will link it later to GitHub

Create the project on TFS Online

In order to be able to use TFS online, you have to have a visual studio account, if you don’t already have one,go to VisualStudio.com and register using your MS Account, it is free

  1. Open your browser and navigate to https://[your account].visualstudio.com
  2. Under “Recent Projects & Teams” Click New TFS New
  3. Enter the Project name, description, Process Template and Version control as Git, TFS support different process templates such as Scrum and CMMI, if you have different needs, you can create a new template and customize it, we won’t go deeper here but you can read more about TFS templates from this link https://msdn.microsoft.com/en-us/library/ms243782.aspxNew Project
  4. Once the project is created, clink on “Navigate to the project” button
  5. Once the page is loaded, you will see a dashboard from where you can see everything about your project, ex: Code, Sprint burn down chart and user stories
  6. Click on Backlog link in the Work widget to start editing the user storiesTFS dashboard
  7. Once the page is loaded, you can add the story by typing the story title in title field and press enter or click Add button, if you can’t see the title field, just click the New link as shown in the screenshot belowbacklog

After the story is added, you can double click it to open the edit dialog which will enable you to add all the details, once this is done, click the Save icon on the top rightedit story

  1. TFS offers you the ability to categorize your user stories into something called Features, think of it as sub-modules to group the related features together, You can click Features from the left menu and add the needed features, then go to the backlog  by clicking the Stories link and Click the Mapping icon and make sure it is On, this will open a panel on the right with the list of features defined, drag the user stories from the left and drop it over the feature

So far, we talked about the application we want to build, we configured its source control and added its requirement.

In the next part we will introduce MVC 5, Create the project structure and build the home page for the application.

You can get the full source code from GitHub Repository https://github.com/haitham-shaddad/AppointmentManager