In my previous article I already explained about the basic background of ASP.Net MVC application, here we will see the implementation of each of them.
Let’s first create an empty Asp.Net MVC solution named as “MVCDemo”
Here we will be using Entity framework to connect with database, fetch/add the data into the database
In Entity framework we can follow one of these three approaches
· Database First approach – Create database with tables, columns, relations etc. and Entity framework will generates corresponding Model classes (Business entities) and Data Access Layer code.
· Model First approach – In this approach Model classes and relationship between them will be defined manually using Model designer in Visual studio and Entity Framework will generate Data Access Layer and Database with tables, columns, relations automatically.
· Code First approach – In this approach manually Plain Old CLR object classes will be created. Relationship between those classes will be defined by means of code. When application executes for the first time Entity framework will generate Data Access Layer and Database with tables, column and relations automatically in the database server.
Right click the project — > Manage Nuget packages. Search for Entity Framework and click on install.
Now we will be creating the data access layer. Create a folder named as “DAL” within the solution
Within the folder we will be creating a class named as “EmployeeDAL”, below is the code:
namespace MVCDemo.DAL
{
public class EmployeeDAL : DbContext
{
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>().ToTable("Employee");
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
}
In web.config we will have to mention the connection string, the name attribute value will be same as DAL class name:
<connectionStrings>
<add connectionString="Data Source=PC258340;Initial Catalog=EmployeeDB;Integrated Security=True" name="EmployeeDAL" providerName="System.Data.SqlClient"/>
</connectionStrings>
Here is my Employee class within a newly created folder named as “Model”
[Table("Employee", Schema = "dbo")]
public class Employee
{
[Key]
public int EmployeeId { get; set; }
[FirstNameValidation]
public string FirstName { get; set; }
[StringLength(15, ErrorMessage = "Last Name length should not be greater than 15")]
public string LastName { get; set; }
[Range(typeof(int), "50000", "500000", ErrorMessage = "Put a proper Salary value between 50000 and 500000")]
[Required(ErrorMessage = "This is a required field")]
public int? Salary { get; set; }
}
Run the application & call the below piece of code will be creating the EmployeeDB database, Employee table automatically
EmployeeBusinessLayer empBusiness = new EmployeeBusinessLayer();
empBusiness. GetEmployees();
For adding record to the table use the following script:
SET IDENTITY_INSERT [dbo].[Employee] ON
INSERT [dbo].[Employee] ([EmployeeId], [FirstName], [LastName], [Salary]) VALUES (1, N'Tarun1 ', N'Chatterjee1', 100000)
INSERT [dbo].[Employee] ([EmployeeId], [FirstName], [LastName], [Salary]) VALUES (2, N'Tarun2', N'Chatterjee2', 200000)
INSERT [dbo].[Employee] ([EmployeeId], [FirstName], [LastName], [Salary]) VALUES (3, N'Tarun3', N'Chatterjee3', 300000)
SET IDENTITY_INSERT [dbo].[Employee] OFF
Under the Model folder we will be creating 3 more models:
UserDetails models will be for user authentication only
namespace MVCDemo.Models
{
public class UserDetails
{
[StringLength(7, MinimumLength = 2, ErrorMessage = "UserName length should be between 2 and 7")]
public string UserName { get; set; }
public string Password { get; set; }
}
}
EmployeeBusinessLayer model is to Get/Save the employee to the database by using the entity framework. EditEmployee method will not be referred anywhere but I have given it to show how we can edit the data into the database using entity framework.
namespace MVCDemo.Models
{
public class EmployeeBusinessLayer
{
public List<Employee> GetEmployees()
{
EmployeeDAL empDal = new EmployeeDAL();
return empDal.Employees.ToList();
}
public Employee SaveEmployee(Employee e)
{
EmployeeDAL empDal = new EmployeeDAL();
empDal.Employees.Add(e);
empDal.SaveChanges();
return e;
}
public int EditEmployee()
{
Employee emp;
int num = 0;
using (var ctx = new EmployeeDAL())
{
emp = (from e in ctx.Employees
where e.EmployeeId == 4
select e).FirstOrDefault();
}
if(emp != null)
{
emp.Salary = 400000;
emp.FirstName = "Tarun4";
emp.LastName = "Chatterjee4";
}
using (var ctx = new EmployeeDAL())
{
ctx.Entry(emp).State = System.Data.Entity.EntityState.Modified;
num = ctx.SaveChanges();
}
return num;
}
public bool IsValidUser(UserDetails u)
{
if (u.UserName == "Admin" && u.Password == "Admin")
{
HttpContext.Current.Session["IsAdmin"] = true;
return true;
}
else if(u.UserName=="tarun" && u.Password=="chatterjee")
{
HttpContext.Current.Session["IsAdmin"] = false;
return true;
}
else
{
HttpContext.Current.Session["IsAdmin"] = true;
return false;
}
}
}
}
//FirstNameValidation model is to define the model object & custom validation
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
namespace MVCDemo.Models
{
public class FirstNameValidation : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null) // Checking for Empty Value
{
return new ValidationResult("Please Provide First Name");
}
return ValidationResult.Success;
}
}
[Table("Employee", Schema = "dbo")]
public class Employee
{
[Key]
public int EmployeeId { get; set; }
[FirstNameValidation]
public string FirstName { get; set; }
[StringLength(15, ErrorMessage = "Last Name length should not be greater than 15")]
public string LastName { get; set; }
[Range(typeof(int), "50000", "500000", ErrorMessage = "Put a proper Salary value between 50000 and 500000")]
[Required(ErrorMessage = "This is a required field")]
public int? Salary { get; set; }
}
}
//Here is my RouteConfig code
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Employee", action = "Index", id = UrlParameter.Optional }
);
}
Now we will be creating CustomFilters. First we will be creating a folder named as “CustomFilters” within the solution
First we will be creating a CustomActionFilter which will be inherited from ActionFilterAttribute
The base ActionFilterAttribute class has the following methods that you can override:
OnActionExecuting – This method is called before a controller action is executed.
OnActionExecuted – This method is called after a controller action is executed.
OnResultExecuting – This method is called before a controller action result is executed.
OnResultExecuted – This method is called after a controller action result is executed.
For example, you might want to create profiling which will log the execution time, method name etc.
Here is the code snippet
namespace MVCDemo.CustomFilters
{
public class CustomActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// First it is executed then going to Home Controller Index
filterContext.Controller.ViewBag.CustomActionMessage1 = "Custom Action Filter: Message from OnActionExecuting method.";
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//After Home Controller Index execution it will be triggered
filterContext.Controller.ViewBag.CustomActionMessage2 = "Custom Action Filter: Message from OnActionExecuted method.";
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
//After OnActionExecuted execution it will be triggered
filterContext.Controller.ViewBag.CustomActionMessage3 = "Custom Action Filter: Message from OnResultExecuting method.";
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//After controller data bind to the View it will be triggered
filterContext.Controller.ViewBag.CustomActionMessage4 = "Custom Action Filter: Message from OnResultExecuted method.";
}
}
}
//Let’s create a CustExceptionFilter in order to track the actual exception occurred
namespace MVCDemo.CustomFilters
{
public class CustExceptionFilter : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
// Used to log the exception message
filterContext.Controller.ViewBag.ExceptionMessage = "Custom Exception: Message from OnException method.";
}
}
}
//We want to create a CustAuthFilter in order to implement a custom authentication system.
namespace MVCDemo.CustomFilters
{
public class CustAuthFilter : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (Convert.ToBoolean(filterContext.HttpContext.Session["IsAdmin"]))
{
filterContext.Result = new ContentResult()
{
Content = "Unauthorized to access specified resource"
};
}
}
}
}
Now we will be creating the controller classes
Login purpose we will having AuthenticationController, below is the code snippet
namespace MVCDemo.Controllers
{
[AllowAnonymous]
public class AuthenticationController : Controller
{
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Login");
}
// GET: Authentication
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult DoLogin(UserDetails u)
{
if (ModelState.IsValid)
{
EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
if (bal.IsValidUser(u))
{
FormsAuthentication.SetAuthCookie(u.UserName, false);
return RedirectToAction("Index", "Employee");
}
else
{
ModelState.AddModelError("CredentialError", "Invalid Username or Password");
return View("Login");
}
}
else
{
return View("Login");
}
}
}
}
DoLogin method is responsible to check if login user is valid or not, according it will redirect the user in Employee View or else redirect to the same login page with error message
Home Controller is mainly used to check how action filter action attributes are working. Here is my Home controller code snippet.
namespace MVCDemo.Controllers
{
[CustAuthFilter]
public class HomeController : Controller
{
[CustExceptionFilter]
[CustomActionFilter]
[Authorize]
[CustAuthFilter]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View("Index");
}
[OutputCache(Duration = 10)]
public ActionResult OutPutTest()
{
ViewBag.Date = DateTime.Now.ToString("T");
return View();
}
}
}
EmployeeController is being used to display the employee details from database & saving the employee into the database
namespace MVCDemo.Controllers
{
public class EmployeeController : Controller
{
[NonAction]
public string SimpleMethod()
{
return "Hi, this is a no action method";
}
[Authorize]
[CustAuthFilter]
public ActionResult Index()
{
EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
employeeListViewModel.UserName = User.Identity.Name; //New Line
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
List<Employee> employees = empBal.GetEmployees();
List<EmployeeViewModel> empViewModels = new List<EmployeeViewModel>();
foreach (Employee emp in employees)
{
EmployeeViewModel empViewModel = new EmployeeViewModel();
empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
empViewModel.Salary = emp.Salary.Value.ToString("C");
if (emp.Salary > 15000)
{
empViewModel.Font = "large";
}
else
{
empViewModel.Font = "medium";
}
empViewModels.Add(empViewModel);
}
employeeListViewModel.Employees = empViewModels;
return View("Index", employeeListViewModel);
}
public ActionResult AddNew()
{
return View("CreateEmployee", new CreateEmployeeViewModel());
}
public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
switch (BtnSubmit)
{
case "Save Employee":
if (ModelState.IsValid)
{
EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
empBal.SaveEmployee(e);
return RedirectToAction("Index");
}
else
{
CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
vm.FirstName = e.FirstName;
vm.LastName = e.LastName;
if (e.Salary.HasValue)
{
vm.Salary = e.Salary.ToString();
}
else
{
vm.Salary = ModelState["Salary"].Value.AttemptedValue;
}
return View("CreateEmployee", vm);
}
case "Cancel":
return RedirectToAction("Index");
}
return new EmptyResult();
}
}
}
Now, we will be creating the View Models. I already defined in my previous article that View models we will be directly bind to the View & it will work as a wrapper of actual view model. Please follow my previous article to know about the benefit of using viewmodel rather view.
All the viewmodel classes will be creating under the ViewModels folder
Here is my EmployeeViewModel:
namespace MVCDemo.ViewModels
{
public class EmployeeViewModel
{
public string EmployeeName { get; set; }
public string Salary { get; set; }
public string Font { get; set; }
}
}
EmployeeListViewModel will be like
namespace MVCDemo.ViewModels
{
public class EmployeeListViewModel
{
public List<EmployeeViewModel> Employees { get; set; }
public string UserName { get; set; }
}
}
CreateEmployeeViewModel will be like:
namespace MVCDemo.ViewModels
{
public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Salary { get; set; }
}
}
Code snippet of Shared -- >_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title - My ASP.NET MVC Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/Site.css" rel="stylesheet" />
</head>
<body>
<div id="body">
@RenderBody()
</div>
@RenderSection("Scripts", required: false)
</body>
</html>
Code snippet of Home -- > OutPutTest.cshtml
@{
ViewBag.Title = "OutPutTest";
}
<h2>OutPutTest</h2>
<h3>@ViewBag.Date</h3>
Code snippet of Home -- > Index.cshtml
@{
ViewBag.Title = "Home Page";
}
<h2>Output Messages :</h2>
<br />
<h3>@ViewBag.AutherizationMessage</h3>
<br />
<h3>@ViewBag.CustomActionMessage1</h3>
<br />
<h3>@ViewBag.CustomActionMessage2</h3>
<br />
<h3>@ViewBag.CustomActionMessage3</h3>
<br />
<h3>@ViewBag.CustomActionMessage4</h3>
<br />
<h3>@ViewBag.ExceptionMessage</h3>
Code snippet of Employee-- > Index.cshtml
@using MVCDemo.ViewModels
@model EmployeeListViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>MyView</title>
</head>
<body>
<div style="text-align:right">
Hello, @Model.UserName
<a href="/Authentication/Logout">Logout</a>
</div>
<hr />
<a href="/Employee/AddNew">Add New</a>
<div>
<table border="1" width="50%">
<tr>
<th>Employee Name</th>
<th>Salary</th>
</tr>
@foreach (EmployeeViewModel item in Model.Employees)
{
<tr>
<td>@item.EmployeeName</td>
<td style= "font-size:@item.Font">@item.Salary</td>
</tr>
}
</table>
</div>
</body>
</html>
Code snippet of Employee-- > CreateEmployee.cshtml
@using MVCDemo.ViewModels
@model CreateEmployeeViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>CreateEmployee</title>
<script>
function ResetForm() {
document.getElementById('TxtFName').value = "";
document.getElementById('TxtLName').value = "";
document.getElementById('TxtSalary').value = "";
}
</script>
</head>
<body>
<div>
<form action="/Employee/SaveEmployee" method="post" id="EmployeeForm">
<table>
<tr>
<td>
First Name:
</td>
<td>
<input type="text" id="TxtFName" name="FirstName" value="@Model.FirstName" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("FirstName")
</td>
</tr>
<tr>
<td>
Last Name:
</td>
<td>
<input type="text" id="TxtLName" name="LastName" value="@Model.LastName" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("LastName")
</td>
</tr>
<tr>
<td>
Salary:
</td>
<td>
<input type="text" id="TxtSalary" name="Salary" value="@Model.Salary" />
</td>
</tr>
<tr>
<td colspan="2" align="right">
@Html.ValidationMessage("Salary")
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name="BtnSubmit" value="Save Employee" />
<input type="submit" name="BtnSubmit" value="Cancel" />
<input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
Code snippet of Authentication-- > Login.cshtml
@model MVCDemo.Models.UserDetails
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
<script src="~/Scripts/jquery-1.8.0.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
<div>
@Html.ValidationMessage("CredentialError", new { style = "color:red;" })
@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{
<table >
<tr style="border:thin">
<td>
@Html.LabelFor(c => c.UserName)
</td>
<td>
@Html.TextBoxFor(x => x.UserName)
@Html.ValidationMessageFor(x => x.UserName)
</td>
</tr>
<tr style="border:thin">
<td>
@Html.LabelFor(c => c.Password)
</td>
<td>
@Html.PasswordFor(x => x.Password)
</td>
</tr>
<tr style="border:none">
<td>
<input type="submit" name="BtnSubmit" value="Login" />
</td>
<td></td>
</tr>
</table>
}
</div>
</body>
</html>
Now build the solution and run
Give the username as tarun & password as chatterjee & click on Login
It will redirect the user in employee index page with employee details form the database
Click on Add new button & it will redirect the user to CreateEmployee view
Fill up the details and Save
Now click on Logout and login with user name & Password as Admin/Admin
Now login by tarun/chatterjee
After 10 second press F5 then value will be refreshed only
Now execute Home/Index action method, it will show the custom action execution message
Happy Coding
Tarun Kumar Chatterjee
Leave a comment