Dot Net Notes
Dot Net Notes
Memory,
Garbage collection {it is used to destroy the memory forcefully, which is used mainly
in for Heap memory management.
Example-
ABC obj;
(This type of object define/store in Stack Memory),
ASP.NET is just tech. that runs on the web server and use for web development.
Server— use for user managements.
Web server—it is use for manage and run the web application.
1. IIS (Web server)—Internet information Server, it work/ install only on Microsoft server.
2. KESTRAL—run on MS server and non-MS server.
Database – handling
Int (4 bytes)
BigInt (8 bytes)
VARCHAR (8000-max character) – stores up to sky value and also use for store the non-Unicode values.
VARCHAR(MAX) (2GB max)
NVARCHAR (4000 max character) – use for stores the Unicode values. Means there are include the
different language character. [N -> national]
NVARCHAR (2GB)
VHARCHAR (variable length) – it always takes +1 or +2 extra bytes after fixed length.
It takes +1 extra bytes when the size of VARCHAR is from 0 – 255.
It takes +2 extra bytes when the size of VARCHAR is greater than >255.
In MS SQL SERVER the max no. of column in table are 1024.
1024 column are called non-sparse column.
Above the 2008 version of MS SQL Server, the sparse column introduced with max column size 30,000.
(The spares column is used when the max no. of column is null. It auto reduces the size of column/ table up
to 40%.)
Web.config --- XML base file ( it is use for connection string because this file is no need for complication)
<add name=”cn” connectionString=” server = dev\sqlexpress; database = dbemply; integrated security = true” />
</connectionStrings>
using System.Data;
using System.Data.SqlClient; (work only with MS SQL Server)
using System.Configuration;
con.ConnectionString = ConfigurationManager.ConnectionStrings["stdKeyId"].ConnectionString;
if (con.State == ConnectionState.Closed)
{
con.Open(); enumeration (constant type)
}
}
[inline queries]
cmd.Connection = con;
cmd.Parameters.AddWithValue("@stdid", TxtId.Text);
cmd.Parameters.AddWithValue("@stdname", TxtName.Text);
cmd.Parameters.AddWithValue("@stdclass", TxtClass.Text); [jitne parameter hote hai
utne hi type honge yanha]
cmd.Parameters.AddWithValue("@stdsub", TxtSub.Text);
cmd.ExecuteNonQuery();
cmd.Dispose(); [it free the resource of the SQL Command]
TxtId.Text = “ “; not use the space because space work as character.
TxtId.Text = string.Empty;
TxtName.Text = string.Empty;
TxtClass.Text = string.Empty;
TxtSub.Text = string.Empty;
TxtId.Focus();
Display_Refactor();
[use to display the data, it can only read and forward the data, it is the
fastest way of data retrieve process]
stdDataReader = cmd.ExecuteReader();
ListBox1.DataTextField = "stdName";
ListBox1.DataValueField = "stdId";
ListBox1.DataSource = stdDataReader;
ListBox1.DataBind();
stdDataReader.Close();
cmd.Dispose();
}
ADO.NET is a data access technology from the Microsoft. NET Framework that provides communication between
relational and non-relational systems through a common set of components. ADO.NET is a set of computer software
components that programmers can use to access data and data services from a database.
protected void
ShowList_SelectedIndexChanged
(object sender, EventArgs e)
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from teacher_table where
TeacherID = @teachid";
cmd.Connection = conn;
use for run the SQL command
cmd.Parameters.AddWithValue("@teachid",
ShowList.SelectedValue);
SqlDataReader teachReader = cmd.ExecuteReader();
iska reference yanha store hoga
if (teachReader.HasRows)
{
teachReader.Read();
TextId.Text = teachReader["TeacherID"].ToString();
TextName.Text = teachReader["TeacherName"].ToString();
TextSub.Text = teachReader["TeacherSubject"].ToString();
TextDep.Text = teachReader["TeacherDept"].ToString();
}
teachReader.Close();
cmd.Dispose();
}
protected void
Delete_btn_Click(object
sender, EventArgs e)
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "delete from student_table where
stdRoll=@stdid";
cmd.Connection = conn;
cmd.Parameters.AddWithValue("@stdid", Textroll.Text);
cmd.ExecuteNonQuery();
cmd.Dispose();
dis_refactor();
clr_refactor();
}
The DELETE statement is used when we want to remove some or all of the records from the table, while the
TRUNCATE statement will delete entire rows from a table.
Master table - The table where the data enter/ change sometimes only.
Transition table - The table where the data change frequently.
Exa-
Country table, state table, city table, registration code.
SELECT regnam,regadd,regeml,cntnam,stanam,ctynam from tbreg,tbcty,tbsta,tbcnt where
regctycod,regctycod = ctycod and ctystacod = stacod and statntcod = cntcod
3-Tier Architecture => Database Tier Middle Tier/Business Tier Presentation Tier
(Use OOPs concept)
Model (Classes, Database Tier), Controller (Classes, Request handler), View ( UI)
It follows the loosely coupled technique.
There are use HTML helpers.
</connectionStrings>
namespace mvc_database_create_edit.Models
{
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string Class { get; set; }
public int Age { get; set; }
}
} use for write only
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace mvc_database_create_edit.Models
{
public class ApplicationContext:DbContext
{
public ApplicationContext() :base("ConString")
{
}
public DbSet<Student> Students { get; set; }
}
}
Controller StudentCtrController
using mvc_database_create_edit.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace mvc_database_create_edit.Controllers
{
public class StudentCtrController : Controller
{
// GET: StudentCtr (it’s value change only in constructor, but const value don’t change
anywhere)
It is a single line declaration and initialization variable and can store any type of data. It is
use only in local members and decide the data types at compile time.
}
}
View (auto generate folder when the controller is created) add view (same name of view as the Action name
(Index)) Index Template (List) modelClass
@{
ViewBag.Title = "Index";
}
<p>
@Html.ActionLink("Create New", "Create")
</p>
@if (!Model.Any())
{
<p class="text-danger">No Record Found!</p>
}
else
{
<table class="table">
<thead>
<tr>
<th> (lambda expression)
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Class)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th></th>
</tr>
</thead>
<tbody> (it decide the data type of item at compile time)
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Class)
</td>
<td>
@Html.DisplayFor(modelItem => item.Age)
</td>
<td
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { id = item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</tbody>
</table>
}
Routes
For using the attribute base routing, firstly add this line in the RouteConfig file.
This line is written on the action method where the routing applies. This is written in Controller file.
Route is just a pattern.
This is the prefix for route pattern. It must be included in front of route and it written in starting at
controller.
These are the constraints which are used in attributes base routing. Where {a} and {b} are parameters.
New Application
Step-:
7) Add Controller
8) Make Action Link in View Shared
9) Index.cshtml
13) Write the coding in controller of server-side validation and show the created data in table
Server-side validation
17) Now create the Edit View and also include the script section and Back to List link
18) Write the Update code with E-mail validation check-
19) Write the code of Details Action and add its View
View
Ternary Operator (this condition can be
performed by the simple If Else condition
as shown below image)
21) Write click on Project Name and add a new folder CustomValidation add class AgeValidation
22) Write the code of Age Validation in class AgeValidation and use it in Student class
23) Write the validation for email add class CustomValidation EmailValidation and its code and use in
Student class
Layout
24) Download the bootstrap theme and paste these in Content Folder
26) Now copy the layout.cshtml file 2 time in same place and change the name of file and also change the
name of @Styles.Render("~/MyContent1/css"),@Styles.Render("~/MyContent2/css")
same as the name of BundleConfig file.
28) This path and the bootstrap file name add where there you want to apply the bootstrap theme
Partial View
30) The Partial View is created once in Shared View and use anywhere in the project
Go to Shared View Right click add view choose partial view
Name must be start with
31) Write the code at here which we want to write many times in the project
Exa.
Now call this file anywhere with 3 types
i) In Index.cshtml @Html.Partial("_PartialView")
ii) In Index.cshtml @{ Html.RenderPartial("_PartialView");}
iii) Make a Action/Method in HomeController and call this file at here
Step: -
1) Install Entity Frmaework
2) Make a connection String
<connectionStrings>
<add name="conStr" connectionString="server=.\sqlexpress; database=MVCDbNewProject; integrated
security=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MVCentityFrameworkNewProject.Models
{
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MVCentityFrameworkNewProject.Models
{
public class Designation
{
public int Id { get; set; }
public string Name { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace MVCentityFrameworkNewProject.Models
{
public class Employee
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Address { get; set; }
public int Salary { get; set; }
[Required]
[Display(Name="Department")]
public int DepartmentId {get; set;}
public Department Department { get; set; }
[Display(Name = "Designation")]
public int DesignationId { get; set; }
public Designation Designation { get; set; }
}
}
using MVCentityFrameworkNewProject.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Drawing.Printing;
using System.Linq;
using System.Web;
namespace MVCentityFrameworkNewProject.Data
{
public class ApplicationDbContext:DbContext
{
public ApplicationDbContext(): base("conStr")
{
}
public DbSet<Department> Departments { get; set; }
public DbSet<Designation> Designations { get; set; }
public DbSet<Employee> Employees { get; set; }
}
}
enable-migrations
add-migrations initLoad
this command creates a file
namespace MVCentityFrameworkNewProject.Migrations
{
using System;
using System.Data.Entity.Migrations;
CreateTable(
"dbo.Designations",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Employees",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false),
Address = c.String(nullable: false),
Salary = c.Int(nullable: false),
DepartmentId = c.Int(nullable: false),
DesignationId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Departments", t => t.DepartmentId, cascadeDelete: true)
.ForeignKey("dbo.Designations", t => t.DesignationId, cascadeDelete: true)
.Index(t => t.DepartmentId)
.Index(t => t.DesignationId);
it makes the code able for that when the data change in the parent class then the child data will
be automatically change
update-database
8) Now for Enter the dummy/raw data into the database of Department and
Designation table, run a empty migration command with any name
add-migration addDatatoDb
This command creates a file and, in this file, there are write some SQL
command for insert the dummy data
namespace MVCentityFrameworkNewProject.Migrations
{
using System;
using System.Data.Entity.Migrations;
// Designation
Sql("insert Designations values('ProgramManager')");
Sql("insert Designations values('TechinicalLeader')");
Sql("insert Designations values('Programer')");
}
namespace MVCentityFrameworkNewProject.Controllers
{
public class EmployeeCtlController : Controller
{
private readonly ApplicationDbContext context;
public EmployeeCtlController()
{
context = new ApplicationDbContext();
}
@model IEnumerable<MVCentityFrameworkNewProject.Models.Employee>
@if (!Model.Any())
{
<h3 class="text-danger">No record found!</h3>
}
else
{
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Salary</th>
<th>Departments</th>
<th>Designation</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var employee in Model)
{
<tr>
<td>@employee.Name </td>
<td>@employee.Address </td>
<td>@employee.Salary </td>
<td>@employee.Department.Name </td>
<td>@employee.Designation.Name </td>
<td>
@Html.ActionLink("Edit", "Upsert", "EmployeeCtl",new { id = employee.Id }, new { @class = "btn btn-primary" })
@Html.ActionLink("Details", "Details", "EmployeeCtl", new { @class = "btn btn-primary" })
<input type="submit" value="Delete" class="btn btn-danger" onclick="return confirm('Want to Delete')" />
</td>
</tr>
}
</tbody>
</table>
}
ViewData["depList"] = context.Departments.ToList();
ViewData["desList"] = context.Designations.ToList();
(It works as to pass the data from Action to View and get data from multiple tables and
there is need for type casting in its view or where the table data show/put/post)
// Create
if (id == null) return View(employee);
//Edit
employee = context.Employees.Include(e => e.Department).Include(e =>
e.Designation).FirstOrDefault(e => e.Id == id);
if (employee == null) return HttpNotFound();
return View(employee);
}
@model MVCentityFrameworkNewProject.Models.Employee
@using MVCentityFrameworkNewProject.Models (this line is write because we use the 2 different model/table
(Department,Designation) in the below code )
@{
ViewBag.Title = "Upsert";
var title = Model.Id != 0 ? "Edit Employee Details" : "Add New Employee";
}
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text text-danger" })
<div class="row">
<div class="form-group">
@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Name, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.Address)
@Html.TextBoxFor(m => m.Address, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Address, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.Salary)
@Html.TextBoxFor(m => m.Salary, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Salary, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m=>m.DepartmentId)
@Html.DropDownListFor(m=>m.DepartmentId,new SelectList(ViewData["depList"] as List<Department>,
"Id","Name"),"Select Your Department", new {@class="form-control"})
@Html.ValidationMessageFor(m=>m.DepartmentId,"", new {@class="text-danger"})
</div>
<div class="form-group">
@Html.LabelFor(m => m.DesignationId)
@Html.DropDownListFor(m => m.DesignationId, new SelectList(ViewData["desList"] as List<Designation>,
"Id", "Name"), "Select Your Designation", new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DesignationId, "", new { @class = "text-danger" })
</div>
<div class="form-group">
<button type="submit" class="btn btn-success">
@(Model.Id != 0 ? "Update" : "Save")
(this ternary condition is use for auto select the name of button (Save/Update), when the id is
0 then display the “Save” else “Update” button )
</button>
</div>
</div>
}
@Html.ActionLink("Back to List!","Index")
@section scripts{
@Scripts.Render("~/bundles/jqueryval")
}
14) Now write the code/create the action for Save and Update into
single Action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upsert(Employee employee)
{
if (employee == null) return HttpNotFound();
if (!ModelState.IsValid) (server side validation)
{
ViewData["depList"] = context.Departments.ToList();
ViewData["desList"] = context.Designations.ToList();
View(employee);
}
// Save
if (employee.Id == 0) context.Employees.Add(employee);
else
{
//Update
var employeeInDb = context.Employees.Find(employee.Id);
if (employeeInDb == null) return HttpNotFound();
employeeInDb.Name = employee.Name;
employeeInDb.Address = employee.Address;
employeeInDb.Salary = employee.Salary;
employeeInDb.DepartmentId = employee.DepartmentId;
employeeInDb.DesignationId = employee.DesignationId;
}
context.SaveChanges();
return RedirectToAction(nameof(Index));
}
<div class="form-group">
@Html.LabelFor(m => m.DesignationId)
@*@Html.DropDownListFor(m => m.DesignationId, new SelectList(ViewData["desList"] as List<Designation>,
"Id", "Name"), "Select Your Designation", new { @class = "form-control" })*@
@Html.DropDownListFor(m => m.DesignationId,new SelectList(ViewBag.desList,"Id","Name"),"Select Your
Designation", new {@class="form-control"})
@Html.ValidationMessageFor(m => m.DesignationId, "", new { @class = "text-danger" })
</div>
In ViewBag there is no need for Type Casting and also no need for include the namespace at
above but in ViewData there is need for include the namespace(@using
MVCentityFrameworkNewProject.Models) and the type casting.
@model MVCentityFrameworkNewProject.Models.Employee
@{
ViewBag.Title = "Details";
}
21) Now add the Delete button view code in Index.cshtml with using the
Html.BeginForm
@model IEnumerable<MVCentityFrameworkNewProject.Models.Employee>
</tbody>
</table>
}
Steps: -
1) New Project
2) ASP.NET CORE MVC, Web App
3) Ecomm_Project2
10) There are create some file and delete the Class1.css file
11) Now again add the new Class Go to File Add New Project Ecomm_Project2.DataAccess
13) Again, add a new class and Delete the Class1.cs file
14) Now clean the all projects and build them by press the right click on the projects
15) Now go to main project and add Project Reference (because the files are added from another
project)
16) Now install the projects ( MS.EntityFrameworkCore and SqlServer and Tools )
17)
18) Now Cut the Models folder from main project and paste it in Ecomm_Project2.Models
20) Now Clean and Build the Ecomm_Project2.Models and main Project
21) Now cut the Data folder from main project and paste it in Ecomm_Project2.DataAccess
24) Now check the namespace and other error in ApplicationDbContext in Ecomm_Poject2.DataAccess
and correct them
25) Now check each projects’ error by Build and solve these errors.
26) During the Build the projects there is error find in Main project,Startup.cs file, Like
27) Add the namespace of these file and you can remove these errors.
28) Again, Build the main project and we find an error more and build the project again and agin
till the all error are not remove/solve
31) Again build the main project and there are show some error
32) Go to Ecomm_Project2.Models ViewModels ErrorViewModel.cs
33) Now again Build the main project and there is no any error in project
34) Add the Database path in appsettings.json and there can do some changes
37) Now if we want to change the theme, then go to Bootswatch website and choose a version 4
theme and use it in our project by replace old css file with new css file
Change the name of ~/lib/bootstrap/dist/css/bootstrap.min.css to
~/lib/bootstrap/dist/css/bootstrap.css in _Layout.cshtml
39) Now delete the two folder Data and Models from Area
40) Now cut the HomeController.cs from Controllers and paste it into the Customer Controllers
42) Now cut the Home folder from View folder of main project and paste it into the Areas
Customer Views
43) Now go to Startup.cs file of main project and add the name of area in the it
44) There is no path find so for this problem there can be add Area name in HomeController of
Area
46) Now for show the output in browser there are copy two files from Views Shared
47) Now add new Admin Area in Area folder of main project
49) Now copy the two files of main project Views Shared into Areas Admin
50) Now add new Category.cs Class in Ecomm_Project2.Models and add Id, Name in Category.cs class
51) Now same a new class add in Ecomm_Project2.Models of name CoverType and Id, Name in it
56) Now go to the Ecomm_project2.DataAccess and add new folder of name Repository
57) Now again add a new folder in Repository folder of name IRepository
58) Now add a new class in IRepository folder of name IRepository.cs and choose the interface
during the create this class
Make it public from internal
59) Now write the Add, Find, Details and Remove code in IRepository class
60) Now add a new class in Repository folder of name Repository.cs in Ecomm_project2.DataAccess
61) Now add a new class of Interface type in subfolder of Repository IRepository of name
ICategoryRepository in in Ecomm_project2.DataAccess project
62) Now write the Update code in new created interface class ICategoryRepository
using Ecomm_Project2.Models.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface ICategoryRepository: IRepository<Category>
{
void Update(Category category);
}
}
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository
{
public class CategoryRepository : Repository<Category>, ICategoryRepository
{
private readonly ApplicationDbContext _context;
public CategoryRepository(ApplicationDbContext context) : base(context)
{
_context = context;
}
public void Update(Category category)
{
_context.Update(category);
}
}
}
64) Now again add a new Interface class in IRepository folder of name ICoverTypeRepository
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface ICoverTypeRepository : IRepository<CoverType>
{
void Update(CoverType coverType);
}
}
namespace Ecomm_Project2.DataAccess.Repository
{
public class CoverTypeRepository : Repository<CoverType>, ICoverTypeRepository
{
private readonly ApplicationDbContext _context;
public CoverTypeRepository(ApplicationDbContext context) : base(context)
{
_context = context;
}
67) Now add the new Interface class type IUnitOfWork in IRepository folder
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface IUnitOfWork
{
ICategoryRepository Category { get; }
ICoverTypeRepository CoverType { get; }
void Save();
}
}
namespace Ecomm_Project2.DataAccess.Repository
{
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
Category = new CategoryRepository(_context);
CoverType = new CoverTypeRepository(_context);
}
public ICategoryRepository Category { get; private set; }
69) Now comment these two lines in Startup.cs file and add a new line in it
70) Now add a new CategoryController controller in Area Admin Controller
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class CategoryController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public CategoryController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IActionResult Index()
{
return View();
}
}
}
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button"
aria-haspopup="true" aria-expanded="false">Content Management</a>
<div class="dropdown-menu">
@*<a class="dropdown-item" href="#">Action</a>*@
<a class="dropdown-item" asp-area="Admin" asp-controller="Category" asp-
action="Index" >Category</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Separated link</a>
</div>
</li>
#region APIs
[HttpGet]
public IActionResult GetAll()
{
var categoryList = _unitOfWork.Category.GetAll();
return Json(new { data = categoryList });
}
#endregion
74) Now right click on GetAll() function and choose Go To Implementation option
<div class="row">
<div class="col-9">
<h2 class="text-success">Category List</h2>
</div>
<div class="col-3">
<a asp-action="Upsert" class="btn btn-info">
New Category
</a>
</div>
</div>
<div class="bordern p-2 m-2">
<table id="tblData" class="table table-active tab-content table-hover table-striped">
<thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
</table>
</div>
76) Now add a new JavaScript file of name category.js in main project wwwroot js add
New Item
Now write the code in JSON form of API data in new create js file category.js file
var dataTable;
$(document).ready(function () {
loadDataTable();
})
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": { "url": "/Admin/Category/GetAll" },
"columns": [{
"data": "name", "width": "70%"
},
{
"data": "id", "render": function (data) {
return `
<div class="text-center">
<a href="/Admin/Category/Upsert/${data}" classs = "btn btn-info">
<i class="fas fa-edit"></li>
</a>
<a classs = "btn btn-danger" onclick=Delete("/Admin/Category/Delete/${data}")>
<i class="fas fa-trash-alt"></li>
</a>
</div>
`;
}
}
]
})
}
@section scripts{
<script src="~/js/category.js"></script>
}
// Edit
category = _unitOfWork.Category.Get(id.GetValueOrDefault());
if (category == null) return NotFound();
return View(category);
}
@model Ecomm_Project2.Models.Category
@{
ViewData["Title"] = "Upsert";
var title = Model.Id != 0 ? "Edit Category" : "New Category";
var saveupdate = Model.Id != 0 ? "Update" : "Save";
}
<form method="post">
<div class="row">
<h2 class="text-primary">@title</h2>
</div>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-8">
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Name"></label>
</div>
<div class="col-8">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row p-2 m-2">
<div class="col-4 offset-4">
<button type="submit" class="btn btn-success form-
control">@saveupdate</button>
</div>
<div class="col-4">
<a asp-action="Index" class="btn btn-primary form-
control">Back to List</a>
</div>
</div>
</div>
</form>
@section scripts{
<partial name="_ValidationScriptsPartial" />
}
<div class="row">
<div class="col">
<button type="submit" class="btn btn-info form-control">Create</button>
</div>
<div class="col">
<a asp-action="Index" class="btn btn-success form-control">
Back to List
</a>
</div>
</div>
82) Now again crate a new View in Shared folder
<div class="row">
<div class="col">
<button type="submit" class="btn btn-info form-control">Update</button>
</div>
<div class="col">
<a asp-action="Index" class="btn btn-primary form-control">
Back to List
</a>
</div>
</div>
83) Now go to Upsert.cshtml file and use these Partial type view in it but firstly we comments
the before Save and Update button code
function Delete(url) {
swal({
text: "Delete Information !!",
title: "Want to delete data ?",
icon: "warning",
buttons: true,
dangerModel: true
}).then((willDelete) => {
if (willDelete) {
$.ajax({
url: url,
type: "DELETE",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
}
})
}
})
}
using
Ecomm_Project2.DataAccess.Repository.IRepository;
using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions;
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class CoverTypeController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public CoverTypeController(IUnitOfWork
unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IActionResult Index()
{
return View();
}
#region APIs
[HttpGet]
public IActionResult GetAll()
{
return Json(new { data = _unitOfWork.CoverType.GetAll() });
}
#endregion
}
}
88) Now add the View of Index in CoverTypeController
<div class="row">
<div class="col-9">
<h2 class="text-success">Cover Type List</h2>
</div>
<div class="col-3">
<a asp-action="Upsert" class="btn btn-info">
New Cover Type
<i class='fas fa-plus'></i>
</a>
</div>
</div>
<div class="border p-2 m-2">
<table id="tblData" class="table table-hover table-striped">
<thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
</table>
</div>
@section scripts{
<script src="~/js/covertype.js"></script>
}
90) Now add a new Item in js file and write code here
<div class="row">
<div class="col-9">
<h2 class="text-success">Cover Type List</h2>
</div>
<div class="col-3">
<a asp-action="Upsert" class="btn btn-info">
New Cover Type
<i class='fas fa-plus'></i>
</a>
</div>
</div>
<div class="border p-2 m-2">
<table id="tblData" class="table table-hover table-striped">
<thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
</table>
</div>
@section scripts{
<script src="~/js/covertype.js"></script>
}
91) Now write the code of View, Find Update and Insert in CoverTypeController.cs
@model Ecomm_Project2.Models.CoverType
@{
ViewData["Title"] = "Upsert";
var title = Model.Id != 0 ? "Edit Item" : "New Cover Type";
var saveupdate = Model.Id != 0 ? "Update" : "Save";
}
<form method="post">
<div class="row">
<div class="col-10 border-bottom">
<h2 class="text-info">@title</h2>
</div>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-8">
<div class="form-group row p-3 m-4">
<div class="col-4 offset-4">
<label asp-for="Name"></label>
</div>
<div class="col-8">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger" />
</div>
</div>
<div class="form-group row p-3 m-4">
@if (Model.Id != 0)
{
<partial name="_EditAndBackToListButton" />
}
else
{
<partial name="_CreateAndBackToListButton" />
}
</div>
</div>
</div>
</form>
@section scripts{
<partial name="_ValidationScriptsPartial" />
}
95) Now write the code of CoverType Delete button in covertype.js file using the sweet alert
function Delete(url) {
swal({
text: "Delete Information !!",
title: "Want to delete data ?",
icon: "warning",
buttons: true,
dangerModel: true
}).then((willDelete) => {
if (willDelete) {
$.ajax({
url: url,
type: "DELETE",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
}
})
}
})
}
96) Now add the store procedure in CoverType for data store.
97) Go to SQL server object explorer in View right click on database and find the store
procedure
Now write the Store procedure command in it
Same add all the other command at here like, update, delete and select and then update-database at
migration command
98) Now run the migration command update-database
Now write the code for access the store procedure in SD class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Utility
{
public static class SD
{
// cover type store procedure
public const string Proc_GetCoverTypes = "GetCoverTypes";
public const string Proc_GetCoverType = "GetCoverType";
public const string Proc_CreateCoverType = "CreateCoverType";
public const string Proc_UpdateCoverType = "UpdateCoverType";
public const string Proc_DeleteCoverType = "DeleteCoverType";
}
}
100) Now add a new Interface type class ISP_CALL in IRepositiory folder
101) Now write the following code
using Dapper;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface ISP_CALL : IDisposable
{
void Execute(string procedureName, DynamicParameters param = null);
T Single<T>(string procedureName, DynamicParameters param = null);
T OneRecord<T>(string procedureName, DynamicParameters param = null);
IEnumerable<T> List<T>(string procedureName, DynamicParameters param = null);
Tuple<IEnumerable<T1>, IEnumerable<T2>> List<T1, T2>(string procedureName, DynamicParameters param =
null);
}
}
namespace Ecomm_Project2.DataAccess.Repository
{
public class SP_CALL : ISP_CALL
{
private readonly ApplicationDbContext _context;
private static string connectionString = "";
public SP_CALL(ApplicationDbContext context)
{
_context = context;
connectionString = _context.Database.GetDbConnection().ConnectionString;
}
105) Now go to CoverTypeController.cs file and write the code of Get, Update/Upsert and
Delete with store procedure type at here
106) Now add a class in in Ecomm_Project2.Models of name Product
namespace Ecomm_Project2.Models
{
public class Product
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string ISBN { get; set; }
public string Author { get; set; }
[Required]
[Range(1,10000)]
public double ListPrice { get; set; }
[Required]
[Range(1,10000)]
public double Price50 { get; set; }
[Required]
[Range(1,10000)]
public double Price100 { get; set; }
[Required]
[Range(1,10000)]
public double Price { get; set; }
[Display(Name ="Image Url")]
public string ImageUrl { get; set; }
[Display(Name ="Category")]
public int CategoryId { get; set; }
[Display(Name ="Cover Type")]
public int CoverTypeId { get; set; }
public CoverType CoverType { get; set; }
}
}
107) Now register this Product.cs class into Ecomm_Project2.DataAccess Data
ApplicationDbContext.cs file
108) Now add migration and update the database add-migration addProductTable
109) Now add a new Interface type class IProductRepository in IRepository folder
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface IProductRepository : IRepository<Product>
{
void Update (Product product);
}
}
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository
{
public class ProductRepository : Repository<Product>, IProductRepository
{
private readonly ApplicationDbContext _context;
public ProductRepository(ApplicationDbContext context) : base(context)
{
_context = context;
}
using Microsoft.AspNetCore.Mvc;
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class ProductController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
114) Now add the Product Index at Navbar in _Layout.cshtml
116) Now go to the ProductController and write the code of Index and JSON API for fetch the
data and sent to View, here we also write the Upsert and much more
using Ecomm_Project2.DataAccess.Repository;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis.Operations;
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class ProductController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public ProductController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
117) Now create a product.js file for View and write the code of show data at columns and
Sweet alert for delete button
var dataTable;
$(document).ready(function () {
loadDataTable();
})
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": { "url": "/Admin/Product/GetAll" },
"columns": [
{ "data": "title", "width": "15%" },
{ "data": "description", "width": "25%" },
{ "data": "author", "width": "15%" },
{ "data": "isbn", "width": "15%" },
{ "data": "price", "width": "15%" },
{
"data": "id",
"render": function (data) {
return `
<div class ="text-center">
<a href ="/Admin/Product/Upsert/${data}" class = "btn btn-info">
<i class ="fas fa-edit"></i>
</a>
<a class = "btn btn-danger" onclick =
Delete("/Admin/Product/Delete/${data}")>
<i class = "fas fa-trash-alt"></i>
</a>
</div>
`;
}
}
]
})
}
function Delete(url) {
swal({
text: "Delete Information !!",
title: "Want to delete data ?",
icon: "warning",
buttons: true,
dangerModel: true
}).then((willDelete) => {
if (willDelete) {
$.ajax({
url: url,
type: "DELETE",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
}
})
}
})
}
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Models.ViewModels
{
public class ProductVM
{
public Product Product { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
public IEnumerable<SelectListItem> CoverTypeList { get; set; }
}
}
120) Now go to the ProductController and Write the Upsert code at here
Now make the Form in Upsert.cshtml of Product for take the input from the user
@model Ecomm_Project2.Models.ViewModels.ProductVM
@{
ViewData["Title"] = "Upsert";
var title = Model.Product.Id != 0 ? "Edit Product" : "New Product";
}
<div class="row">
<h2 class="text-center text-primary border-bottom">@title</h2>
</div>
<div class="row">
<div class="col-md-6">
<form method="post" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@if (Model.Product.Id != 0)
{
<input type="hidden" asp-for="@Model.Product.Id" />
}
<div class="form-group">
<label asp-for="Product.Title"></label>
<input asp-for="Product.Title" class="form-control" />
<span asp-validation-for="Product.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.ISBN"></label>
<input asp-for="Product.ISBN" class="form-control" />
<span asp-validation-for="Product.ISBN" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.Description"></label>
<textarea asp-for="Product.Description" class="form-control"></textarea>
<span asp-validation-for="Product.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.Author"></label>
<input asp-for="Product.Author" class="form-control" />
<span asp-validation-for="Product.Author" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.ListPrice"></label>
<input asp-for="Product.ListPrice" class="form-control" />
<span asp-validation-for="Product.ListPrice" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.Price"></label>
<input asp-for="Product.Price" class="form-control" />
<span asp-validation-for="Product.Price" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.Price50"></label>
<input asp-for="Product.Price50" class="form-control" />
<span asp-validation-for="Product.Price50" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.Price100"></label>
<input asp-for="Product.Price100" class="form-control" />
<span asp-validation-for="Product.Price100" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.CategoryId"></label>
@Html.DropDownListFor(m => Model.Product.CategoryId,Model.CategoryList,"Select Category",new
{@class = "form-control"})
<span asp-validation-for="Product.CategoryId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.CoverTypeId"></label>
@Html.DropDownListFor(m => Model.Product.CoverTypeId,Model.CoverTypeList,"Select CoverType",new
{@class = "form-control"})
<span asp-validation-for="Product.CoverTypeId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product.ImageUrl"></label>
<input type="file" name="files" id="uploadBox" multiple class="form-control" />
</div>
<div class="form-group p-2 m-2">
@if (Model.Product.Id != 0)
{
<partial name="_EditAndBackToListButton" />
}
else
{
// <partial name="_CreateAndBackToListButton" />
<div class="row">
<div class="col">
<button type="submit" onclick="return ValData()"class="btn btn-info form-
control">Save</button>
</div>
<div class="col"><a asp-action="Index" class="btn btn-success form-control">Back To
List</a>
</div>
</div>
}
</div>
</form>
</div>
</div>
@section scripts{
<partial name="_ValidationScriptsPartial" />
<script
src="https://cdn.tiny.cloud/1/yceb7wqr2ps5v3vunieemb9syejgjl73j210uk6duakmo75e/tinymce/5/tinymce.min.js"
referrerpolicy="origin"></script>
<script>
tinymce.init({
selector: "textarea",
plugins: "lists",
menubar: "file edit format"
})
function ValData(){
if (document.getElementById("uploadBox").value == ""){
swal("Error","Please Select Image!!",'error');
return false;
}
}
</script>
}
124) Now go to the ProductController.cs and write the code for valid file path and valid
image number( more than one)
using Ecomm_Project2.DataAccess.Repository;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models;
using Ecomm_Project2.Models.ViewModels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.Data.SqlClient;
using System;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class ProductController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IWebHostEnvironment _webHostEnvironment;
public ProductController(IUnitOfWork unitOfWork, IWebHostEnvironment webHostEnvironment)
{
_unitOfWork = unitOfWork;
_webHostEnvironment = webHostEnvironment;
}
}
else
{
productVM = new ProductVM()
{
Product = new Product(),
CategoryList = _unitOfWork.Category.GetAll().Select(cl => new SelectListItem()
{
Text = cl.Name,
Value = cl.Id.ToString()
}),
CoverTypeList = _unitOfWork.CoverType.GetAll().Select(ct => new SelectListItem()
{
Text= ct.Name,
Value = ct.Id.ToString()
})
};
if(productVM.Product.Id != 0)
{
productVM.Product = _unitOfWork.Product.Get(productVM.Product.Id);
}
}
return View(productVM);
}
}
}
//Delete File
var webRootPath = _webHostEnvironment.WebRootPath;
var imagePath = Path.Combine(webRootPath, productInDb.ImageUrl.Trim('\\'));
if (System.IO.File.Exists(imagePath))
{
System.IO.File.Delete(imagePath);
}
_unitOfWork.Product.Remove(productInDb);
_unitOfWork.Save();
return Json(new { success = true, message = "Data Deleted Successfully!" });
}
128) Now go to the HomeController and the write the code of card representation in Index
@model IEnumerable<Ecomm_Project2.Models.Product>
<div class="row">
@foreach (var product in Model)
{
<div class="col-lg-3 col-md-6 ">
<div class="row p-2">
<div class="col-12p-1" style="border:1px solid #008cba; border-radius: 4px;">
<div class="card" style="border:4px;">
<img src="@product.ImageUrl" class="card-img-top rounded" />
<hr/>
<div class="pl-1">
<p class="card-title h5"><b style="color:#2c3e50">@product.Title</b></p>
<p class="card-title text-primary">by <b>@product.Author</b></p>
</div>
<div style="padding-left:5px;">
<p>List Price: <strike><b class="">[email protected]("0.00")</b></strike></p>
</div>
<div style="padding-left:5px;">
<p style="color:maroon">As low as: <b class="">[email protected]("0.00")</b></p>
</div>
</div>
<div>
<a asp-action="Details" class="btn btn-primary form-control border-0" asp-route-
id="@product.Id">Details</a>
</div>
</div>
</div>
</div>
}
</div>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Models
{
public class Company
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Display(Name ="Street Address")]
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
[Display(Name ="Postal Code")]
public string PostalCode { get; set; }
[Display(Name ="Phone Number")]
public string PhoneNumber { get; set; }
[Display(Name ="Is Authorized Company")]
public bool IsAuthorizedCompany { get; set; }
}
}
132) Now add the migrations for set the tables in the database
133) Now add a new Interface type class in Ecomm_Project2.DataAccess of folder IRepository
with name ICompanyRepository
134) Now write the code of update tables in this interface class
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface ICompanyRepository:IRepository<Company>
{
void Update(Company company);
}
}
135) Now add a new class of name CompanyRepository in folder of Repository in
Ecomm_Project2.DataAccess
136) Now write the code for connect this class with database in it
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models;
using Microsoft.AspNetCore.Identity.UI.V4.Pages.Internal.Account;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository
{
public class CompanyRepository : Repository<Company>, ICompanyRepository
{
private readonly ApplicationDbContext _context;
public CompanyRepository(ApplicationDbContext context) : base(context)
{
_context = context;
}
139) Now add the MVC Controller in Areas Admin Controllers of name CompanyController
140) Now write the code at here and add the UnitOfWork
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Microsoft.AspNetCore.Mvc;
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class CompanyController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public CompanyController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
142) Now add the Index page of Company class and write the following code
<div class="row">
<div class="col-9">
<h2 class="text-success">Company List</h2>
</div>
<div class="col-3">
<a asp-action="Upsert" class="btn btn-info form-control">
Add New Company <i class="fas fa-plus"></i>
</a>
</div>
</div>
<div class="border p-2 m-2">
<table id="tblData" class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Phone Number</th>
<th>Is Authorized</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
@section scripts {
<script src="~/js/company.js"></script>
}
143) Now for access these columns data we add a GetAll() name API in CompanyController
var dataTable;
$(document).ready(function () {
loadDataTable();
})
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": { "url": "/Admin/Company/GetAll" },
"columns": [
{ "data": "name", "width": "15%" },
{ "data": "streetAddress", "width": "15%" },
{ "data": "city", "width": "15%" },
{ "data": "state", "width": "15%" },
{ "data": "phoneNumber", "width": "15%" },
{
"data": "isAuthorizedCompany",
"render": function (data) {
if (data) {
return `<input type="checkbox" checked disable />`;
}else
{
return `<input type="checkbox" disable />`;
}
}
},
{
"data": "id",
"render": function (data) {
return `
<div class ="text-center">
<a href ="/Admin/Company/Upsert/${data}" class = "btn btn-info">
<i class ="fas fa-edit"></i>
</a>
<a class = "btn btn-danger" onclick = Delete("/Admin/Company/Delete/${data}")>
<i class = "fas fa-trash-alt"></i>
</a>
</div>
`;
}
}
]
})
function Delete(url) {
swal({
text: "Delete Information !!",
title: "Want to delete data ?",
icon: "warning",
buttons: true,
dangerModel: true
}).then((willDelete) => {
if (willDelete) {
$.ajax({
url: url,
type: "DELETE",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
}
})
}
})
}
145) Now go to the CompanyController and write the code of Upsert/Add and Update code
146) Now add the Razor View of Upsert action of Company and create the input field
@model Ecomm_Project2.Models.Company
@{
ViewData["Title"] = "Upsert";
var title = Model.Id != 0 ? "Edit Company" : "New Company";
}
<form method="post">
<div class="row border">
<div class="col-12">
<h2 class="text-success border-bottom">@title</h2>
</div>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-8 border rounded p-2 m-2">
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Name"></label>
</div>
<div class="col-8">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
@section scripts{
<partial name="_ValidationScriptsPartial" />
}
147) Now write the Delete API code in CompanyController
148) Now for use the Identity framework, go to the main project, Ecomm_Project2 right
click add New Scaffolded item Identity add choose Override all file checkbok
button in below option Data context class choose, DataAccess.Data add
149) Now go to Ecomm_Project2.Models, right click add new class name ApplicationUser
namespace Ecomm_Project2.Models
{
public class ApplicationUser : IdentityUser
{
[Required]
public string Name { get; set; }
[Display(Name ="Street Address")]
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
[Display(Name ="Postal Code")]
public string PostalCode { get; set; }
[Display(Name ="Company")]
public int? CompanyId { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
[NotMapped]
public string Role { get; set; }
}
}
150) Now add this class in ApplicationDbContext file
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface IApplicationUserRepository : IRepository<ApplicationUser>
{
}
}
153) Now add a new class in Repository folder of name ApplicationUserRepository
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public class ApplicationUserRepository : Repository<ApplicationUser>, IApplicationUserRepository
{
private readonly ApplicationDbContext _context;
public ApplicationUserRepository(ApplicationDbContext context) : base(context)
{
_context = context;
}
}
}
156) Now go to the Register.cshtml.cs file and add the some new custom columns
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.",
MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
// Add custom columns
[Required]
public string Name { get; set; }
[Display(Name ="Street Address")]
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
[Display(Name ="Postal Code")]
public string PostalCode { get; set; }
[Display(Name ="Phone Number")]
public string PhoneNumber { get; set; }
public int? CompanyId { get; set; }
public string Role { get; set; }
}
157) Now go to the Register.cshtml file and add these new custom columns in html file
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.StreetAddress"></label>
<input asp-for="Input.StreetAddress" class="form-control" />
<span asp-validation-for="Input.StreetAddress" class="text-
danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.PhoneNumber"></label>
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber" class="text-
danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.State"></label>
<input asp-for="Input.State" class="form-control" />
<span asp-validation-for="Input.State" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.City"></label>
<input asp-for="Input.City" class="form-control" />
<span asp-validation-for="Input.City" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.PostalCode"></label>
<input asp-for="Input.PostalCode" class="form-control" />
<span asp-validation-for="Input.PostalCode" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to register.</h4>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<p>
There are no external authentication services configured. See <a
href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via
external services.
</p>
</div>
}
else
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-
returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-primary" name="provider"
value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div>
158) Now add the Identity of User and Role and also add the Razors pages in Startup.cs
file
159) We add the Identity Framework in the Models project, because we are using the
Identity framework
160) Now go to the Ecomm_Project2.Utility folder and add a new class EmailSender
using Microsoft.AspNetCore.Identity.UI.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Utility
{
public class EmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
throw new NotImplementedException();
}
}
}
164) Now assign the role of user in the SD.cs class in Utility project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Utility
{
public static class SD
{
// cover type store procedure
public const string Proc_GetCoverTypes = "GetCoverTypes";
public const string Proc_GetCoverType = "GetCoverType";
public const string Proc_CreateCoverType = "CreateCoverType";
public const string Proc_UpdateCoverType = "UpdateCoverType";
public const string Proc_DeleteCoverType = "DeleteCoverType";
//Roles
public const string Role_Admin = "Admin";
public const string Role_Employee = "Employee User";
public const string Role_Company = "Company User";
public const string Role_Individual = "Individual User";
}
}
167) When the Admin is created the comment this line, because the first admin user is
created
168) Add the Role and Company in InputModel
171) Now assign the role to all the user instead of the Individual user in
Registr.cshtml.cs file
172) Now create the dropdown list for the select the Role of Admin and the Company Id for
the Admin in Register.cshtml
Firstly, add this
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
@if (User.IsInRole(SD.Role_Admin))
{
<div class="form-group">
<label asp-for="Input.CompanyId"></label>
@Html.DropDownListFor(m => m.Input.CompanyId, Model.Input.CompanyList,"Select Role",new{@class
=" form-control"})
<span asp-validation-for="Input.CompanyId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Role"></label>
@Html.DropDownListFor(m => m.Input.Role, Model.Input.RoleList,"Select Role",new{@class ="
form-control"})
<span asp-validation-for="Input.Role" class="text-danger"></span>
</div>
}
<button type="submit" class="btn btn-primary">Register</button>
</form>
173) Now create a new User controller in the Areas Admin Controllers Right
Click
174) Now add all the user in the list and give the access to the Admin user to delete the
other user
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.Utility;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace Ecomm_Project2.Areas.Admin.Controllers
{
[Area("Admin")]
public class UserController : Controller
{
private readonly ApplicationDbContext _context;
public UserController(ApplicationDbContext context)
{
_context = context;
}
public IActionResult Index()
{
return View();
}
#region APIs
[HttpGet]
public IActionResult GetAll()
{
var userList = _context.ApplicationUsers.Include(a => a.Company).ToList(); // AspNetUsers
var roles = _context.Roles.ToList(); // AspNetRoles
var userRoles = _context.UserRoles.ToList(); // AspNetUserRoles
}
#endregion
}
}
175) Now add the Razor View of Index action of User controller
<div class="row">
<div class="col-9">
<h2 class="tet-primary">User List</h2>
</div>
<div class="col-3">
<a asp-area="Identity" class="btn btn-info" asp-page="/Account/Register">
<i class="fas fa-plus"> Create New User</i>
</a>
</div>
</div>
<div class="border rounded p-2 m-2">
<table id="tblData" class="table table-borderless table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone Number</th>
<th>Company</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
</table>
</div>
176) Now add this user in the navbar at the _Layout.cs file
177) Now add a user.js file to show the data in the columns from the database
var dataTable;
$(document).ready(function () {
loadDataTable();
})
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": {
"url": "/Admin/User/GetAll"
},
"columns": [
{ "data": "name", "width": "15%" },
{ "data": "email", "width": "15%" },
{ "data": "phoneNumber", "width": "15%" },
{ "data": "company.name", "width": "15%" },
{ "data": "role", "width": "15%" },
{
"data": {
id: "id", lockoutEnd: "lockoutEnd"
},
"render": function (data) {
var today = new Date().getTime();
var lockOut = new Date(data.lockoutEnd).getTime();
if (lockOut > today) {
//User Locked
return `
<div class="text-center">
<a class="btn btn-danger" onclick=LockUnLock('${data.id}')>UnLock</a>
</div>
`;
}
else {
// user unlock
return `
<div class="text-center">
<a class="btn btn-success" onclick=LockUnLock('${data.id}')>Lock</a>
</div>
`;
}
}
} ] })}
function LockUnLock(id) {
$.ajax({
url: "/Admin/User/LockUnlock",
type: "POST",
data: JSON.stringify(id),
contentType: "application/json",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
} })}
179) Now write the code of OnSubmit data of LockUnlock code in UserController.cs
182) Now write the code in Register.cshtml.cs for navigate the user according to its role
183) Now Authorized the Page to the user according to their role, add the Authorize word
below the Admin in Category, CoverType, Product, Company and User files
184) Now, when those pages are not access by the user and he/she get those error, we
change this code. For this goto the startup.cs page and some pages path
185) Now to hide the Navbar options from the user there should be some changes in the
_Layout.cs file like this
@if (User.IsInRole(SD.Role_Admin))
{
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-
toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Select
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" asp-area="Admin" asp-controller="Category" asp-action="Index">Category</a>
<a class="dropdown-item" asp-area="Admin" asp-controller="CoverType" asp-action="Index">Cover
Type</a>
<a class="dropdown-item" asp-area="Admin" asp-controller="Product" asp-action="Index">Product</a>
</div>
</li>
}
@if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee))
{
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-
toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Company/User
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" asp-area="Admin" asp-controller="Company" asp-action="Index">Company</a>
<hr />
<a class="dropdown-item" asp-area="Admin" asp-controller="User" asp-action="Index">Users</a>
</div>
</li>
}
186) Now for the Open Authentication like, the user can login with the Facebook, Google
account etc. so for this we must be install their packages.
187) Now to add these authentications go to the startup.cs file
Note! These ids are only for sample no the real. When you no have google ClientId and ClientSecret
then firstly make sure it comment otherwise it show the error, because you don’t have these id.
188) Now go to the ExternalLogin.cshtml.cs and do some changes for add new input field,
when the user login through the Facebook etc.
189) Now write this code in ExternalLogin.cshtml.cs for new Input field
@page
@model ExternalLoginModel
@{
ViewData["Title"] = "Register";
}
<h1>@ViewData["Title"]</h1>
<h4 id="external-login-title">Associate your @Model.ProviderDisplayName account.</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-page-handler="Confirmation" asp-route-returnUrl="@Model.ReturnUrl" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.StreetAddress"></label>
<input asp-for="Input.StreetAddress" class="form-control" />
<span asp-validation-for="Input.StreetAddress" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.State"></label>
<input asp-for="Input.State" class="form-control" />
<span asp-validation-for="Input.State" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.City"></label>
<input asp-for="Input.State" class="form-control" />
<span asp-validation-for="Input.State" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.PostalCode"></label>
<input asp-for="Input.PostalCode" class="form-control" />
<span asp-validation-for="Input.PostalCode" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.PhoneNumber"></label>
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
191) If we want to access or retrieve the data from Facebook other than email and name,
like Address, city, phone number etc then we can’t receive the data.
That’s why now this line make comment, because the Facebook don’t send this data of the
user.
192) Now this type of data take from the user manually. For this we create the multiple
input types in ExternalLogin.cshtml.cs
193) Now we can write the code for authentication via google. So firstly we create a
account on the google. Go the console.developers.google website
a) Now click on NEW PROJECT at top right side
b) Now write the Project name in the input field and create
e) If we can’t find the Goople+ API then manually search and choose it
n) Now paste the local url of the project which is show at the browser in the URls 1 input
field and also write the Authorized redirect URls link and click on CREATE button
o) Now the OAuth Client is created and there are 2 values are generated like, Your Client
ID and Your Client Secret. Copy these two Ids and paste it in the Startup.cs file as
p) Now when we add this, there is create a another button Google like Facebook button in
the Login page
q) When we click on the login with Google button, then we go on the Google Authentication
page like
r) Now choose your account and login with it and after successfully login we can see the
same name of user in the Navbar by which we login.
194) There we can also add some other Authentication type. It means if there are add
restriction on user to access the web page like, Home, Privacy or other then we can add the
[AllowAnonymous] at the above on the Action name in CategoryController.cs like
But now we are not adding this functionality, so now we remove these.
namespace Ecomm_Project2.Models
{
public class ShoppingCart
{
public ShoppingCart()
{
Count = 1;
}
public int Id { get; set; }
public string ApplicationUserId { get; set; }
[ForeignKey("ApplicationUserId")]
public ApplicationUser ApplicationUser { get; set; }
public int ProductId { get; set; }
[ForeignKey("ProductId")]
public Product Product { get; set; }
public int Count { get; set; }
[NotMapped]
public double Price { get; set; }
}
}
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface IShoppingCartRepository : IRepository<ShoppingCart>
{
void Update(ShoppingCart shoppingCart);
}
}
199) Now add a new class ShoppingCartRepository.cs in Repository folder
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository
{
public class ShoppingCartRepository : Repository<ShoppingCart>, IShoppingCartRepository
{
private readonly ApplicationDbContext _context;
public ShoppingCartRepository(ApplicationDbContext context) : base(context)
{
_context = context;
}
202) Now to show the details of the item, we create the Detail action in HomeController.cs
file
203) Now add the Razor view of this Details action
@model Ecomm_Project2.Models.ShoppingCart
<form method="post">
</div>
</div>
</div>
</div>
</div>
</form>
204) Now write the code for add to cart data/item in ShoppingCart at HomeController
[HttpPost]
[AutoValidateAntiforgeryToken]
[Authorize]
public IActionResult Details(ShoppingCart shoppingCart)
{
shoppingCart.Id = 0;
if (ModelState.IsValid)
{
var claimsIdentity = (ClaimsIdentity)User.Identity;
var claim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
shoppingCart.ApplicationUserId = claim.Value;
207) Now add/ register the session variable in the SD.cs file as a stored variable
208) Now add the Icon in navbar to show the Cart Item number details, in _Layout.cshtml
namespace Ecomm_Project2.Areas.Customer.Controllers
{
[Area("Customer")]
public class CartController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public CartController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
<form method="post">
<br />
<div class="backgroundWhiteBorder">
<div class="container">
<div class="card">
<div class="card-header bg-dark text-light ml-0 row container">
<div class="col-6">
<i class="fa fa-shopping-cart"></i>
Shopping Cart
</div>
<div class="col-6 text-right">
<a asp-controller="Home" asp-action="Index" class="btn btn-outline-info btn-sm">Continue
Shopping</a>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="d-none d-lg-block col-lg-1 text-center py-2">
<img src="https://via.placeholder.com/150" class="rounded" width="100%" />
</div>
<div class="col-12 text-sm-center col-lg-6 text-lg-left">
<h5><strong>--TITLE--</strong></h5>
<p><small>--DESCRIPTION--</small></p>
</div>
<div class="col-12 text-sm-center col-lg-5 text-lg-right row">
<div class="col-4 text-md-right" style="padding-top:5px;">
<h6><strong>--Price --<span class="text-muted">x</span> --Count-- </strong></h6>
</div>
<div class="col-6 col-sm-4 col-lg-6">
<div class="float-right mx-1">
<button type="submit" class="btn btn-primary">
<i class="fas fa-plus"></i>
</button>
</div>
<div class="float-right mx-1">
<button type="submit" class="btn btn-danger">
<i class="fas fa-minus"></i>
</button>
</div>
</div>
<div class="col-2 col-sm-4 col-lg-2 text-right">
<button type="submit" class="btn btn-outline-danger">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col-12 col-md-6 offset-md-6 col-lg-4 offset-lg-8 pr-4">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between bg-light">
<span class="text-info"> Total (USD)</span>
<strong class="text-info">$ <span id="txtOrderTotal">--TOTAL--</span></strong>
</li>
</ul>
</div>
</div>
</div>
<div class="card-footer">
<div class="card-footer row">
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Models
{
public class OrderHeader
{
public int Id { get; set; }
public string ApplicationUserId { get; set; }
[ForeignKey("ApplicationUserId")]
public ApplicationUser ApplicationUser { get; set; }
[Required]
public DateTime OrderDate { get; set; }
[Required]
public DateTime ShippingDate { get; set; }
[Required]
public double OrderTotal { get; set; }
213) Now again add a new public type class OrderDetails in Ecomm_Project2.Models
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
namespace Ecomm_Project2.Models
{
public class OrderDetails
{
public int Id { get; set; }
public int OrderHeaderId { get; set; }
[ForeignKey("OrderHeaderId")]
public OrderHeader OrderHeader { get; set; }
public int ProductId { get; set; }
[ForeignKey("ProductId")]
public Product Product { get; set; }
public int Count { get; set; }
public double Price { get; set; }
}
}
214) Now add these two class in ApplicationDbContetxt
216) Now make the interface of OrderHeader and OrderDetais one by one.
First we create the pubic Interface type class of OrderHeader of with the name
IOrderHeaderRepository.cs
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface IOrderHeaderRepository : IRepository<OrderHeader>
{
void Update(OrderHeader orderHeader);
}
}
217) Now add a public class of this OrderHeader class in Repository folder
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models;
using Microsoft.AspNetCore.Identity.UI.V4.Pages.Internal.Account.Manage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository
{
public class OrderHeaderRepository :
Repository<OrderHeader>,IOrderHeaderRepository
{
private readonly ApplicationDbContext _context;
public OrderHeaderRepository(ApplicationDbContext
context) : base(context)
{
_context = context;
}
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository.IRepository
{
public interface IOrderDetailsRepository :
IRepository<OrderDetails>
{
void Update(OrderDetails orderDetails);
}
}
using Ecomm_Project2.DataAccess.Data;
using Ecomm_Project2.DataAccess.Repository.IRepository;
using Ecomm_Project2.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.DataAccess.Repository
{
public class OrderDetailsRepository :
Repository<OrderDetails>, IOrderDetailsRepository
{
private readonly ApplicationDbContext _context;
public
OrderDetailsRepository(ApplicationDbContext context) :
base(context)
{
_context = context;
}
// order status
public const string OrderStatusPending = "Pending";
public const string OrderStatusApproved = "Approved";
public const string OrderStatusInProgress = "Processing";
public const string OrderStatusShipped = "Shipped";
public const string OrderStatusCancelled = "Cancelled";
public const string OrderStatusRefunded = "Refunded";
//Payment status
public const string PaymentStatusPending = "Pending";
public const string PaymentStatusApproved = "Approved";
public const string PaymentStatusDelayPayment = "PaymentStatusDelay";
public const string PaymentStatusRejected = "Rejected";
public static double GetPriceBasedOnQuantity(double quantity, double price, double price50, double
price100)
{
if (quantity < 50)
return price;
else if (quantity < 100)
return price50;
else
return price100;
}
// <p>hello</p>
public static string ConvertToRawHtml(string source)
{
char[] array = new char[source.Length];
int arrayIndex = 0;
bool inside = false;
for(int i = 0; i < source.Length; i++)
{
char let = source[i]; // <p>
if(let == '<')
{
inside = true;
continue;
}
if(let == '>')
{
inside = false;
continue;
}
if (!inside)
{
array[arrayIndex] = let; // hello
arrayIndex++;
}
}
return new string( array, 0, arrayIndex );
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Models.ViewModels
{
public class ShoppingCartVM
{
public IEnumerable<ShoppingCart> ListCart { get; set; }
public OrderHeader OrderHeader { get; set; }
}
}
226) Now write the code in Index action of CartController.cs file for get the data from
multiple tables in the Details of the Product
[BindProperty]
public ShoppingCartVM ShoppingCartVM { get; set; }
}
return View(ShoppingCartVM);
}
@model Ecomm_Project2.Models.ViewModels.ShoppingCartVM
<form method="post">
<br />
@if (Model.ListCart.Count() > 0)
{
<div class="backgroundWhiteBorder">
<div class="container">
<div class="card">
<div class="card-header bg-dark text-light ml-0 row container">
<div class="col-6">
<i class="fa fa-shopping-cart"></i>
Shopping Cart
</div>
<div class="col-6 text-right">
<a asp-controller="Home" asp-action="Index" class="btn btn-outline-info btn-sm">Continue
Shopping</a>
</div>
</div>
<div class="card-body">
@foreach (var item in Model.ListCart)
{
var amount = item.Price * item.Count;
<div class="row">
<div class="d-none d-lg-block col-lg-1 text-center py-2">
<img src="@item.Product.ImageUrl" class="rounded" width="100%" />
</div>
<div class="col-12 text-sm-center col-lg-6 text-lg-left">
<h6>@item.Product.Title</h6>
<p><small>@Html.Raw(item.Product.Description)</small></p>
</div>
<div class="col-12 text-sm-center col-lg-5 text-lg-right row">
<div class="col-4 text-md-right" style="padding-top:5px;">
<h6>@item.Price<span class="text-muted">x</span>@item.Count = @amount</h6>
</div>
<div class="col-6 col-sm-4 col-lg-6">
<div class="float-right mx-1">
<a asp-action="plus" asp-route-id="@item.Id" class="btn btn-primary">
<i class="fas fa-plus"></i>
</a>
</div>
<div class="float-right mx-1">
<a asp-action="minus" asp-route-id="@item.Id" class="btn btn-danger">
<i class="fas fa-minus"></i>
</a>
</div>
</div>
<div class="col-2 col-sm-4 col-lg-2 text-right">
<a asp-action="delete" asp-route-id="@item.Id" class="btn btn-outline-danger">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
</div>
}
<hr />
<div class="row">
<div class="col-12 col-md-6 offset-md-6 col-lg-4 offset-lg-8 pr-4">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between bg-light">
<span class="text-info"> Total (USD)</span>
<strong class="text-info">$ <span id="txtOrderTotal">@Model.OrderHeader.OrderTotal</span></strong>
</li>
</ul>
</div>
</div>
</div>
<div class="card-footer">
<div class="card-footer row">
</form>
228) Now write the code for increment/ decrement and delete of the item quantity in
CartController
// session
var claimIdentity = (ClaimsIdentity)User.Identity;
var claim = claimIdentity.FindFirst(ClaimTypes.NameIdentifier);
if(claim != null)
{
var count = _unitOfWork.ShoppingCart.GetAll(sc => sc.ApplicationUserId ==
claim.Value).ToList().Count;
HttpContext.Session.SetInt32(SD.Ss_CartSessionCount, count);
}
return RedirectToAction(nameof(Index));
229) Now add write the code of Summary in CartController. So create the View of Summary
@model Ecomm_Project2.Models.ViewModels.ShoppingCartVM
<form method="post">
<br />
<div class="backgroundWhiteBorder">
<div class="container">
<div class="card">
<div class="card-header bg-dark text-light ml-0 row container">
<div class="col-6">
<i class="fa fa-shopping-cart"></i>
Order Summary
</div>
<div class="col-6 text-right">
<a class="btn btn-outline-info btn-sm" asp-action="Index">Back to Cart</a>
</div>
</div>
<div class="card-body">
<div class="container rounded p-2">
<div class="row">
<div class="col-12 col-lg-6 pb-4">
<div class="row">
<h4 class="d-flex justify-content-between align-items-center mb-3">
<span class="text-info">PickUp Details:</span>
</h4>
</div>
<div class="row my-1">
<div class="col-3">
<label>Name</label>
</div>
<div class="col-9">
<input type="text" asp-for="OrderHeader.Name" class="form-control" />
</div>
</div>
<div class="row my-1">
<div class="col-3">
<label>Phone</label>
</div>
<div class="col-9">
<input type="text" asp-for="OrderHeader.PhoneNumber" class="form-control" />
</div>
</div>
<div class="row my-1">
<div class="col-3">
<label>Street Address</label>
</div>
<div class="col-9">
<input type="text" asp-for="OrderHeader.StreetAddress" class="form-control" />
</div>
</div>
<div class="row my-1">
<div class="col-3">
<label>City</label>
</div>
<div class="col-9">
<input type="text" asp-for="OrderHeader.City" class="form-control" />
</div>
</div>
<div class="row my-1">
<div class="col-3">
<label>State</label>
</div>
<div class="col-9">
<input type="text" asp-for="OrderHeader.State" class="form-control" />
</div>
</div>
<div class="row my-1">
<div class="col-3">
<label>Postal Code</label>
</div>
<div class="col-9">
<input type="text" asp-for="OrderHeader.PostalCode" class="form-control" />
</div>
</div>
</div>
<div class="col-12 col-lg-5 offset-lg-1">
<h4 class="d-flex justify-content-between align-items-center mb-3">
<span class="text-info">Order Summary:</span>
</h4>
<ul class="list-group mb-3">
<li class="list-group-item d-flex justify-content-between">
<div>
<h6 class="my-0">--TITLE--</h6>
<small class="text-muted">Quantity: --COUNT--</small>
</div>
<span class="text-muted">$ --PRICE* COUNT--</span>
</li>
<li class="list-group-item d-flex justify-content-between bg-light">
<small class="text-info">Total (USD)</small>
<strong class="text-info">$--GRAND TOTAL--</strong>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-12 col-md-8 pt-2">
<p style="color:maroon; font-size:14px;">Estimate Arrival Date:
@DateTime.Now.AddDays(7).ToShortDateString() - @DateTime.Now.AddDays(14).ToShortDateString()</p>
</div>
<div class="col-12 col-md-4">
230) Write the code for Order Summary details in Summary.cshtml file
231) Now write the code for Place Order data submit on button click in CartController.cs
[HttpPost]
[AutoValidateAntiforgeryToken]
[ActionName("Summary")]
public IActionResult SummaryPost()
{
var claimsIdentity = (ClaimsIdentity)User.Identity;
var claim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
ShoppingCartVM.OrderHeader.ApplicationUser = _unitOfWork.ApplicationUser.
FirstOrDefault(u => u.Id == claim.Value, includeProperties: "Company");
ShoppingCartVM.OrderHeader.PaymentStatus = SD.PaymentStatusPending;
ShoppingCartVM.OrderHeader.OrderStatus = SD.OrderStatusPending;
ShoppingCartVM.OrderHeader.OrderDate = DateTime.Now;
ShoppingCartVM.OrderHeader.ApplicationUserId = claim.Value;
_unitOfWork.OrderHeader.Add(ShoppingCartVM.OrderHeader);
_unitOfWork.Save();
@model int
<div class="container row">
<div class="col-12 text-center">
<h1 class="text-primary text-center">Order Submitted Successfully</h1><br />
<img src="~/images/success.webp" width="50%" />
</div>
<div class="col-12 text-center" style="color:green">
<br />
Thank you for your order! <br />
We have received your order and we will send a follow up email shortly!
<br />
Your Order Number is :@Model
</div>
</div>
233) Now for payment gateway firstly we create an account in Stripe.com website
By these steps we can create a new account.
234) Now create a new class StripeSettings in Ecomm_Project2.Utility
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace Ecomm_Project2.Utility
{
public class StripeSettings
{
public string Publishablekey { get; set; }
public string Secretkey { get; set; }
}
}
236) Now go to the main project and right click on it and install the Stripe package
@*Stripe *@
@{
var orderTotalAmount = Model.OrderHeader.OrderTotal * 100;
}
<script src="https://checkout.stripe.com/checkout.js"
class="stripe-button"
data-key="@Stripe.Value.Publishablekey"
data-amount="@orderTotalAmount"
data-name="Book Shopping Project"
data-description="Get Your Book Now"
data-locale="auto"
data-label="Place Order"
data-allow-remeber-me="false"
data-image="https://www.shutterstock.com/image-photo/businessman-pressing-on-virtual-screen-260nw-
489207220.jpg">
</script>
239) Now add the stripe token for user security checking in the CartController
Firstly, add the stripe token as a parameter
#region Stripe
if (stripeToken == null)
{
ShoppingCartVM.OrderHeader.PaymentDueDate = DateTime.Now.AddDays(30);
ShoppingCartVM.OrderHeader.PaymentStatus = SD.PaymentStatusDelayPayment;
ShoppingCartVM.OrderHeader.OrderStatus = SD.OrderStatusApproved;
}
else
{
// payment process
var options = new ChargeCreateOptions()
{
Amount = Convert.ToInt32(ShoppingCartVM.OrderHeader.OrderTotal),
Currency = "usd",
Description = "Order Id : " + ShoppingCartVM.OrderHeader.Id,
Source = stripeToken
};
//Payment
var service = new ChargeService();
Charge charge = service.Create(options);
if (charge.BalanceTransactionId == null)
ShoppingCartVM.OrderHeader.PaymentStatus = SD.PaymentStatusRejected;
else
ShoppingCartVM.OrderHeader.TransactionId = charge.BalanceTransactionId;
if(charge.Status.ToLower() == "succeeded")
{
ShoppingCartVM.OrderHeader.PaymentStatus = SD.PaymentStatusApproved;
ShoppingCartVM.OrderHeader.OrderStatus = SD.OrderStatusApproved;
ShoppingCartVM.OrderHeader.OrderDate = DateTime.Now;
}
_unitOfWork.Save();
}
#endregion
240) Now for hide the Place Order button in Order Summary go to Summary.cshtml, add a
JavaScript code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Utility
{
public class EmailSettings
{
public String PrimaryDomain { get; set; }
public int PrimaryPort { get; set; }
public String SecondaryDomain { get; set; }
public int SecondaryPort { get; set; }
public String UsernameEmail { get; set; }
public String UsernamePassword { get; set; }
public String FromEmail { get; set; }
public String ToEmail { get; set; }
public String CcEmail { get; set; }
}}
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace Ecomm_Project2.Utility
{
public class EmailSender : IEmailSender
{
private EmailSettings _emailSettings { get; }
public EmailSender(IOptions<EmailSettings> emailSettings)
{
_emailSettings = emailSettings.Value;
}
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
Execute(email, subject, htmlMessage).Wait();
return Task.FromResult(0);
}
public async Task Execute(string email, string subject, string message)
{
try
{
string toEmail = string.IsNullOrEmpty(email) ? _emailSettings.ToEmail : email;
MailMessage mail = new MailMessage()
{
From = new MailAddress(_emailSettings.UsernameEmail, "My Email Name..")
};
mail.To.Add(toEmail);
mail.CC.Add(_emailSettings.CcEmail);
mail.Subject = "Book Shopping App : " + subject;
mail.Body = message;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
using (SmtpClient smtp = new SmtpClient(_emailSettings.PrimaryDomain,
_emailSettings.PrimaryPort))
{
smtp.Credentials = new NetworkCredential(_emailSettings.UsernameEmail,
_emailSettings.UsernamePassword);
smtp.EnableSsl = true;
await smtp.SendMailAsync(mail);
}
}
catch (Exception ex)
{
string str = ex.Message;
}
}
}
}
245) Now go to the Register.cshtml.cs and make the code un-comment which was comment
before
246) Now go to the CartController.cs and write the code for email sender confirmation
247) Now go to the Index.cshtml page and write the confirmation condition at here
248) Now go to CartController.cs file and add the EmailConfirmation in IndexPost action
Project 2 (WEB API/ API)
3) Next
6) Now create a new folder Models in main project and add a new class NationalPark.cs in this
folder
using System;
using System.ComponentModel.DataAnnotations;
namespace NationalParkAPI.Models
{
public class NationalPark
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string State { get; set; }
public byte[] Picture { get; set; }
public DateTime Created { get; set; }
public DateTime Established { get; set; }
}
}
7) Now add a new folder Data in main project and a new class ApplicationdbContext in it
using Microsoft.EntityFrameworkCore;
using NationalParkAPI.Models;
namespace NationalParkAPI.Data
{
public class ApplicationDbContext:DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options):base(options)
{
}
public DbSet<NationalPark> NationalParks { get; set; }
}
}
8) Now add the connection string in Startup.cs file
using NationalParkAPI.Migrations;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace NationalParkAPI.Models
{
public class Trail
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Distance { get; set; }
[Required]
public string Elevation { get; set; }
public DateTime DateCreated { get; set; }
public enum DifficultyType { Easy, Moderate, Difficult }
public DifficultyType Difficulty { get; set; }
public int NationalParkId { get; set; }
[ForeignKey("NationalParkId")]
public NationalPark NationalPark { get; set; }
}
}
11) Now add this Model class Trail class in ApplicationDbContext class
12) Now again add the migration and update database
13) Now create a new Repository folder in main project and a sub folder IRepository in it.
14) Now add a new Interface type class INationalParkRepository in IRepository folder.
INationalParkRepository.cs
using NationalParkAPI.Models;
using System.Collections.Generic;
namespace NationalParkAPI.Repository.IRepository
{
public interface INationalParkRepository
{
ICollection<NationalPark> GetNationalParks();
NationalPark GetNationalPark(int nationalParkId);
bool NationalParkExists(int nationalParkId);
bool NationalParkExists (string nationalParkName);
bool CreateNationalPark(NationalPark nationalPark);
bool UpdateNationalPark(NationalPark nationalPark);
bool DeleteNationalPark(NationalPark nationalPark);
bool Save();
}
}
15) Now add a new class NationalParkRepository in Repository folder.
NationalParkRepository.cs
using Microsoft.AspNetCore.Authentication;
using NationalParkAPI.Data;
using NationalParkAPI.Models;
using NationalParkAPI.Repository.IRepository;
using System.Collections.Generic;
using System.Linq;
namespace NationalParkAPI.Repository
{
public class NationalParkRepository : INationalParkRepository
{
private readonly ApplicationDbContext _context;
public NationalParkRepository(ApplicationDbContext context)
{
_context = context;
}
public bool CreateNationalPark(NationalPark nationalPark)
{
_context.NationalParks.Add(nationalPark);
return Save();
}
16) Now create a interface type class ITrailRepository in the IRepository folder.
ITrailRepository.cs
using NationalParkAPI.Models;
using System.Collections;
using System.Collections.Generic;
namespace NationalParkAPI.Repository.IRepository
{
public interface ITrailRepository
{
ICollection<Trail> GetTrails();
ICollection<Trail> GetTrailsInNationalPark(int nationalParkId);
Trail GetTrail(int trailId);
bool TrailExists(int trailId);
bool TrailExists(string trailName);
bool CreateTrail(Trail trail);
bool UpdateTrial(Trail trail);
bool DeleteTrail(Trail trail);
bool Save();
}
}
TrailRepository.cs
using Microsoft.EntityFrameworkCore;
using NationalParkAPI.Data;
using NationalParkAPI.Models;
using NationalParkAPI.Repository.IRepository;
using System;
using System.Collections.Generic;
using System.Linq;
namespace NationalParkAPI.Repository
{
public class TrailRepository : ITrailRepository
{
private readonly ApplicationDbContext _context;
public TrailRepository(ApplicationDbContext context)
{
_context = context;
}
19) Now create two new classes to NationalPark class and Trail Class in new sub folder DTOs of
Models folder for make them more secure through DTOs (Data Transfer Objects).
DTO means it adds a new layer between the User and Database(db and controller) for make
more secure. In it the only models/columns are add those are represent to the user and other
will be hide.
{
Db model rep dto controller (Frontend)
// db model dto
// dto model db
NationalParkDto.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
namespace NationalParkAPI.Models.DTOs
{
public class NationalParkDto
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string State { get; set; }
public byte[] Picture { get; set; }
public DateTime Created { get; set; }
public DateTime Established { get; set; }
}
}
TrailDto.cs
using System.ComponentModel.DataAnnotations;
using static NationalParkAPI.Models.Trail;
namespace NationalParkAPI.Models.DTOs
{
public class TrailDto
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Distance { get; set; }
[Required]
public string Elevation { get; set; }
public DifficultyType Difficulty { get; set; }
public int NationalParkId { get; set; }
public NationalPark NationalPark { get; set; }
}
}
MappingProfile.cs
using AutoMapper;
using NationalParkAPI.Models;
using NationalParkAPI.Models.DTOs;
using System.Net.Sockets;
using System.Security.Cryptography;
namespace NationalParkAPI.DTOMapping
{
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<NationalParkDto, NationalPark>().ReverseMap();
CreateMap<TrailDto, Trail>().ReverseMap();
}
}
}
22) Now go to the Startup.cs file and add the MappingProfile.cs in Mapping
23) Now add a new API Controller-Empty NationalParkController in the controller folder of main
project
NationalParkController.cs
using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NationalParkAPI.Models;
using NationalParkAPI.Models.DTOs;
using NationalParkAPI.Repository.IRepository;
using System.Linq;
namespace NationalParkAPI.Controllers
{
[Route("api/NationalPark")]
[ApiController]
public class NationalParkController : Controller
{
private readonly INationalParkRepository _nationalParkRepository;
private readonly IMapper _mapper;
public NationalParkController(INationalParkRepository nationalParkRepository, IMapper mapper)
{
_nationalParkRepository = nationalParkRepository;
_mapper = mapper;
}
[HttpGet]
public IActionResult GetNationalParks()
{
var nationalParkListDto = _nationalParkRepository.GetNationalParks().ToList().
Select(_mapper.Map<NationalPark, NationalParkDto>);
return Ok(nationalParkListDto); // 200
}
[HttpGet("{nationalParkId:int}",Name = "GetNationalPark")]
public IActionResult GetNationalPark(int nationalParkId)
{
var nationalPark = _nationalParkRepository.GetNationalPark(nationalParkId);
if (nationalPark == null) return NotFound(); //404
var nationalParkDto = _mapper.Map<NationalParkDto>(nationalPark);
return Ok(nationalParkDto); //200
}
[HttpPost]
public IActionResult CreateNationalPark([FromBody]NationalParkDto nationalParkDto)
{
if(nationalParkDto == null) return BadRequest(ModelState);
if (_nationalParkRepository.NationalParkExists(nationalParkDto.Name))
{
ModelState.AddModelError("", "National Park already in DB");
return StatusCode(StatusCodes.Status500InternalServerError);
}
if (!ModelState.IsValid) return BadRequest(ModelState);
TrailController.cs
using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NationalParkAPI.Models;
using NationalParkAPI.Models.DTOs;
using NationalParkAPI.Repository.IRepository;
using System.Linq;
namespace NationalParkAPI.Controllers
{
[Route("api/Trail")]
[ApiController]
public class TrailController : ControllerBase
{
private readonly ITrailRepository _trailRepository;
private readonly IMapper _mapper;
public TrailController(ITrailRepository trailRepository, IMapper mapper)
{
_trailRepository = trailRepository;
_mapper = mapper;
}
[HttpGet]
public IActionResult GetTrails()
{
return Ok(_trailRepository.GetTrails().ToList().Select(_mapper.Map<Trail, TrailDto>));
}
[HttpGet("{trailId=int}", Name = "GetTrail")]
public IActionResult GetTrail(int trailId)
{
var trail = _trailRepository.GetTrail(trailId);
if (trail == null) return NotFound();
return Ok(_mapper.Map<TrailDto>(trail));
}
[HttpPost]
public IActionResult CreateTrail([FromBody] TrailDto trailDto)
{
if (trailDto == null) return BadRequest(ModelState);
if (!ModelState.IsValid) return NotFound();
if (_trailRepository.TrailExists(trailDto.Name))
{
ModelState.AddModelError("", $"Trail already in db:{trailDto.Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
var trail = _mapper.Map<Trail>(trailDto);
if (!_trailRepository.CreateTrail(trail))
{
ModelState.AddModelError("", $"Somthing went wrong while save the trail : {trail.Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
//return Ok();
return CreatedAtRoute("GetTrail", new { trailId = trail.Id }, trail);
}
[HttpPut]
public IActionResult UpdateTrail([FromBody] TrailDto trailDto)
{
if (trailDto == null) return BadRequest();
if (!ModelState.IsValid) return BadRequest();
25) Now add a new project ParkWebApp in the Main Solution as steps below
26) Now add the for multiple page start go to the solution and do some settings
namespace ParkWebApp
{
public static class SD
{
public static string APIBaseUrl = "https://localhost:44388/";
public static string NationalParkAPIPath = APIBaseUrl + "api/NationalPark/";
public static string TrailAPIPath = APIBaseUrl + "api/Trail/";
}
}
28) Now add the new NationalPark.cs class in the models folder of the ParkWebApp project
using System.ComponentModel.DataAnnotations;
using System;
namespace ParkWebApp.Models
{
public class NationalPark
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string State { get; set; }
public byte[] Picture { get; set; }
public DateTime Created { get; set; }
public DateTime Established { get; set; }
}
}
29) Now again add a new class Trail.cs in Models folder of the ParkWebApp project
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System;
namespace ParkWebApp.Models
{
public class Trail
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Distance { get; set; }
[Required]
public string Elevation { get; set; }
public DateTime DateCreated { get; set; }
public enum DifficultyType { Easy, Moderate, Difficult }
public DifficultyType Difficulty { get; set; }
[Display(Name="National Park")]
public int NationalParkId { get; set; }
public NationalPark NationalPark { get; set; }
}
}
30) Now add a new Repository folder in the ParkWebApp project. And also add new subfolder in the
Repository folder
31) Now for creating a Generic repository add a new interface IRepository in the subfolder of
Repository folder IRepository, at ParkWebApp
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ParkWebApp.Repository.IRepository
{
public interface IRepository<T> where T:class
{
Task<T> GetAsync(string url, int id);
Task<IEnumerable<T>> GetAllAsync(string url);
Task<bool> CreateAsync(string url, T objToCreate);
Task<bool> UpdateAsync(string url, T objToUpdate);
Task<bool> DeleteAsync(string url, int id);
}
32) Now add a new class Repository in the Repository folder of ParkWebApp project
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json;
using ParkWebApp.Repository.IRepository;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace ParkWebApp.Repository
{
public class Repository<T> : IRepository<T> where T : class
{
private readonly IHttpClientFactory _httpClientFactory;
public Repository(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
}
}
33) Now add a new interface INationalParkRepository in IRepository folder in ParkWebApp project
using ParkWebApp.Models;
namespace ParkWebApp.Repository.IRepository
{
public interface INationalParkRepository:IRepository<NationalPark>
{
}
}
using ParkWebApp.Models;
using ParkWebApp.Repository.IRepository;
using System.Net.Http;
namespace ParkWebApp.Repository
{
public class NationalParkRepository : Repository<NationalPark>, INationalParkRepository
{
private readonly IHttpClientFactory _httpClientFactory;
public NationalParkRepository(IHttpClientFactory httpClientFactory) : base(httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
}
}
35) Now again add a new Interface ITrailRepository in IRepository folder of ParkWebApp project
using ParkWebApp.Models;
namespace ParkWebApp.Repository.IRepository
{
public interface ITrailRepository : IRepository<Trail>
{
}
}
36) Now add a new class TrailRepository in Repository folder of ParkWebApp project
using ParkWebApp.Models;
using ParkWebApp.Repository.IRepository;
using System.Net.Http;
namespace ParkWebApp.Repository
{
public class TrailRepository : Repository<Trail>, ITrailRepository
{
private readonly IHttpClientFactory _httpClientFactory;
public TrailRepository(IHttpClientFactory httpClientFactory) : base(httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
}
}
37) Now add these Interfaces and Classes in Startup.cs of ParkWebApp
38) Now add a new controller NationalParkController in Controllers folder of ParkWebApp project
using Microsoft.AspNetCore.Mvc;
using ParkWebApp.Repository.IRepository;
namespace ParkWebApp.Controllers
{
public class NationalParkController : Controller
{
private readonly INationalParkRepository _nationalParkRepository;
public NationalParkController(INationalParkRepository nationalParkRepository)
{
_nationalParkRepository = nationalParkRepository;
}
40) Now add the National Park controller in the navbar of Home page, so go the _Layout.cshtml
file
41) Now add the links of CSS and JavaScript in the _Layout.cshtml file
<div class="row">
<div class="col-6">
<h2 class="text-primary">National Park List</h2>
</div>
<div class="col-6 text-right">
<a class="btn btn-info" asp-action="Upsert">
<i class="fas fa-plus"></i> New National Park
</a>
</div>
</div>
<div class="p-3">
<table id="tblData" class="table table-striped table-active table-bordered">
<thead>
<tr>
<th>Name</th>
<th>State</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
43) Now write the code for get the API data in the table at the NationalParkController.cs file
in the ParkWebApp project
44) Now add the new js file nationalPark.js in the js folder of wwwroot folder of the ParkWebApp
project
45) Now write the code to show the data in list/table in nationalPark.js file
var dataTable;
$(document).ready(function () {
loadDataTable();
})
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": {
"url": "NationalPark/GetAll",
"type": "GET",
"datatype": "json"
},
"columns": [{ "data": "name", "width": "40%" },{ "data": "state", "width": "40%" },
{
"data": "id", "render": function (data) {
return `
<div class="text-center">
<a href="NationalPark/Upsert/${data}" class = "btn btn-info">
<i class="fas fa-edit"></i>
</a>
<a class = "btn btn-danger" onclick=Delete("/NationalPark/Delete/${data}")>
<i class="fas fa-trash-alt"></i>
</a>
</div>
`;
}
}
]})}
function Delete(url) {
swal({
text: "Delete Information !!",
title: "Want to delete data ?",
icon: "warning",
buttons: true,
dangerModel: true
}).then((willDelete) => {
if (willDelete) {
$.ajax({
url: url,
type: "DELETE",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
}
})
}})}
@model ParkWebApp.Models.NationalPark
@{
ViewData["Title"] = "Upsert";
var title = Model.Id != 0 ? "Edit National Park" : "New National Park";
var saveupdate = Model.Id != 0 ? "Update" : "Save";
}
<form method="post" enctype="multipart/form-data">
@if (Model.Id != 0)
{
<input type="hidden" asp-for="@Model.Id" />
}
<div class="row border">
<div class="col-10 border-bottom p-2 m-2">
<h1 class="text-primary">@title</h1>
</div>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-8 p-2">
<div class="form-group row">
<div class="col-4">
<label asp-for="Name"></label>
</div>
<div class="col-8">
<input asp-for="Name" class="form-control" />
<span class="text-danger" asp-validation-for="Name"></span>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label asp-for="State"></label>
</div>
<div class="col-8">
<input asp-for="State" class="form-control" />
<span class="text-danger" asp-validation-for="State"></span>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label asp-for="Picture"></label>
</div>
<div class="col-8">
@*<input asp-for="Name" class="form-control" />*@
<input type="file" name="files" id="projectImage" asp-for="Picture" class="form-control"
multiple />
<span class="text-danger" asp-validation-for="Picture"></span>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label asp-for="Established"></label>
</div>
@{
var dateEst = "";
if (Model.Id != 0)
{
dateEst = Model.Established.ToShortDateString();
}
}
<div class="col-8">
<input type="text" id="datepickers" value="@dateEst" asp-for="Established" class="form-
control" />
49) Now write the code for Update the information in NationalParkController.cs
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Upsert(NationalPark nationalPark)
{
if (ModelState.IsValid)
{
var files = HttpContext.Request.Form.Files;
if (files.Count > 0)
{
byte[] p1 = null;
using (var fs1 = files[0].OpenReadStream())
{
using (var ms1 = new MemoryStream())
{
fs1.CopyTo(ms1);
p1 = ms1.ToArray();
}
}
nationalPark.Picture = p1;
}
else
{
var npInDb = await _nationalParkRepository.GetAsync(SD.NationalParkAPIPath,
nationalPark.Id);
nationalPark.Picture = npInDb.Picture;
}
if (nationalPark.Id == 0)
await _nationalParkRepository.CreateAsync(SD.NationalParkAPIPath, nationalPark);
else
await _nationalParkRepository.UpdateAsync(SD.NationalParkAPIPath, nationalPark);
return RedirectToAction(nameof(Index));
}
else
return View(nationalPark);
}
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Serialization;
using ParkWebApp.Repository.IRepository;
namespace ParkWebApp.Controllers
{
public class TrailController : Controller
{
private readonly ITrailRepository _trailRepository;
public TrailController(ITrailRepository trailRepository)
{
_trailRepository = trailRepository;
}
54) Now write the code for Get the data in the Json form in the TrailController.cs file
55) Now write the code for show the data in table from the Json form in the trail.js file. So
create the trail.js file in the js folder at wwwroot folder in ParkWebApp project
var dataTable;
$(document).ready(function () {
loadDataTable();
})
function loadDataTable() {
dataTable = $('#tblData').DataTable({
"ajax": {
"url": "Trail/GetAll",
"type": "GET",
"datatype": "json"
},
"columns": [
{ "data": "nationalPark.name", "width": "20%" },
{ "data": "name", "width": "20%" },
{ "data": "distance", "width": "20%" },
{ "data": "elevation", "width": "20%" },
{
"data": "id", "render": function (data) {
return `
<div class="text-center">
<a href="Trail/Upsert/${data}" class = "btn btn-info">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger" onclick=Delete("Trail/Delete/${data}")>
<i class="fas fa-trash-alt"></i>
</a>
</div>
`;
}
}
]
})
}
function Delete(url) {
/*debugger;*/
swal({
text: "Delete Information !!",
title: "Want to delete data ?",
buttons: true,
icon: "warning",
dangerModel: true
}).then((willDelete) => {
if (willDelete) {
$.ajax({
url: url,
type: "DELETE",
success: function (data) {
if (data.success) {
toastr.success(data.message);
dataTable.ajax.reload();
}
else {
toastr.error(data.message);
}
}
})
}
})
}
So, create a new sub folder ViewModels in the Models folder. In this folder add a new class
TrailVM
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.VisualBasic.FileIO;
using System.Collections;
using System.Collections.Generic;
namespace ParkWebApp.Models.ViewModels
{
public class TrailVM
{
public Trail Trail { get; set; }
public IEnumerable<SelectListItem> nationalParkList { get; set; }
}
}
59) Now write the code for Insert the data in TrailController.cs
60) Before write the code of Upsert firstly we add a include method in the NationalParkAPI
project, TrialRepository
@model ParkWebApp.Models.ViewModels.TrailVM
@{
ViewData["Title"] = "Upsert";
var title = Model.Trail.Id != 0 ? "Edit Trail" : "New Trail";
var saveupdate = Model.Trail.Id != 0 ? "Update" : "Save";
}
<form method="post" asp-action="Upsert">
<div class="row border">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@if (Model.Trail.Id != 0)
{
<input type="hidden" asp-for="@Model.Trail.Id" />
}
<div class="col-8 border-bottom">
<h2 class="text-primary">@title</h2>
</div>
</div>
<div class="col-8">
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Trail.NationalParkId"></label>
</div>
<div class="col-8">
@Html.DropDownListFor(m => Model.Trail.NationalParkId,
Model.nationalParkList,"Select National Park",
new {@class = "form-control"})
<span asp-validation-for="Trail.NationalParkId" class="text-danger"></span>
</div>
</div>
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Trail.Name"></label>
</div>
<div class="col-8">
<input asp-for="Trail.Name" class="form-control" />
<span asp-validation-for="Trail.Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Trail.Difficulty"></label>
</div>
<div class="col-8">
<select asp-for="Trail.Difficulty" asp-
items="Html.GetEnumSelectList<ParkWebApp.Models.Trail.DifficultyType>()"
class="form-control"></select>
<span asp-validation-for="Trail.Difficulty" class="text-danger"></span>
</div>
</div>
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Trail.Distance"></label>
</div>
<div class="col-8">
<input asp-for="Trail.Distance" class="form-control" />
<span asp-validation-for="Trail.Distance" class="text-danger"></span>
</div>
</div>
<div class="form-group row p-2 m-2">
<div class="col-4">
<label asp-for="Trail.Elevation"></label>
</div>
<div class="col-8">
<input asp-for="Trail.Elevation" class="form-control" />
<span asp-validation-for="Trail.Elevation" class="text-danger"></span>
</div>
</div>
<div class="form-group row p-2 m-2">
<div class="col-4 offset-4">
<button type="submit" class="btn btn-success form-control">@saveupdate</button>
</div>
<div class="col-4">
<a asp-action="Index" class="btn btn-primary form-control">Back to List</a>
</div>
</div>
</div>
</form>
@section scripts{
<partial name="_ValidationScriptsPartial" />
}
62) Now write the code of Save and Update of Trail information in TrailController.cs
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Upsert(TrailVM trailVM)
{
if (ModelState.IsValid)
{
if (trailVM.Trail.Id == 0)
await _trailRepository.CreateAsync(SD.TrailAPIPath, trailVM.Trail);
else
await _trailRepository.UpdateAsync(SD.TrailAPIPath, trailVM.Trail);
return RedirectToAction(nameof(Index));
}
else
{
IEnumerable<NationalPark> nationalParks = await _nationalParkRepository.
GetAllAsync(SD.NationalParkAPIPath);
trailVM = new TrailVM()
{
Trail = new Trail(),
nationalParkList = nationalParks.Select(np => new SelectListItem()
{
Text = np.Name,
Value = np.Id.ToString()
})
};
return View(trailVM);
}
}
63) Now write the Delete API code of Trail data in the TrailController.cs
64) Now to show the all data on the Home page in ParkWebApp project, we create a Index view. But
firstly, we add the INationalParkRepository and ITrailRepository in the HomeControlle
65) Now add a new class as a ViewModel IndexVM in the Models ViewModels
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Routing.Tree;
using System.Collections;
using System.Collections.Generic;
namespace ParkWebApp.Models.ViewModels
{
public class IndexVM
{
public IEnumerable<NationalPark> NationalParkList { get; set; }
public IEnumerable<Trail> TrailList { get; set; }
}
}
66) Now add the this IndexVM class in the HomeControler.cs
@model ParkWebApp.Models.ViewModels.IndexVM
@{
ViewData["Title"] = "Home Page";
}
// <tr>
// <td>@trailemp</td>
// <td>@trailemp</td>
// <td>@trailemp</td>
// <td>@trailemp</td>
// </tr>
// }
//}
}
</tbody>
</table>
</div>
</div>
</div>
<div class="col-12 col-lg-4 text-center">
@{
var base64 = Convert.ToBase64String(nationalPrak.Picture);
var finalStr = string.Format("data:image;base64,{0}", base64);
}
<img src="@finalStr" class="card-img-top p-2 rounded" width="100%" />
</div>
</div>
</div>
<br />
</div>
</div>
</div>
68) Now go to the NationalParkAPI project, here in the Models folder, add a new model class User
in it
using Microsoft.EntityFrameworkCore.Query;
using System.ComponentModel.DataAnnotations.Schema;
namespace NationalParkAPI.Models
{
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Role { get; set; }
[NotMapped]
public string Token { get; set; }
}
}
69) Now add this Model in the ApplicationDbContext
using NationalParkAPI.Models;
namespace NationalParkAPI.Repository.IRepository
{
public interface IUserRepository
{
bool IsUniqueUser(string username);
User Authenticate(string userName, string password);
User Register(string userName, string password);
}
}
72) Now add the new class UserRepository in the Repository folder
using NationalParkAPI.Data;
using NationalParkAPI.Models;
using NationalParkAPI.Repository.IRepository;
using System.Linq;
namespace NationalParkAPI.Repository
{
public class UserRepository : IUserRepository
{
private readonly ApplicationDbContext _context;
private readonly AppSettings _appSettings;
public UserRepository(ApplicationDbContext context, IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public User Authenticate(string userName, string password)
{
var userInDb = _context.Users.FirstOrDefault(u => u.UserName == userName && u.Password ==
password);
if (userInDb == null) return null;
userInDb.Password = "";
return userInDb;
}
74) Now add a new API controller UserController in the Controllers folder of the NationalParkAPI
project
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NationalParkAPI.Models;
using NationalParkAPI.Repository.IRepository;
namespace NationalParkAPI.Controllers
{
[Route("api/user")]
[ApiController]
public class UserController : Controller
{
private readonly IUserRepository _userRepository;
public UserController(IUserRepository userRepository)
{
_userRepository = userRepository;
}
[HttpPost("register")]
public IActionResult Register([FromBody] User user)
{
if (ModelState.IsValid)
{
var isUniqueUser = _userRepository.IsUniqueUser(user.UserName);
if (!isUniqueUser)
return BadRequest("User in use!!");
var userInfo = _userRepository.Register(user.UserName, user.Password);
if (userInfo == null) return BadRequest();
}
return Ok();
}
}
}
75) Now add a new class UserVM in the Models folder, because there is no need to show all the
Information of the user during the login time. So for hide other information here we create
the a new model
namespace NationalParkAPI.Models
{
public class UserVM
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
76) Now create a new Authentication type method in the UserCotroller for check user correct or
not
77) Now for authorized the all pages here we add the Authorize in the NationalParkController and
TrailController
78) Now for apply the JWT (JSON WEB TOKEN) in the project here firstly we install the JWT
package
79) Now to get the token key there is add a new class AppSettings in the NationalParkAPI project
namespace NationalParkAPI
{
public class AppSettings
{
public string Secret { get; set; }
}
}
80) Now go to the appsettings.json file and create a new token id at here
81) Now go to the Startup page and add the JWT Authentication
82) Now go to the UserRepository login system add this JWT token for authorization by the token
83) Now add a new class ConfigureSwaggerOptions in the NationalPark project for configure the
authorization with the token
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Collections.Generic;
namespace NationalParkAPI
{
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
public void Configure(SwaggerGenOptions options)
{
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer Scheme,\r\n" +
"Enter 'Bearer' [space] and then your token in the text input below \r\n" +
"Example:Bearer 123456abcde \r\n" +
"Name:Authorization\r\n" +
"In header",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement() {
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header
},
new List<string>()
}
});
}
}
}
84) Now add this class in the Startup.cs file and also add the Authentication method