Introduction
In this article, we will demonstrate how we can build an application that creates the CV. As you know, resume/CV has different parts, such as - personal information, education, work experiences, skills, certifications, languages. We are using ASP.NET MVC 5, jQuery, and Bootstrap in order to build our application. I hope you will like it.
Prerequisites
Make sure you have installed Visual Studio 2015 (.NET Framework 4.5.2) and SQL Server. In this post, we are going to:
- Create Database.
- Create MVC application.
- Configuring Entity framework ORM to connect to the database.
- Create repository.
- Create resume controller.
- Adding all the needed pages in order to build our application.
SQL Database part
The database script is included in the source code of our project.
Create your MVC application
Open Visual Studio and select File >> New Project.
The "New Project" window will pop up. Select ASP.NET Web Application (.NET Framework), name your project, and click OK.
Next, a new dialog will pop up for selecting the template. We are going choose MVC template and click OK.
Once our project is created, we will add ADO.NET Entity Data Model.
Adding ADO.NET Entity Data Model
Right-click on the project name, click Add >> Add New Item.
A dialog box will pop up. Inside Visual C#, select Data >> ADO.NET Entity Data Model, and enter the name for your DbContext model as Resume, then click Add.
As you can see, we have 4 model contents. We are selecting the first approach (EF Designer from the database).
As you can see below, we need to select server name, then via drop down list, connect to a database section. You must choose your database name and finally click OK.
For the next step, the dialog Entity Data Model Wizard will pop up for choosing objects which will be used in our application. We are selecting all the tables followed by a click on "Finish" button.
Finally, we see that EDMX model generates all the objects, as shown below.
Create repository
After generating our Edmx file, the next step is to create all methods which will be used in our application.
First, we need to create repository folder. To do that, from solution explorer, right click on project name >> Add >> New Folder (you can name it as you like).
Now, we will add IResumeRepository interface which contains all the methods that should be implemented in our ResumeRepository class.
IResumeRepository.cs
- using ResumeMVC.EDMXModel;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Web;
-
- namespace ResumeMVC.Repository
- {
- public interface IResumeRepository
- {
- bool AddPersonnalInformation(Person person, HttpPostedFileBase file);
- string AddOrUpdateEducation(Education education, int idPer);
- int GetIdPerson(string firstName, string lastName);
- string AddOrUpdateExperience(WorkExperience workExperience, int idPer);
- bool AddSkill(Skill skill, int idPer);
- bool AddCertification(Certification certification, int idPer);
- bool AddLanguage(Language language, int idPer);
- Person GetPersonnalInfo(int idPer);
- IQueryable<Education> GetEducationById(int idPer);
- IQueryable<WorkExperience> GetWorkExperienceById(int idPer);
- IQueryable<Skill> GetSkillsById(int idPer);
- IQueryable<Certification> GetCertificationsById(int idPer);
- IQueryable<Language> GetLanguageById(int idPer);
- }
- }
ResumeRepository.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using ResumeMVC.EDMXModel;
- using System.IO;
- using System.Data.Entity.Validation;
- using System.Data.Entity;
- using AutoMapper.QueryableExtensions;
- using ResumeMVC.ViewModels;
-
- namespace ResumeMVC.Repository
- {
- public class ResumeRepository : IResumeRepository
- {
-
- private readonly DBCVEntities _dbContext = new DBCVEntities();
-
- public bool AddCertification(Certification certification, int idPer)
- {
- try
- {
- int countRecords = 0;
- Person personEntity = _dbContext.People.Find(idPer);
-
- if (personEntity != null && certification != null)
- {
- personEntity.Certifications.Add(certification);
- countRecords = _dbContext.SaveChanges();
- }
-
- return countRecords > 0 ? true : false;
- }
- catch (DbEntityValidationException dbEx)
- {
-
- throw;
- }
-
- }
-
- public bool AddLanguage(Language language, int idPer)
- {
- int countRecords = 0;
- Person personEntity = _dbContext.People.Find(idPer);
-
- if (personEntity != null && language != null)
- {
- personEntity.Languages.Add(language);
- countRecords = _dbContext.SaveChanges();
- }
-
- return countRecords > 0 ? true : false;
- }
-
- public string AddOrUpdateEducation(Education education, int idPer)
- {
- string msg = string.Empty;
-
- Person personEntity = _dbContext.People.Find(idPer);
-
- if(personEntity != null)
- {
- if (education.IDEdu > 0)
- {
-
- _dbContext.Entry(education).State = EntityState.Modified;
- _dbContext.SaveChanges();
-
- msg = "Education entity has been updated successfully";
- }
- else
- {
-
- personEntity.Educations.Add(education);
- _dbContext.SaveChanges();
-
- msg = "Education entity has been Added successfully";
- }
- }
-
- return msg;
- }
-
- public string AddOrUpdateExperience(WorkExperience workExperience, int idPer)
- {
- string msg = string.Empty;
-
- Person personEntity = _dbContext.People.Find(idPer);
-
- if (personEntity != null)
- {
- if (workExperience.IDExp > 0)
- {
-
- _dbContext.Entry(workExperience).State = EntityState.Modified;
- _dbContext.SaveChanges();
-
- msg = "Work Experience entity has been updated successfully";
- }
- else
- {
-
- personEntity.WorkExperiences.Add(workExperience);
- _dbContext.SaveChanges();
-
- msg = "Work Experience entity has been Added successfully";
- }
- }
-
- return msg;
- }
-
- public bool AddPersonnalInformation(Person person, HttpPostedFileBase file)
- {
- try
- {
- int nbRecords = 0;
-
- if (person != null)
- {
- if (file != null)
- {
- person.Profil = ConvertToBytes(file);
- }
-
- _dbContext.People.Add(person);
- nbRecords = _dbContext.SaveChanges();
- }
-
- return nbRecords > 0 ? true : false;
- }
- catch (DbEntityValidationException dbEx)
- {
-
- Exception raise = dbEx;
- foreach (var validationErrors in dbEx.EntityValidationErrors)
- {
- foreach (var validationError in validationErrors.ValidationErrors)
- {
- string message = string.Format("{0}:{1}",
- validationErrors.Entry.Entity.ToString(),
- validationError.ErrorMessage);
-
-
- raise = new InvalidOperationException(message, raise);
- }
- }
- throw raise;
- }
-
- }
-
- public bool AddSkill(Skill skill, int idPer)
- {
- int countRecords = 0;
- Person personEntity = _dbContext.People.Find(idPer);
-
- if(personEntity != null && skill != null)
- {
- personEntity.Skills.Add(skill);
- countRecords = _dbContext.SaveChanges();
- }
-
- return countRecords > 0 ? true : false;
-
- }
-
- public IQueryable<Certification> GetCertificationsById(int idPer)
- {
- var certificationList = _dbContext.Certifications.Where(w => w.IdPers == idPer);
- return certificationList;
- }
-
- public IQueryable<Education> GetEducationById(int idPer)
- {
- var educationList = _dbContext.Educations.Where(e => e.IdPers == idPer);
- return educationList;
- }
-
- public int GetIdPerson(string firstName, string lastName)
- {
- int idSelected = _dbContext.People.Where(p => p.FirstName.ToLower().Equals(firstName.ToLower()))
- .Where(p => p.LastName.ToLower().Equals(lastName.ToLower()))
- .Select(p => p.IDPers).FirstOrDefault();
-
- return idSelected;
- }
-
- public IQueryable<Language> GetLanguageById(int idPer)
- {
- var languageList = _dbContext.Languages.Where(w => w.IdPers == idPer);
- return languageList;
- }
-
- public Person GetPersonnalInfo(int idPer)
- {
- return _dbContext.People.Find(idPer);
- }
-
- public IQueryable<Skill> GetSkillsById(int idPer)
- {
- var skillsList = _dbContext.Skills.Where(w => w.IdPers == idPer);
- return skillsList;
- }
-
- public IQueryable<WorkExperience> GetWorkExperienceById(int idPer)
- {
- var workExperienceList = _dbContext.WorkExperiences.Where(w => w.IDPers == idPer);
- return workExperienceList;
- }
-
- private byte[] ConvertToBytes(HttpPostedFileBase image)
- {
- byte[] imageBytes = null;
- BinaryReader reader = new BinaryReader(image.InputStream);
- imageBytes = reader.ReadBytes((int)image.ContentLength);
- return imageBytes;
- }
-
- }
- }
Note
Do not forget to add the following View Models.
To do that, from solution explorer, right click on project name >> Add >> New Folder.
CertificationVM.cs
- public class CertificationVM
- {
- [Required(ErrorMessage = "Please Your Certification name")]
- public string CertificationName { get; set; }
-
- [Required(ErrorMessage = "Please enter Certification Authority")]
- public string CertificationAuthority { get; set; }
-
- [Required(ErrorMessage = "Please select Certification Level")]
- public string LevelCertification { get; set; }
-
- [Required(ErrorMessage = "Please select achievement date")]
- public Nullable<System.DateTime> FromYear { get; set; }
-
- public List<SelectListItem> ListOfLevel { get; set; }
- }
EducationVM.cs
- public class EducationVM
- {
-
- public int IDEdu { get; set; }
-
- [Required(ErrorMessage = "Please Your Institute or university")]
- public string InstituteUniversity { get; set; }
-
- [Required(ErrorMessage = "Please Your Title of diploma")]
- public string TitleOfDiploma { get; set; }
-
- [Required(ErrorMessage = "Please Your Degree")]
- public string Degree { get; set; }
-
- [Required(ErrorMessage = "Please enter Start Year")]
- public Nullable<System.DateTime> FromYear { get; set; }
-
- [Required(ErrorMessage = "Please enter End Year")]
- public Nullable<System.DateTime> ToYear { get; set; }
- [Required(ErrorMessage = "Please enter City")]
- public string City { get; set; }
- [Required(ErrorMessage = "Please enter Country")]
- public string Country { get; set; }
-
- public List<SelectListItem> ListOfCountry { get; set; }
- public List<SelectListItem> ListOfCity { get; set; }
-
- }
LanguageVM.cs
- public class LanguageVM
- {
- [Required(ErrorMessage = "Please enter Language Name")]
- public string LanguageName { get; set; }
-
- [Required(ErrorMessage = "Please select Proficiency")]
- public string Proficiency { get; set; }
-
- public List<SelectListItem> ListOfProficiency { get; set; }
- }
PersonVM.cs
- public class PersonVM
- {
- public int IDPers { get; set; }
-
- [Required(ErrorMessage = "Please Your First Name ")]
- public string FirstName { get; set; }
- [Required(ErrorMessage = "Please Your Last Name ")]
- public string LastName { get; set; }
- [Required(ErrorMessage = "Please Your Date Of Birth ")]
- public Nullable<System.DateTime> DateOfBirth { get; set; }
-
- [Required(ErrorMessage = "Please Your Nationality ")]
- public string Nationality { get; set; }
-
- [Required(ErrorMessage = "Select Your Educational Level ")]
- public string EducationalLevel { get; set; }
-
- [Required(ErrorMessage = "Please Your Address ")]
- public string Address { get; set; }
-
- [Required(ErrorMessage = "Please Your Phone Number ")]
- public string Tel { get; set; }
-
- [Required(ErrorMessage = "Please Your Email Address ")]
- public string Email { get; set; }
-
- [Required(ErrorMessage = "Please Your Summary")]
- [DataType(DataType.MultilineText)]
- public string Summary { get; set; }
-
- [Required(ErrorMessage = "Please Your LinekedIn Profil")]
- [DataType(DataType.Url)]
- public string LinkedInProdil { get; set; }
-
- [Required(ErrorMessage = "Please Your Facebook Profil")]
- [DataType(DataType.Url)]
- public string FaceBookProfil { get; set; }
-
- [Required(ErrorMessage = "Please Your C# Corner Profil")]
- [DataType(DataType.Url)]
- public string C_CornerProfil { get; set; }
-
- [Required(ErrorMessage = "Please Your Twitter Profil")]
- [DataType(DataType.Url)]
- public string TwitterProfil { get; set; }
- public byte[] Profil { get; set; }
-
- public List<SelectListItem> ListNationality { get; set; }
- public List<SelectListItem> ListEducationalLevel { get; set; }
- }
SkillsVM.cs
- public class SkillsVM
- {
- [Required(ErrorMessage="Please enter your skill name")]
- public string SkillName { get; set; }
- }
WorkExperienceVM.cs
- public class WorkExperienceVM
- {
- public int IDExp { get; set; }
-
- [Required(ErrorMessage ="Please Your Company")]
- public string Company { get; set; }
-
- [Required(ErrorMessage = "Please Your Title")]
- public string Title { get; set; }
-
- [Required(ErrorMessage = "Please Country is required")]
- public string Country { get; set; }
-
- [Required(ErrorMessage = "Please enter Start Date")]
- public Nullable<System.DateTime> FromYear { get; set; }
-
- [Required(ErrorMessage = "Please enter End Date")]
- public Nullable<System.DateTime> ToYear { get; set; }
-
- [Required(ErrorMessage = "Please enter Description")]
- [DataType(DataType.MultilineText)]
- public string Description { get; set; }
-
- public List<SelectListItem> ListeOfCountries { get; set; }
-
- }
Create a controller
Now, we are going to create a Controller. Right-click on the controllers folder> > Add >> Controller>> selecting MVC 5 Controller - Empty>> click Add. In the next dialog, name the controller as ResumeController and then click Add.
ResumeController.cs
Here, we should provide all the needed personal information such as first name, last name, date of birth, and nationality.
We have created two actions - personal information with httpGet which is used to get personal information view and another personal information action with httpPost that is responsible to add our object into person table.
- [HttpGet]
- public ActionResult PersonnalInformtion(PersonVM model)
- {
-
- List<SelectListItem> nationality = new List<SelectListItem>()
- {
- new SelectListItem { Text = "Morocco", Value = "Morocco", Selected = true},
- new SelectListItem { Text = "India", Value = "India"},
- new SelectListItem { Text = "Spain", Value = "Spain"},
- new SelectListItem { Text = "USA", Value = "USA"},
- };
-
-
-
- List<SelectListItem> educationalLevel = new List<SelectListItem>()
- {
- new SelectListItem { Text = "Hight School", Value = "Hight School", Selected = true},
- new SelectListItem { Text = "Diploma", Value = "Diploma"},
- new SelectListItem { Text = "Bachelor's degree", Value = "Bachelor's degree"},
- new SelectListItem { Text = "Master's degree", Value = "Master's degree"},
- new SelectListItem { Text = "Doctorate", Value = "Doctorate"},
- };
-
- model.ListNationality = nationality;
- model.ListEducationalLevel = educationalLevel;
-
- return View(model);
- }
-
- [HttpPost]
- [ActionName("PersonnalInformtion")]
- public ActionResult AddPersonnalInformtion(PersonVM person)
- {
-
- if(ModelState.IsValid)
- {
-
- Mapper.Initialize(cfg => cfg.CreateMap<PersonVM, Person>());
-
- Person personEntity = Mapper.Map<Person>(person);
-
- HttpPostedFileBase file = Request.Files["ImageProfil"];
-
- bool result = _resumeRepository.AddPersonnalInformation(personEntity, file);
-
- if(result)
- {
- Session["IdSelected"] = _resumeRepository.GetIdPerson(person.FirstName, person.LastName);
- return RedirectToAction("Education");
- }
- else
- {
- ViewBag.Message = "Something Wrong !";
- return View(person);
- }
-
- }
-
- ViewBag.MessageForm = "Please Check your form before submit !";
- return View(person);
-
- }
Here, we are using education to provide all the details. As you can see below, the education form has several fields, such as institute/university, Title of diploma, degree, etc.
We have created two actions to achieve that - education which is decorated with httpGet in order to display our education form via partial view, then education action with httpPost which will persist our education object into educations table.
- [HttpGet]
- public ActionResult Education(EducationVM education)
- {
- return View();
- }
-
- [HttpPost]
- public ActionResult AddOrUpdateEducation(EducationVM education)
- {
- string msg = string.Empty;
-
- if(education != null)
- {
-
- Mapper.Initialize(cfg => cfg.CreateMap<EducationVM, Education>());
- Education educationEntity = Mapper.Map<Education>(education);
-
- int idPer = (int)Session["IdSelected"];
-
- msg = _resumeRepository.AddOrUpdateEducation(educationEntity, idPer);
-
- }
- else
- {
- msg = "Please re try the operation";
- }
-
- return Json(new { data = msg }, JsonRequestBehavior.AllowGet);
- }
-
- [HttpGet]
- public PartialViewResult EducationPartial(EducationVM education)
- {
-
- education.ListOfCountry = GetCountries();
-
- return PartialView("~/Views/Shared/_MyEducation.cshtml", education);
- }
Now, we need to add user work experiences. To do that, we have created work experience action to get our View which is absolutely decorated with httpGet, then work experience action with httpPost that is responsible to add all the data of work experience into work exp table.
- [HttpGet]
- public ActionResult WorkExperience()
- {
- return View();
- }
-
- public PartialViewResult WorkExperiencePartial(WorkExperienceVM workExperience)
- {
- workExperience.ListeOfCountries = GetCountries();
-
- return PartialView("~/Views/Shared/_MyWorkExperience.cshtml", workExperience);
- }
-
- public ActionResult AddOrUpdateExperience(WorkExperienceVM workExperience)
- {
-
- string msg = string.Empty;
-
- if (workExperience != null)
- {
-
- Mapper.Initialize(cfg => cfg.CreateMap<WorkExperienceVM, WorkExperience>());
- WorkExperience workExperienceEntity = Mapper.Map<WorkExperience>(workExperience);
-
- int idPer = (int)Session["IdSelected"];
-
-
- msg = _resumeRepository.AddOrUpdateExperience(workExperienceEntity, idPer);
-
- }
- else
- {
- msg = "Please re try the operation";
- }
-
- return Json(new { data = msg }, JsonRequestBehavior.AllowGet);
- }
Finally, we are going to add the code snippet for skills, certifications, and languages.
For skills
- [HttpGet]
- public ActionResult SkiCerfLang()
- {
- return View();
- }
-
- public PartialViewResult SkillsPartial()
- {
- return PartialView("~/Views/Shared/_MySkills.cshtml");
- }
-
- public ActionResult AddSkill(SkillsVM skill)
- {
- int idPer = (int)Session["IdSelected"];
- string msg = string.Empty;
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<SkillsVM, Skill>());
- Skill skillEntity = Mapper.Map<Skill>(skill);
-
- if (_resumeRepository.AddSkill(skillEntity, idPer))
- {
- msg = "skill added successfully";
- }
- else
- {
- msg = "something Wrong";
- }
-
- return Json(new { data = msg}, JsonRequestBehavior.AllowGet);
- }
For certifications
- public PartialViewResult CertificationsPartial(CertificationVM certification)
- {
- List<SelectListItem> certificationLevel = new List<SelectListItem>()
- {
- new SelectListItem { Text = "Beginner", Value = "Beginner", Selected = true},
- new SelectListItem { Text = "Intermediate", Value = "Intermediate"},
- new SelectListItem { Text = "Advanced", Value = "Advanced"}
- };
-
- certification.ListOfLevel = certificationLevel;
-
- return PartialView("~/Views/Shared/_MyCertifications.cshtml", certification);
- }
-
- public ActionResult AddCertification(CertificationVM certification)
- {
- int idPer = (int)Session["IdSelected"];
- string msg = string.Empty;
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<CertificationVM, Certification>());
- Certification certificationEntity = Mapper.Map<Certification>(certification);
-
- if (_resumeRepository.AddCertification(certificationEntity, idPer))
- {
- msg = "Certification added successfully";
- }
- else
- {
- msg = "something Wrong";
- }
-
- return Json(new { data = msg }, JsonRequestBehavior.AllowGet);
- }
For languages
- public PartialViewResult LanguagePartial(LanguageVM language)
- {
- List<SelectListItem> languageLevel = new List<SelectListItem>()
- {
- new SelectListItem { Text = "Elementary Proficiency", Value = "Elementary Proficiency", Selected = true},
- new SelectListItem { Text = "LimitedWorking Proficiency", Value = "LimitedWorking Proficiency"},
- new SelectListItem { Text = "Professional working Proficiency", Value = "Professional working Proficiency"},
- new SelectListItem { Text = "Full Professional Proficiency", Value = "Full Professional Proficiency"},
- new SelectListItem { Text = "Native Or Bilingual Proficiency", Value = "Native Or Bilingual Proficiency"}
- };
-
- language.ListOfProficiency = languageLevel;
-
- return PartialView("~/Views/Shared/_MyLanguage.cshtml", language);
- }
-
- public ActionResult AddLanguage(LanguageVM language)
- {
- int idPer = (int)Session["IdSelected"];
- string msg = string.Empty;
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<LanguageVM, Language>());
- Language languageEntity = Mapper.Map<Language>(language);
-
- if (_resumeRepository.AddLanguage(languageEntity, idPer))
- {
- msg = "Language added successfully";
- }
- else
- {
- msg = "something Wrong";
- }
-
- return Json(new { data = msg }, JsonRequestBehavior.AllowGet);
- }
To generate our resume, we are going to add the following actions.
- public ActionResult CV()
- {
- return View();
- }
GetPersonnalInfoPartial
- public PartialViewResult GetPersonnalInfoPartial()
- {
- int idPer = (int)Session["IdSelected"];
- Person person = _resumeRepository.GetPersonnalInfo(idPer);
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<Person, PersonVM>());
- PersonVM personVM = Mapper.Map<PersonVM>(person);
-
- return PartialView("~/Views/Shared/_MyPersonnalInfo.cshtml", personVM);
- }
GetEducationCVPartial
- public PartialViewResult GetEducationCVPartial()
- {
- int idPer = (int)Session["IdSelected"];
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<Education, EducationVM>());
- IQueryable<EducationVM> educationList = _resumeRepository.GetEducationById(idPer).ProjectTo<EducationVM>().AsQueryable();
-
- return PartialView("~/Views/Shared/_MyEducationCV.cshtml", educationList);
- }
WorkExperienceCVPartial
- public PartialViewResult WorkExperienceCVPartial()
- {
- int idPer = (int)Session["IdSelected"];
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<WorkExperience, WorkExperienceVM>());
- IQueryable<WorkExperienceVM> workExperienceList = _resumeRepository.GetWorkExperienceById(idPer).ProjectTo<WorkExperienceVM>().AsQueryable();
-
-
- return PartialView("~/Views/Shared/_WorkExperienceCV.cshtml", workExperienceList);
- }
SkillsCVPartial
- public PartialViewResult SkillsCVPartial()
- {
- int idPer = (int)Session["IdSelected"];
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<Skill, SkillsVM>());
- IQueryable<SkillsVM> skillsList = _resumeRepository.GetSkillsById(idPer).ProjectTo<SkillsVM>().AsQueryable();
-
-
- return PartialView("~/Views/Shared/_MySkillsCV.cshtml", skillsList);
- }
CertificationsCVPartial
- public PartialViewResult CertificationsCVPartial()
- {
- int idPer = (int)Session["IdSelected"];
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<Certification, CertificationVM>());
- IQueryable<CertificationVM> certificationList = _resumeRepository.GetCertificationsById(idPer).ProjectTo<CertificationVM>().AsQueryable();
-
-
- return PartialView("~/Views/Shared/_MyCertificationCV.cshtml", certificationList);
- }
LanguageCVPartial
- public PartialViewResult LanguageCVPartial()
- {
- int idPer = (int)Session["IdSelected"];
-
-
- Mapper.Initialize(cfg => cfg.CreateMap<Language, LanguageVM>());
- IQueryable<LanguageVM> languageList = _resumeRepository.GetLanguageById(idPer).ProjectTo<LanguageVM>().AsQueryable();
-
-
- return PartialView("~/Views/Shared/_MyLanguageCV.cshtml", languageList);
- }
That’s all. Please send your feedback and queries in the comments box.