0% found this document useful (0 votes)
15 views388 pages

ASP.NET

ASP.NET is an open-source web framework by Microsoft for building modern web applications using .NET languages. It includes various runtimes like .NET Framework, .NET Core, and .NET Runtime, which support multiple platforms. The document also covers the differences between desktop, web, and mobile applications, as well as key concepts related to the Internet, web hosting, and domain names.

Uploaded by

gsaiteja2410
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views388 pages

ASP.NET

ASP.NET is an open-source web framework by Microsoft for building modern web applications using .NET languages. It includes various runtimes like .NET Framework, .NET Core, and .NET Runtime, which support multiple platforms. The document also covers the differences between desktop, web, and mobile applications, as well as key concepts related to the Internet, web hosting, and domain names.

Uploaded by

gsaiteja2410
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 388

ASP.

NET
ASP.NET is an Open-Source Web Framework, created by Microsoft, for building Modern Web Apps and
Services with .NET using C# or VB.NET or F# languages. ASP.NET extends the .NET platform with tools and libraries
specifically for building Web Apps.

.NET is Platform Independent i.e., applications that are developed by using .NET can run on multiple
Platform’s and to run .NET Applications on a machine that machine should be 1st installed with a software i.e., .NET
Runtime. Microsoft provided us 3 different .NET Runtimes that came over a period, like:
 .NET Framework Runtime
 .NET Core Runtime
 .NET Runtime

.NET Framework Runtime was launched in the year 2002 and this is available only for Windows Platforms.
The first version of this Runtime is 1.0 and the last version is 4.8.

.NET Core Runtime was launched in the year 2016 and this is available for multiple platforms like Windows,
Linux, and Mac. The first version of this Runtime is 1.0 and the last version is 3.1.

.NET Runtime is also same as .NET Core Runtime which was launched in the year 2020 and this is also
available for multiple platforms like Windows, Linux, and Mac. This is a combination of .NET Framework and .NET
Core and evolved as “One .NET”. The first version of .NET Runtime started with 5.0 and we call this as .NET 5 and the
latest is .NET 6.

In .NET Framework we have been provided with ASP.NET Framework for building Web Applications and
under this we have different options like:
 ASP.NET Web Forms
 ASP.NET MVC
 ASP.NET Web API

In .NET CORE, .NET 5, and so on, we have been provided with ASP.NET Core Framework for building Web
Applications and under this also we have different options again, like:
 ASP.NET Core Web App (Razor Pages)
 ASP.NET Core Web App (Model-View-Controller)
 ASP.NET Core Web API

Note: ASP.NET Core is the open-source version of ASP.NET that can be developed and run-on Windows, Linux,
macOS, and Docker. This was first released in 2016 and is a re-design of earlier Windows-Only versions of ASP.NET.
Performance is a key focus of ASP.NET Core which is faster than other popular web frameworks as per independent
TechEmpower benchmarks. Like the rest of .NET, ASP.NET is also open source on GitHub which has over 100,000
contributions and 3,700 companies have already contributed.

Applications what we use day to day are divided into different categories like:
 Desktop Applications
 Web Applications
 Mobile Applications

1
Desktop Applications means, these applications must be installed on our computer first to consume them.
Example: MS Office, Skype Messenger, Zoom, Browsers, Visual Studio, SQL Server Management Studio, etc.

Web Applications means, we install these applications on a centralized machine or server known as Web Server and
then clients all over the World can access these application by connecting to the Web Server thru Internet.
Example: Facebook, Gmail, Amazon, Flipkart, etc.

Mobile Applications are also like Desktop Applications only i.e., we need to install them on our Mobiles or Tablets
to consume, but they work with the help of Internet like a Web Application.
Example: WhatsApp, Swiggy, Zomato, Uber, Ola, etc.

Desktop Applications vs Web Applications:


 Web Applications need to be installed only once that to on 1 Computer only whereas Desktop App’s must be
installed separately on each computer.
 When we need to update a Web App’s it needs to be done only on the single computer where it is installed,
whereas in case of Desktop App’s it needs to be done on every computer.
 Desktop App’s are confined to a particular location, and they have usability constraints, whereas Web App’s are
convenient for the users to access them from any location using internet.
 Web Application’s relies significantly on internet connectivity and speed, so absence of internet or poor
connectivity can cause performance issues whereas Desktop App’s are standalone in nature and hence do not
face any hindrances resulting from Internet connectivity.
 Web Application is completely internet dependent, so they consume more bandwidth whereas Desktop App’s
are partially internet dependent, so they consume less bandwidth.
 To build Desktop Application with .NET Languages we are provided with technologies like Console App’s,
Windows Forms App’s, WPF (Windows Presentation Foundation) App’s and same as that to build Web
Applications we are provided with technologies like ASP.NET and ASP.NET Core.

Web Applications vs Mobile Applications:


 Web apps need an active internet connection to run, whereas mobile apps may work offline.
 Mobile apps have the advantage of being faster and more efficient, but they do require the user to regularly
download updates. Web apps will update themselves.
 Mobile apps are developed for operating systems like iOS and Android. They can be accessed from anywhere by
downloading the application on the device you want to use. Whereas the Web application can run on any OS like
desktop operating systems as well as mobile operation systems also.
 Mobile applications are much safer when compared to web applications.
 The web app is less expensive when compared to mobile apps.

Desktop Applications vs Mobile Applications:


 Desktop apps run on stationary machines or laptops, while mobile apps run on mobile devices such as mobile
phones or tablets.
 Mobile apps have limitations when it comes to storage, connectivity, etc.
 Mobile apps are designed to function with the phone’s inbuilt features like the microphone, camera, location
services, etc.
 Desktop apps are usually more flexible and agile than mobile apps.
 Mobile users interact with their devices in many ways than traditional apps. For example, mobile apps must be
designed for vertical orientation, while desktop apps can be designed for landscape orientation.

2
What is Internet?
Ans: Internet is a global system of interconnected computer networks that use the standard Internet protocol suite
(TCP/IP) to link several billion devices worldwide. It is a network of networks that consists of millions of private,
public, academic, business, and government networks, of local to global scope, that are linked by a broad array of
electronic, wireless, and optical networking technologies. Internet carries an extensive range of information,
resources, and services, such as the inter-linked hypertext documents and applications of the World Wide Web
(WWW), the infrastructure to support email, and peer-to-peer networks for file sharing and telephony.

What is World Wide Web (WWW)?


 The Web is a network of devices all over the world.
 All the devices in the web can communicate with each other.
 All the devices use a communication protocol called Http(s).

How does WWW work?


 Web information is stored in files called Web Pages.
 Collection of Web Pages is known as Web Site or Web Application.
 Web Site or Web Application is hosted on computers called Web Servers.
 Devices reading the Web Pages are called Web Clients.
 Web Clients views the Web Pages with a program called as Web Browser.

How does a Web Browser fetch a Web Page?


 A browser fetches a Web Page from a Web Server by a request and this request is a standard “HTTP Request”
containing a Page Address known as URL (Uniform Resource Locator).
 An Address or URL may look like this: http(s)://www.google.com:80/default.html
Format of URL: <Protocol>://<Domain Name>:<Port>/<Request Page>

3
How does a Browser Display a Web Page?
 All Web Pages contain instructions for display and the Web Browser displays the page by reading those
instructions.
 The most common display instructions are called HTML.

What is a Web Server?


 The collection of Web Pages is called as a Web Site or Web Application.
 To let others, view your Web Pages, you must publish your Web Site or Web Application.
 To publish your Site or Application, you must copy it to a Web Server.
 Your own PC can act as a Web Server if it is connected to a network, but the most common practice is to use a
Hosting Internet Service Provider (ISP).

What is an Internet Service Provider?


 An ISP provides Internet Services.
 A common Internet service is Web Hosting.
 Web Hosting means storing your Web Site or Web Application on a Public Server.
 Web Hosting normally includes Email Services also.
 Web Hosting often includes Domain Name Registration also.

Summary:
 If you want other people to view your Web Site or Application, you must copy your Site to a Public Server.
 Even if you can use your own PC as a Web Server but it is very common to let an ISP host your Site.
 Included in Web Hosting solution you can also expect Domain Name Registration and standard Email Services.
 Hosting your Site or Application on your own Server is always an option and here are some points to consider:

1. Hardware Expenses: To run a “real” Web Site or Web Application, you will have to buy some powerful Server
hardware. Don’t expect that a low-cost PC will do the job. You will also need a permanent (24 hours a day) high-
speed internet connection.
2. Software Expenses: Remember that Server-Licenses often are higher than Client-Licenses. Also note that
Server-Licenses might have limit on number of users.
3. Labour Expenses: Don’t expect low labour expenses. You must install your own hardware and software. You
also must deal with bugs and viruses and keep your server constantly running.

Benefits of using an Internet Service Provider (Public Server): renting a Web Server from an ISP is a very common
option and most small companies store their Web Site or Web Application on a Server provided by an ISP only. Here
are some advantages:
1. Connection Speed: Most ISPs have very fast connections to the Internet.
2. Security and Stability: ISPs are specialists on Web Hosting. Expect their Servers to have more than 99% up time,
the latest software patches, and the best Virus Protection.
3. Powerful Hardware: ISPs often have powerful Web Servers that can be shared by several companies. You can
also expect them to have an effective Load Balancing, and necessary Backup Servers.

Things to Consider with an ISP:


1. 24-hour support: Make sure your ISP offers 24-hours support. Don’t put yourself in a situation where you cannot
fix critical problems without having to wait until the next working day. Toll-free phone could be vital if you don’t
want to pay for long distance calls.

4
2. Daily Backup: Make sure your ISP runs a daily backup routine; otherwise, you may lose valuable data.
3. Traffic Volume: Study the ISP’s traffic volume restrictions. Make sure that you don’t have to pay a fortune for
unexpected high traffic if your Site becomes popular.
4. Content Restrictions: Study the ISP’s content restrictions if you plan to publish pictures or broadcast video or
sound and make sure that you can do it.
5. E-mail Capabilities: Make sure your ISP supports the Email capabilities you need.
6. Database Access: If you plan to use data from Databases in your Site, make sure your ISP supports the Database
access you need.

What is TCP/IP?
Ans: TCP/IP stands for Transmission Control Protocol / Internet Protocol, is a family of protocols for communication
between computers. It defines how electronic devices should be connected over the network, and how data should
be transmitted between them.

 TCP: is responsible for breaking down data into small packets before they can be sent over a network, and for
assembling the packets again when they arrive.
 IP: takes care of the communication between computers. It is responsible for addressing, sending, and receiving
the data packets over the Internet.

TCP/IP Protocols for the Web: web browsers and servers use TCP/IP protocols to connect to the Internet. Common
TCP/IP protocols are:

1. HTTP: Hyper Text Transfer Protocol takes care of the communication between a Web Server and a Web Browser.
HTTP is used for sending requests from a Web Client (Browser) to a Web Server, returning Web Content (Web
Pages) from the Server back to the Client.
2. HTTPS: Secure HTTP, takes care of secure communication between a Web Server and a Web Browser. HTTPS
typically handles Credit Card transactions and other sensitive data.
3. FTP: File Transfer Protocol, takes care of transmission of files between Computers.
4. SMTP: Simple Mail Transfer Protocol, used to send or receive Emails between Senders and Receivers.

IP is Connection-Less:
 IP is a “connection-less” communication protocol.
 IP does not occupy the communication line between two computers. This reduces the need for network lines.
Each line can be used for communication between many different computers at the same time.
 With IP, messages are broken up into small independent “packets” and sent between computers via the
Internet. IP is responsible for “routing” each packet to the correct destination.

IP Routers:
 When an IP Packet is sent from a computer, it arrives at an IP Router.
 IP Router is now responsible for “routing” the packet to the correct destination, directly or via another Router.
 Communicating via IP is like sending a long letter as many small postcards, each finding its own way to the
receiver.

IP Addresses:
 This is a unique identification for every device in the network.
 IP uses 32 bits or four bytes numeric value where each number should be ranging between 0 to 255.

5
 IP addresses are normally written as four numbers separated by a period, like this: 31.13.65.36.
 Each device must have a unique IP address before it can connect to the Internet.
 Each IP packet must have an address before it can be sent to another computer.
 This is an IP address: 31.13.65.36. This might be the same address: www.facebook.com

Domain Names:
 A name is much easier to remember than a 12-digit number.
 Names used for IP addresses are called Domain Names; for example, “www.facebook.com” is a domain name.
 When you address a web site, like “www.facebook.com”, the name is translated to a number by a Domain Name
Server (DNS).
 All over the world, DNS Servers are connected to the Internet. DNS servers are responsible for translating
Domain Names into IP Addresses.
 When a new Domain Name is registered together with an IP Address, DNS Servers all over the world are updated
with this information.

What is a Domain Name?


 A Domain Name is a unique name for a Web Site, like google.com, facebook.com.
 Choosing a hosting solution should include Domain Name registration also.
 Domain Names must be registered. When Domain Names are registered, they are added to a large domain
name register. In addition, information about the Web Site, including the IP Address is stored on a DNS Server.

What is a DNS?
 DNS stands for Domain Name System.
 A DNS Server is responsible for informing all other computers on the Internet about the Domain Name and the
Web Site address.

Registering a Domain:
 Domains can be registered from Domain Name registration companies.
 These companies provide an interface to search for available Domain Names, and they offer a variety of Domain
Name extensions that can be registered at the same time.

Choosing a Domain Name:


 Choosing a Domain Name is a major step for any individual or organization.
 New Domain Name extensions and creative thinking offer thousands of excellent Domain Names!
 When choosing a name, it is important to consider the purpose of a Domain Name, which is to provide an easy
way to reach your Web Site.
 The best domains have the following listed characteristics: Short, Meaningful, Clear and Exposure:

1. Short - People don’t like to type! So, a short Domain Name is always easier to type, read, and remember.
2. Meaningful - A short domain is nothing without meaning, “34i4nh.com” is not easy to enter or to remember.
Select a domain that relates to your site in a way that people will understand about your site.
3. Clear - Clarity is important when selecting a Domain Name. Avoid a name that is difficult to spell or pronounce.
4. Exposure - Names that are short and easy to remember are an asset. In addition to visitors, also consider
search engines. Search engines index your site and rank it for relevance against terms people search for your
sites, consider including a relevant search term in your domain.

6
What is web hosting?
Ans: Web hosting is a service provided by companies that sell or lease space on a server where you can store the
files that make your website accessible on the internet. This typically requires that you own a domain, and these
companies may help you in purchase one.

What is shared hosting?


Ans: Shared hosting is a popular hosting option where a provider hosts multiple websites on one physical web server.
Typically, most websites don't use many server resources, so shared hosting lets providers offer stable service at a
low cost. Shared hosting allows you to share hosting space and costs with others, while benefitting from the speed
and space you need for your small business website.

Domain Name Servers (DNS): it is the Internet’s equivalent of a phone book. They maintain a directory of Domain
Names and translate them to IP Addresses. This is necessary because, although Domain Names are easy for people
to remember, computers or machines, access websites based on IP Addresses only. Information from all the Domain
Name Servers across the Internet are gathered and housed at the Central Registry. Host companies and Internet
Service Providers interact with the Central Registry on a regular schedule to get updated DNS information.

The Internet Assigned Numbers Authority (IANA): manages IP address space allocations globally and delegates five
Regional Internet Registries (RIRs) to allocate IP address blocks to local Internet Registries like ISP’s and other
entities. A Regional Internet Registry (RIR) is an organization that manages the allocation and registration of Internet
number resources within a particular region of the world. The Regional Internet Registry system eventually dividing
the world into 5 RIR’s:
 African Network Information Center (AFRINIC) for Africa.
 American Registry for Internet Numbers (ARIN) for the United States, Canada, several parts of the Caribbean
region, and Antarctica.
 Asia-Pacific Network Information Centre (APNIC) for Asia, Australia, New Zealand, and neighboring countries.
 Latin America and Caribbean Network Information Centre (LACNIC) for Latin America and parts of the Caribbean
region.
 Reseaux IP European’s Network Coordination Centre (RIPE NCC) for Europe, Russia, Middle East, and Central
Asia.

Till now you might have created some Web Pages by using HTML, Java Script, and CSS, and are able to access those
pages from your local machines by using their physical path or address in the browser; but how can we access
those Web Pages from remote machines within a network?
Ans: If we want to provide access to the Web Pages, we have developed to remote machines we need to take the
help of a Server Software known as “Web Server”.

What is a Server?
Ans: It is software which works on 2 principles like request and response. There are so many Servers software’s in
the industry, like Server Operating Systems (Windows Servers, Linux, Solaris, etc.) Database Servers (Oracle, SQL
Server, and My SQL etc.), Application Servers, Web Servers, etc., and for us what we need is a Web Server to provide
access to our Web Pages to Remote Clients.

What is the need of a Web Server?


Ans: this software is used for taking request (HTTP Request) from clients in the form of a “URL (Uniform Resource
Locator)” and then sends Web Pages as response (HTTP Response).

7
What Web Server software’s are available for us to consume?
Ans: There are so many Webservers software’s that are available in the market like Apache Web Server from Apache,
Nginx Web Server from NGINX, IIS Web Server from Microsoft, GWS Web Server from Google, LiteSpeed Web Server
from LiteSpeed Technologies, but the most compatible Web Server for ASP.NET Applications is IIS Web Server from
Microsoft.

Working with IIS Web Server:


 IIS stands for Internet Information Services which is formerly known as Internet Information Server.
 IIS Web Server is a product of Microsoft and more compatible for our ASP.NET and ASP.NET Core Applications.
 IIS is a part of Windows OS which is generally installed on our machines along with the Operating System, and
to verify whether it is installed on your machine or not, open any Web Browser and type in the below URL:
http://localhost

Note: If IIS is not installed on your machine, we get the below error:
“HTTP Error 404. The requested resource is not found.”

Installing IIS on our machine if not installed already: Go to Control Panel => click on Programs and Features => In
the window opened, click on “Turn Windows features on or off”, which opens another window called “Windows
Features” => in the new window opened select the CheckBox “Internet Information Services” and also select each
and every Sub-Item (Checkbox’s) under it and click on the Ok button which will install IIS on your machine, then
restart your machine. Once IIS is installed on your machine re-verify whether it is working or not by using the above
URL.

How to access a Web Page using IIS?


Ans: When we install IIS Web Server on our machine it will provide us an admin console for managing IIS and we call
it as “IIS Manager”, which can be launched by searching for “inetmgr” in the window search. Once IIS Manager is
opened, in LHS of the window we find “Connections Panel” and in that Panel we find our Computer Name as Server
Name (Server is the name of my Web Server because the name of my computer is Server) and when we expand it,
we find a node called as “Sites” and under that we find a website with the name “Default Web Site”, which is created
when IIS is installed on our machines.

What is a Web Site?


Ans: Web Site is a collection of Web Pages, and a Web Server is a collection of Web Sites, i.e., a Web Server can
contain 1 or more Web Sites under it and by default when IIS is installed on a machine there will be 1 Website already
created, with the name as “Default Web Site”.

8
To access Web Pages thru IIS Web Server, do the following:
Step 1: Create a folder on your PC in any drive naming it as “ASP”.

Step 2: Create an HTML Page with the name “Login.html” with the below code and save it into the “ASP” folder.

<!DOCTYPE html>
<html>
<head><title>Login Form</title></head>
<body>
<form>
<table align="center">
<caption>Login Form</caption>
<tr>
<td>User Name:</td>
<td><input type="text" id="txtName" name="txtName" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" id="txtPwd" name="txtPwd" /></td>
</tr>
<tr>
<td align="center" colspan=2>
<input type="submit" value="Login" />
<input type="reset" value="Reset" />
</td>
</tr>
</table>
</form>
</body>
</html>

If we want to access Web Pages thru Web Server, we are provided with 3 different options:
Option 1: Accessing thru “Default Web Site”, because this Website is already created under IIS Web Server we can
access our Web Pages thru the Site and to do that we need to copy our Web Pages to a folder that is linked with this
Website i.e., “<OS Drive>:\inetpub\wwwroot” and if we copy our Web Pages into this folder we can access them
thru IIS using their “Virtual Path” either from a local or a remote machine also. To test this let’s copy our “Login.html”
file into this folder and then access it thru the Virtual Path of the file as following:

Local Machine => http://localhost/Login.html or http://Server/Login.html


Remote Machine => http://Server/Login.html

Note: for every Web Site that is created on IIS, there will be 1 associated folder on the Hard Disk and all the Web
Pages of that Site should be placed into that folder, right now “Default Web Site” is mapped with the “wwwroot”
folder and that is the reason why we placed our “Login.html” Page into that folder. To view the mapping folder of
“Default Web Site”, right click on the “Default Web Site” in “IIS Manager” Window => select “Manage Website” and
under that select “Advanced Settings” which opens a window and in that we find “Physical Path” property and beside
that we find the folder that is mapped to this Web Site.

9
Option 2: Accessing them thru an Application or Virtual Directory created under Default Web Site, in this case
without copying all the Web Pages into “inetpub/wwwroot” folder as we did in the previous case, we can create an
“Application or Virtual Directory” under “Default Web Site” and map them to our physical folder where we have
saved our Web Pages i.e., “ASP” Folder.

To create an Application or Virtual Directory, Right Click on “Default Web Site” in “IIS Manager”, select the
option “Add Application” or “Add Virtual Directory” which opens a Window and in that, in “Alias” TextBox enter a
name of your choice and under “Physical Path” TextBox enter the physical path of your folder i.e., "<drive>:\ASP".

Now following the above process, create 1 Application with the name “Site1” and create 1 Virtual Directory
with the name “Site2” and map both to our physical folder i.e., “ASP”. From now we can access the page of this
folder in any of the following ways:

Local Machine: http://localhost/Site1/Login.html Or http://Server/Site1/Login.html


Local Machine: http://localhost/Site2/Login.html Or http://Server/Site2/Login.html

Remote Machine: http://Server/Site1/Login.html


Remote Machine: http://Server/Site2/Login.html

Option 3: Accessing the Web Pages by creating a Site. In this case we create a new Site under IIS just like the existing
site i.e., Default Web Site and map it to a physical folder, but the difference is; in this case we can give our own Host
Name or Domain Name just like “localhost” which is the Host Name or Domain Name for “Default Web Site” or we
can use the same Host Name i.e., “localhost” and change the Port No.

Creating a new Site by changing Port No: right click on “Sites” node in “Connections” panel and select the option
“Add Website”, which opens a new window and in that window under “Site name” Textbox specify a name to the
site for example: “NitSite1” and under “Physical path” TextBox specify location of our folder i.e., “<drive>:\ASP”,
now under “Port” Textbox the default Port will be shown as “80”, change to any new value like “90” and click on the
“Ok” button which will create the new site under IIS. Now we can access the Web Pages in our folder using the below
URL:

Local Machine: http://localhost:90/Login.html Or http://Server:90/Login.html


Remote Machine: http://Server:90/Login.html

Creating a new Site by changing Host or Domain Name: right click on “Sites” node in “Connections” panel and select
the option “Add Website”, which opens a new window and in that window under “Site name” Textbox specify a
name to the site for example: “NitSite2” and under “Physical path” TextBox specify location of our folder i.e.,
“<drive>:\ASP”, now under “Host Name” TextBox specify a Host Name or Domain Name, for example “nitsite.com”
and click on the “Ok” button, which will create a new Site under Sites.

Note: To use this Web Site we need to specify the Host Name under a file, “hosts” which is in the following folder:
“C:\Windows\System32\drivers\etc”. To do that first copy the file into a different location (because it can’t be edited
in the current location), add the below code in it in the last line, save and again copy the file back to
“C:\Windows\System32\drivers\etc” folder.

127.0.0.1 nitsite.com

10
Now we can access the Web Pages in our folder using the following URL:
Local Machine => http://nitsite.com/Login.html
Remote Machine => http://nitsite.com/Login.html

Note: till now we have created 1 Application and 1 Virtual Directory under “Default Web Site” and 2 Sites under the
Server with the name “MySite1” and “MySite2” so all these 4 will be present under “IIS Manager” under Connections
panel as below:

Creating Dynamic Web Pages: These are pages that are created based on a client’s request, and the content of these
pages will change based on the request i.e., the output of the page will change time to time. For example, a
transaction report in a Bank's Web Site.

Staring Date: 01/04/2024


Ending Date: 31/03/2025
Transaction Value:* >= 15000
Transaction Value:* <= 30000 *Optional

How to create a dynamic Web Page?


Ans: To create a dynamic Web Page along with HTML, Client-Side Scripting Languages (Java Script) and CSS we also
require taking the help of some Server-Side Technologies. There are so many Server-Side Technologies that are
available in the industry for creating dynamic Web Pages like: ColdFusion, Perl, PHP, Classical ASP, JSP, Servlets,
ASP.NET, ASP.NET Core, Django, etc.

1. HTML => Static Web Pages


2. HTML + CSS => Static Web Pages (Beauty)
3. HTML + CSS + Java Script => Static Web Pages (Interactive)
4. HTML + CSS + Java Script + Server Side Technologies => Dynamic Web Pages

Every Server-Side Technology uses some programming Language for implementing the logic, for example:
 ColdFusion => CFML
 Perl => Perl Script
 PHP => PHP Script
 Classical ASP => VB Script or JScript
 JSP and Servlets => Java
 ASP.NET & ASP.NET Core => .NET Languages
 DJango => Python

11
Under ASP.NET we again have 2 options available for developing Dynamic Web Pages:
1. ASP.Net Web Forms
2. ASP.Net MVC

ASP.NET Web Forms


 It is an Open-Source Server-Side Web Application Framework designed by Microsoft for Web Development to
produce Dynamic Web Pages.
 It’s designed to allow programmers to build Web Sites/Web Applications and Web Services.
 It was 1st released in Jan 5, 2002, with 1.0 version of .NET Framework and this is a successor to Microsoft’s
Classical ASP technology.
 The current version of ASP.NET is 4.x released on October 2019 which will be the last version and it is succeeded
by ASP.NET Core.
 ASP.NET is built on Common Language Runtime (CLR), allowing programmers to write ASP.NET code by using
any of the supported .NET Languages and while coding an ASP.NET Application, we will have access to all
Libraries of “.NET Framework” which enable us to develop Web Applications and then benefit from CLR, Type
Safety, Inheritance, and all Object-Oriented Programming features.
 ASP.NET is a unified Web Development Framework which includes all the services that are necessary for us to
build an Enterprise Class Web Application’s with minimum volume of coding.

How to create Dynamic Web Pages by using ASP.NET Web Forms?


Ans: To create a Dynamic Web Page by using ASP.NET Web Forms we need to follow the below process:
1. Save the Page with “.aspx” extension and that Page can contain HTML, Java Script, CSS and ASPX Code.
2. Implement the logic (ASPX Code) that must be executed on the Server in any of the following ways:

<script language="CS|VB" runat="server">


-Server-Side Logic (ASPX Code)
</script>
Or
<%
-Server-Side Logic (ASPX Code)
%>

Language attribute is to specify in which language we want to implement the logic and it can either be VB
or CS, but the default is VB. Runat attribute is to specify that this logic should be processed by the Web Server.

Note: in-case we are implementing the logic by using second approach we don’t require to specify runat attribute
and the default language will be VB.

The extension of a Web Page plays a very crucial role while creating dynamic web pages i.e., if the extension
of Web Page is “.html”, Web Server will not process the logic that we have implemented by ASP.NET and to test that,
write the below code in a notepad, save it as “Test.html” and access it thru Web Server.

<!DOCTYPE html>
<html>
<head>
<title>First Dynamic Web Page</title>

12
</head>
<body>
<h1 style="text-align:center;color:red;background-color:yellow">Naresh I Technologies</h1>
Server Date: <% Response.Write(DateTime.Now.ToShortDateString()) %> <br />
Server Time: <% Response.Write(DateTime.Now.ToLongTimeString()) %>
</body>
</html>

Note: save the above page in our “ASP” folder and access it from browser in any of the following ways:
http://localhost/Site1/Test.html //Accessing thru Application created.
http://localhost/Site2/Test.html //Accessing thru Virtual Directory created.
http://localhost:90/Test.html //Accessing thru Site created with different Port No. 90
http://nitsite.com/Test.html //Accessing thru Site created with Domain Name.

In the above case even if the Web Page contains ASPX Code in it, Web Server will not process that code
because of the page extension, so it will send the content of page “as is” to the Browser for publishing. When we
send a request from any Browser to Web Server for any “.html” page, Web Server will immediately send content of
that page as Response to the Browser without checking what is present in the file, so the ASPX Code we implemented
in the file is not processed by the server but displayed directly (“as is”) on the Browser.

Now use “Save As” option in notepad and save “Test.html” as “Test.aspx” in our folder i.e., “ASP”, and when
we access the Page from Browser, we don’t see the logic, but what we see is the result when accessed:
http://localhost/Site1/Test.aspx //Accessing thru Application created.
http://localhost/Site2/Test.aspx //Accessing thru Virtual Directory created.
http://localhost:90/Test.aspx //Accessing thru Site created with different Port No. 90
http://nitsite.com/Test.aspx //Accessing thru Site created with Domain Name.

When we send request from a Web Browser to Web Server for any “.aspx” page, Web Server will open the
file, reads line by line from the file and writes the HTML Code “as is” into the Output Stream, whereas if it finds any
ASPX Code, it will process that logic and writes the results that are obtained from processing, into the Output Stream
as Text (HTML), so that after processing the whole page, content in the Output Stream will be sent to Browser as
Response.

ASP.NET Renders HTML: Unfortunately, internet still has bandwidth limitations and not every person is running on
the same OS, same Web Browser or same Device, and these issues make it necessary to stick with HTML as our mark-
up language of choice. So, in all the Server-Side technologies including ASP.NET; Web Server will process all the logic
implemented by us using any technology and converts the result into Text (HTML) which we call it as Rendering and
then that HTML will be sent to Clients as Response.

13
What is the default language used in the creation of ASPX Pages?
Ans: The default language that is used in the creation of ASPX Pages is VB (VB.NET).

How to use C# as the language for creation of ASPX Pages?


Ans: If we want to use C# language for creation of ASPX Pages we need specify that by using “Page Directive” on top
of the page and by using this we can specify the language we want to use for development of the page with the help
of its language attribute as following:

<%@ Page Language="C# | CS" %>

To test this, write the above statement on the top of our “Test.aspx” file we have created earlier and
immediately we get an error when we run the page stating that “;” is expected and to resolve the problem end the
below 2 statements with “;”:

<% Response.Write(DateTime.Now.ToShortDateString()); %>


<% Response.Write(DateTime.Now.ToLongTimeString()); %>

Note: a directive is an instruction that we give to the Web Server. By using Page directive, we are telling the Web
Server that the content in this page is implemented by using the specified language i.e., “C#” so that Web Server will
use the appropriate language compiler to process the page.

What is “Response” in our above code?


Ans: Response is an instance of a pre-defined class “HttpResponse”, and we call it as an intrinsic object and apart
from this Response we also have 7 other intrinsic objects like: Request, Server, Session, Application, Trace, User and
Cache, which can be directly consumed in our Web Pages. Each intrinsic object is internally an instance of some class
like “Request” is an instance of class “HttpRequest”, “Response” is an instance of class “HttpResponse”, and “Server”
is an instance of class “HttpServerUtility” and so on.

How intrinsic objects are accessible to our ASPX Pages?


Ans: Intrinsic objects are accessible to our ASPX Pages from its parent class i.e., every ASPX Page after its compilation
gets converted into a class and that class will internally inherit from a pre-defined class called “Page”, which is
defined under “System.Web.UI” namespace of the BCL (Base Class Libraries) and all the above 8 intrinsic objects are
inherited from that “Page” class to our ASPX Pages.

Coding Techniques in ASP.NET: ASP.NET offers 2 different coding techniques for creating Dynamic Web Pages, those
are:
1. Inline coding technique
2. Code behind technique

Inline Coding: in this case HTML, Java Script, CSS, Input Controls and Business Logic (implemented by C# or VB) will
be present in 1 file that is saved with “.aspx” extension. The “Test.aspx” page we have created above is an example
for “Inline Coding”.

Code Behind: in this case HTML, Java Script, CSS, and Input Controls will be present under 1 file that is saved with
“.aspx” extension and Business Logic (implemented by C# or VB) will be present in a separate file that is saved with
“.aspx.cs” or “.aspx.vb” based on the language in which we are implementing the Business Logic.

14
Developing Web Pages using Visual Studio: Open Visual Studio => select “Create a new project” option => now
under the Window opened, choose C# under “All_Languages DropDownList”, choose Windows under “All_Platforms
DropDownList”, choose Web under “All Project_Types DropDownList” and now in the below choose “ASP.NET Web
Application (.NET Framework)” and click Next, which launches a new Window, enter Project name as “FirstWebApp”,
Location as “<drive>:\ASP”, under Framework option choose the latest Framework Version in the Dropdown and
click on the Create button which launches a new Window and in that choose Empty Project Template and in the RHS
select Web Forms CheckBox and make sure all the other Checkbox’s are un-checked and click on Create Button which
will create and opens the new project.

Right now, the project which is opened is empty which doesn’t contain any Web Pages in it and if we open
the Solution Explorer and watch, we will find 2 empty folders here with the names App_Data & Models which can
either be deleted or leave them as is, and under the project we will also find 3 files with the names “Global.asax”,
“Packages.config” and “Web.config” which are required under every ASP.NET Web Application.

Note: Every “ASP.NET Web Application” project is a collection of Web Pages and we call them here as Web Forms.

Adding a Web Form in our project: right now our project doesn't contain any Web Form’s in it, and if we want to
add a new Web Form, open Solution Explorer right click on the project and select Add => “New Item” which opens
the “Add New Item” window, choose Web Form in it, which will ask for a name, default will be “WebForm1.aspx”,
change it as “First.aspx” and click on the Add button.

By default, the page “First.aspx” contains “Page Directive” on top of the page with few attributes like:
“Language”, “AutoEventWireup”, “Code Behind” and “Inherits”, below that we find some HTML Code containing
Head and Body sections.

To view the Code Behind file associated with this Web Form right click on the Web Form in document
window and select View Code option which will launch the file “First.aspx.cs” that contain a class in it with the name
First inheriting from the Page class and notice that class First is a partial class i.e., it is defined on more than one
source files.
1. First.aspx.cs
2. First.aspx.designer.cs

Note: by default, “First.aspx.cs” file is only visible to us and if we want to view “First.aspx.designer.cs” file, open
Solution Explorer and expand “First.aspx” node and under that we find both the files. “Designer.cs” files are used by
Visual Studio to auto-generate code i.e., the code in these files will be generated by Visual Studio, so never edit the
content of this files.

Writing code in a Web Form: because our page is created in Code Behind model, we can implement our logic either
in “.aspx” file or “.aspx.cs” file also. For example, if we want to implement logic in “First.aspx”, then write the below
code under “<div>” tag which we find under the “<body>” tag:

15
Server Date: <% Response.Write(DateTime.Now.ToShortDateString()); %>
<br />
Server Time: <% Response.Write(DateTime.Now.ToLongTimeString()); %>

Note: to run the Web Page hit F5 and it executes the page and displays the output on browser.

If we want to implement logic in “aspx.cs” file, then add another new Web Form in the project naming it as
“Second.aspx”, go to its Code View and write the below code under the method “Page_Load” which we find in the
file “Second.aspx.cs”:

Response.Write($"Server Date: {DateTime.Now.ToShortDateString()}");


Response.Write("<br />");
Response.Write($"Server Time: {DateTime.Now.ToLongTimeString()}");

How does a Web Application run under Visual Studio?


Ans: To run a Web Application we require a Web Server and without that Web Server we can’t run any Web
Application, so Visual Studio by default provides a built-in Web Server to run the Web Application’s that we develop
under Visual Studio i.e., “IIS Express” and right now our project FirstWebApp is running thru that “IIS Express Web
Server” only.

Visual Studio will add each Web Application to IIS Express as a Site by allocating a random Port to each Web
Application, which will be different from Project to Project and Machine to Machine. To view the Port that is
allocated for your Web Application run any Web Form in our project and watch the URL in browsers address bar
which will be as following:
http://localhost:YourPort/First.aspx http://localhost:YourPort/Second.aspx

Note: IIS Express is provided for testing our Web Applications at the time of development and we call this as a
“Development Web Server” also and once the Application development is completed, we can host our Web
Application either on the “Local IIS” of our machine or “IIS” on remote machines or on some Public Server also.

How to host our Web Application into Local IIS?


Ans: as discussed above our Web Application is right now running under IIS Express of Visual Studio, and it's possible
to host the Application on Local IIS of our machine and to do that first close your Visual Studio and re-open it in
Administrator mode and to do that, right click on the Visual Studio and select the option “Run as Administrator”.
Now open Solution Explorer, right click on the project and select Properties option which will launch Project Property
Window, in that window on the LHS we find Web tab, click on it and now on the right scroll down to Servers section,
there we find a DropDownList and in that by default “IIS Express” is selected and in the “Project URL TextBox” it will
be showing the current Project’s URL i.e.,: http://localhost:Port/.

Now in the DropDownList select “Local IIS” option which will change the Project URL as following:
http://localhost/FirstWebApp, and beside the Project URL Textbox we find a button “Create Virtual Directory” click
on it, which will create an Application under the “Default Web Site” of “Local IIS”, now click on the Save button in
“Visual Studio Standard Toolbar” and from now our Web Application will be running thru Local IIS and the URL when
we run our Web Forms will be as following:
http://localhost/FirstWebApp/First.aspx
http://localhost/FirstWebApp/Second.aspx

16
Working with Web Forms: every Web Form in an ASP.NET Web Application project will be having 3 places to work
with, those are:
1. Source View
2. Design View
3. Code View

Source View: when a new Web Form is added by default its display’s the Source View only, which is nothing but the
“.aspx” file of the Web Form and we use this for writing HTML, CSS, Java Script as well as all the logic for creation of
Input Controls.

Design View: This is a visual representation of Source View i.e., whatever we write in Source View will be displayed
as output in Design View just like how output is displayed on Browser and because of this feature Visual Studio IDE
is known as WYSIWYG (What You See Is What You Get) IDE. We can also use this for designing the UI’s, by a feature
called “Drag and Drop”.

Note: To navigate from “Source View” to “Design View”, in the bottom of “.aspx” file we find 3 options: Design, Split
& Source. By default, it will be pointing to Source, click on Design which will take us to the Design View or click on
Split to see both at a time in top and bottom.

Code View: this is nothing but “.aspx.cs” file of the Web Form and we use this for implementing all the business logic
using C# Language.

ASP.NET Server Controls: in ASP.NET to design the UI’s we don’t use HTML Controls at all, and in that place, we are
provided with “ASP.NET Server Controls” for designing UI’s. The advantages of using ASP.NET Server Controls over
HTML Controls are:

1. HTML Controls will lose the state of their values once the Web Page is submitted to Server, whereas
ASP.NET Server Controls will maintain the state of their values even after page submission.
2. HTML Controls can’t be accessed directly in C# Code whereas ASP.NET Server Controls are directly
accessible in the C# Code and, we have the advantage of intellisense listing members of that control.

We are provided with various Controls in ASP.NET for designing UI’s and all those Controls are pre-defined
Classes in our Libraries, which are defined under the namespace System.Web.UI.WebControls. ASP.NET Server
Controls are divided into different categories like:
1. Standard Controls
2. Data Controls
3. Validation Controls
4. Navigation Controls
5. Login Controls
6. Web Parts Controls
7. Ajax Extension Controls
8. Dynamic Data Controls

Note: we have been provided with number of Controls that are developed by using C# Language, but all those
controls at the time of page processing will be rendering required HTML and the logic for rendering is implemented
in a method of that Control class i.e., “RenderControl” and this method will be called by ASP.NET Framework while
processing the page.

17
To check ASP.NET Server Controls renders HTML, add a new Web Form in the existing project i.e.,
“FirstWebApp”, naming it as “Fourth.aspx” and write the below code under the “<div>” tag we find in Source View:

Enter Name: <input name="txtName1" type="text" id="txtName1" />


<input type="submit" name="btnSubmit1" value="Save" id="btnSubmit1" /><br />
Enter Name: <asp:TextBox ID="txtName2" runat="server" />
<asp:Button ID="btnSubmit2" runat="server" Text="Save" />

Run the above page, we see 2 TextBox’s and 2 Button’s on the page, now right click on the Browser and
select the option “View Page Source” which will display the Source Code of this page and notice in that code; ASP.Net
Server Controls also will be showing code in HTML format only because they are rendered and this is how we see
the code there, under the last <div> tag.

Enter Name: <input name="txtName1" type="text" id="txtName1" />


<input type="submit" name="btnSubmit1" value="Save" id="btnSubmit1" /><br />
Enter Name: <input name="txtName2" type="text" id="txtName2" />
<input type="submit" name="btnSubmit2" value="Save" id="btnSubmit2" />

Working with ASP.NET Server Controls: every ASP.NET Server Control is associated with 3 things in it:
1. Properties
2. Methods
3. Events

 Properties are nothing but attributes of a control which defines the look of a control. E.g.: Width, Height,
BackColor, ForeColor, BorderColor, BorderStyle, Font, etc.
 Methods are actions performed by the control when we call them. E.g.: Focus(), Clear(), RenderControl(), etc.
 Event is a time period which tells when an action has to be performed. E.g.: Click of a Button, Load of a Page,
TextChanged of a TextBox, etc.

Note: The parent class for all ASP.NET Server Controls is class Control of “System.Web.UI” namespace, which
contains all the common Properties, Methods, and Events of all ASP.NET Server Controls.

Placing an ASP.NET Server Control on a Web Form: to work with ASP.NET Server Controls create a new empty
“ASP.NET Web Application (.NET Framework)” project, naming it as “ControlsDemo”, choose Empty Project
Template and select the “Web Forms - Check Box”, uncheck all the other Checkbox’s and click on Create button. In
the project add a Web Form, naming it as “ControlCreation.aspx” and delete the “<div>” tag that is present inside
the “<form>” tag. We can place a control on our Web Form either thru “Design View” or “Source View” or “Code
View” also.

Design View: go to Design View of our Web Form and in the LHS we find a window called Toolbox, open it and in
that window under the Standard Tab we find a list of controls, either double click on the Button control or Drag and
Drag the Button control on to the Design View.

Note: this action will generate all the required ASPX Code for creation of the Button and to view that code go to
Source View of the page and there we find the below code:
<asp:Button ID="Button1" runat="server" Text="Button" />

18
Source View: same as the above we can also write code for creation of a control just like what Visual Studio has
generated and to test that write the below code under existing Button1 in Source View:
<asp:Button ID="Button2" runat="server" Text="Button" />

Note: every Control we place on a Web Form is an instance of an appropriate control class, so in the above case
Button1 and Button2 are 2 instances of Button Class.

Code View: we can also explicitly create the instance of any control class thru CSharp Code and add it on the Web
Form and to test this process go to “ButtonCreation.aspx.cs” file of our Web Form and write the below code in
“Page_Load” method which is present there:
Button Button3 = new Button();
Button3.ID = "Button3";
Button3.Text = "Button";
form1.Controls.Add(Button3);

Note: now run the Web Form and you will see all the 3 buttons on the Browser Window.

Working with properties of Controls: every ASP.NET Server Control is associated with “n” no. of properties and all
those properties will define the look of the control. We can set properties to a control also in 3 different ways.

Using Design View: go to Design View of the “ControlCreation.aspx” Web Form, select Button1 and hit F4 which
opens the Properties Window on RHS, listing all the properties of Button1 and in that window we find Control
properties like BackColor, BorderColor, BorderStyle, BorderWidth, FontSize, ForeColor, etc, change any of the
required property values and view the output directly in Design View.

Note: above action will generate all the required code in Source View as per our settings, to verify that go to Source
View and watch the code added to Button1 which will be as following:
<asp:Button ID="Button1" runat="server" Text="Button" BackColor="Yellow" BorderColor="Blue"
BorderStyle="Dotted" BorderWidth="5px" Font-Size="XX-Large" ForeColor="Red" />

Using Source View: same as Visual Studio generated the code for settings of Button1 in Source View, we can also
write manual code to perform property settings, and to test that add the following code for Button2 tag, which
should now look as below:
<asp:Button ID="Button2" runat="server" Text="Button" BackColor="Yellow" BorderColor="Blue"
BorderStyle="Dashed" BorderWidth="5px" Font-Size="XX-Large" ForeColor="Red" />

Using Code View: we can also set properties to controls by writing “C# Code”, to test that go to
“ButtonCreation.aspx.cs” file and write the below code in “Page_Load” method above the statement
“form1.Controls.Add(Button3);”:
Button3.BackColor = System.Drawing.Color.Yellow;
Button3.BorderColor = System.Drawing.Color.Blue;
Button3.BorderStyle = BorderStyle.Double;
Button3.BorderWidth = Unit.Pixel(5);
Button3.Font.Size = FontUnit.XXLarge;
Button3.ForeColor = System.Drawing.Color.Red;

Note: run the Web Form again to watch the output.

19
Working with Events of Control: An Event is a time-period which tells when an action must be performed i.e., when
a method must be executed. Every Control is associated with a set of events and each Event will fire at some point
of time which is based on user interactions, so we can bind methods with these events and those methods will
execute whenever the event fires.

Note: in GUI (Graphical User Interface) programming we don’t call methods directly, but we bind the methods with
events and those methods gets executed whenever the event fires and every event will fire at some point of time.
Events are already defined under the Control classes, so we need to define methods in our page class and then bind
those methods with events.

We can define methods for events in 3 different ways:


Using Design View: go to design view of “ControlCreation.aspx”, select Button1, hit F4, in the property window
opened we find Events option on the top, select it which will show events of Button and every Event will fire at some
point of time which can be identified by watching the description below. Now double click on Click - Event which will
generate a method in “aspx.cs” file for implementing the logic that should be executed when the End user clicks on
the Button and the name of that method will be “Button1_Click” which follows a pattern i.e., “<Control
Name>_<Event Name>”, now write the below code in that method:
Response.Write("<script>alert('Button1 is clicked.')</script>");

Note: now if we go to source view and watch, we find “Button1_Click” method bound to the Button’s click event as
following:
<asp:Button ID="Button1" runat="server" ……… OnClick="Button1_Click" />

Using Source View: we can generate methods for events thru source view also and to do that go to source view and
add the following code to Button2 tag in the end:
OnClick="Button2_Click"

Note: when we type “OnClick=”, Intellisense will display the option “<Create New Event>” select it, which will
automatically generate the above code. Now in code view we find our method “Button2_Click” for implementing
the logic, write the below code in it:
Response.Write("<script>alert('Button2 is clicked.')</script>");

Using Code View: we can generate methods for events in code view also, and to do that write the following
statement in “Page_Load” method above the statement “form1.Controls.Add("Button1");”:

Type Button3.Click += and hit the tab key => which will change as Button3.Click += Button3_Click;

The above action will generate a method with the name “Button3_Click” in the class, write the below code
under that method:
Response.Write("<script>alert('Button3 is clicked.')</script>");

Note: the methods under which we are implementing the logic for an Event are known as “Event Procedure” or
“Event Handlers”, where these methods are non-value returning and every method takes 2 parameters in common,
those are:

1. “sender” of type Object


2. “e” of type EventArgs or child class of EventArgs

20
Default Events: every control is associated with multiple events with it and to generate a Event Handler for any of
those events we need to follow any of the 3 processes that are described above, whereas for every control there
will be 1 default event and in case we want to generate Event Handler to that default event without following any
of the options that are described above, we can directly double click on the Control in design view which will
generate the required Event Handler.
Control Default Event
Button, LinkButton, ImageButton Click
TextBox TextChanged
CheckBox and RadioButton CheckedChanged
DropDownList, ListBox, CheckBoxList and RadioButtonList SelectedIndexChanged
Calendar SelectionChanged

Label Control: this control is used for displaying static text on the UI and we set the text value by using the Text
property of the control.

Button Control: this control is designed for submitting a page to Server and under this family we have 3 Classes
(Controls): Button, LinkButton and ImageButton, and when we place any of the above 3 button on a Web Form they
will render all the required HTML Code and converts as following:
Button => Html Input-Type Submit
LinkButton => Html Hyperlink
ImageButton => Html Input-Type Image

Note: to use ImageButton we need to set the ImageUrl property and to do that open Solution Explorer, right click
on the Project, select “Add” => “New Folder”, which will add a new Folder in the project, name it as “Images”. Now
right click on the Images folder and select “Add” => “Existing Item” which will open a dialog box, select an image
from your hard disk and it will add into the folder.

To work with “Button” controls add a new Web Form in the project naming it as “ButtonDemo1.aspx” and
write the below code under “<div>” tag:

<asp:Button ID="btnClick1" runat="server" Text="Click Me" />


<asp:LinkButton ID="btnClick2" runat="server" Text="Click Me" />
<asp:ImageButton ID="btnClick3" runat="server" ImageUrl="~/Images/Image.jpg" Width="50" Height="50" />

When we run the page, it will render the below code and we can view that by using “View Page Source”
option of browser:
<input type="submit" name="btnClick1" value="Click Me" id="btnClick1" />
<a id="btnClick2" href="javascript:__doPostBack(&#39;btnClick2&#39;,&#39;&#39;)">Click Me</a>
<input type="image" name="btnClick3" id="btnClick3" src="Images/Image.jpg" style="height:50px;width:50px;" />

What is meant by submitting a page to Server?


Ans: submitting a page to server means transferring all the values of a page that are entered into the controls from
Client’s Browser to the Web Server in a “key/value” and the control’s name will be used as “key”.

Page Submission is of 2 types:


1. Postback Submission
2. Cross-Page Submission

21
Note: Postback submission is a process of submitting a page back to itself whereas cross page submission means it
is a process of submitting a page to another page.
Page1 => Submitting to Page1 //Postback Submission
Page1 => Submitting to Page2 //Crosspage Submission

By default, Button control submits a page back to itself (Postback) only, and it is also capable of submitting
the page to other pages also (Cross Page).

Understanding “Post Back Submission” and “Cross Page Submission”: add a new Web Form in our project naming
it as “ButtonDemo2.aspx” and write the below code under its “<div>” tag:
<asp:Button ID="Button1" runat="server" Text="Postback Submission" />
<asp:Button ID="Button2" runat="server" Text="Crosspage Submission" />

Right now, both the Buttons will perform Postback Submission only, and to check that, go to
“ButtonDemo2.aspx.cs” file and write the below code under “Page_Load” Event Handler:

if (IsPostBack)
Response.Write("This is a post or post back request.");
else
Response.Write("This is a first or get request.");

Note: “IsPostBack” is a property of our parent class Page which returns true if the current request is a Post or
Postback request and false if it is a First or Get request. First request to a page is called as “Get Request” and the
next requests to a page are called as “Post Request”.

Now run the Web Form and watch the output which will initially display the value as “This is a first or get
Request.” which indicates it’s a first request and when we click on any of the 2 buttons it will display the value as
“This is a post or post back Request.” which indicates it’s a post back request.

Right now, both buttons are performing post back submission only whereas if we want the 2nd Button to
perform a cross page submission then add a new Web Form in the project naming it as “ButtonDemo3.aspx” and
write the following code under its “Page_Load” Event Handler in Code View:
Response.Write("<font color='red'>Cross Page Submission.</font>");

Now come to Design View of “ButtonDemo2.aspx”, select 2nd Button, go to its properties, identify the
PostBackUrl property, select it, which will display a Button beside with “…”, click on it which will launch a new
window and in that select “ButtonDemo3.aspx” and then run “ButtonDemo2.aspx” form, and watch the output i.e.,
when we click on Button1 it will perform Post Back Submission and when we click on Button2 it will perform Cross
Page Submission and launches “ButtonDemo3.aspx”.

Important members of Button Control:


1. Text: It is a property using which we can associate some data with the control that is visible to end users and
this works as a caption of the button.
2. PostBackUrl: It is a property using which we can specify the address of target page to whom the current page
has to submit when the button is clicked.
3. OnClientClick: It is a property using which we can specify the name of a JavaScript function which has to be
executed when the button is clicked, i.e., before submitting the page to server.

22
4. CommandName & CommandArgument: These 2 properties are used for associating some additional data with
the Button apart from the Text property but these are not visible to end users and these values can be used in
code under Command Event.
5. Click: It is an event which fires when the button is clicked.
6. Command: This is also an event which fires when the button is clicked and there are associated CommandName
or CommandArgument values.

To understand about the “OnClientClick” property, add a new Web Form in the project naming it as
“ButtonDemo4.aspx” and write the below code under its “<div>” tag:
<asp:Button ID="Button1" runat="server" Text="Click Me" />
<asp:Label ID="Label1" runat="server" ForeColor="Red" />

In this Web Form when we click on Button it has to display a message in Label Control saying that, the page
has been submitted to server. To achieve it generate a “Click Event Handler” for Button Control and write the below
code in it:
Label1.Text = "Page is submitted to server.";

Now when we run the Web Form and click on the Button control, Label control will display the message.
But when the user clicks on the Button first it must ask for a confirmation about submitting the page to server and
if the user accepts it, then only page should be submitted to server. This can be done by using Java Script code and
to do that, go to Source View of “ButtonDemo4.aspx” and write the below code under “<head>” section of page:

<script>
function Confirmation() {
var Result = confirm("Are you sure of submitting the page to server?");
return Result;
}
</script>

Now to execute this code when the Button is clicked, go to Design View of the Web Form, select the Button,
go to its Properties, select OnClientClick property and type the name of Java Script function we defined, as following:
return Confirmation(). Now run the Web Form again and check the difference in output.

Understanding about Object and EventArgs parameters of Event Handlers: as discussed earlier every Event Handler
will be taking 2 parameters i.e., “sender” of type “object” and “e” of type “EventArgs” or child class of “EventArgs”.
The use of these parameters is we can implement logic for multiple controls in a single Event Handler.

1. “object sender”: to understand about this parameter, add a new Web Form in the project naming it as
“Calculator1.aspx” and write the below code in its “<div>” tag:

<table align="center">
<caption>Calculator</caption>
<tr>
<td>Enter 1<sup>st</sup> number:</td>
<td><asp:TextBox ID="txtNum1" runat="server" /></td>
</tr>

23
<tr>
<td>Enter 2<sup>nd</sup> number:</td>
<td><asp:TextBox ID="txtNum2" runat="server" /></td>
</tr>
<tr>
<td>Result Generated:</td>
<td><asp:TextBox ID="txtResult" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnAdd" runat="server" Text="Add" />
<asp:Button ID="btnSub" runat="server" Text="Sub" />
<asp:Button ID="btnMul" runat="server" Text="Mul" />
<asp:Button ID="btnDiv" runat="server" Text="Div" />
<asp:Button ID="btnMod" runat="server" Text="Mod" />
</td>
</tr>
</table>

Now let's write 1 Event Handler method for all the 5 buttons and to do that go to design view of the form,
select “Add” button, open property window, select Events, select Click Event and beside that specify a name to the
Event Handler - “Buttons_Click” and click on it which will generate the Event Handler with the given name.

Now bind the Event Handler with remaining 4 buttons, and to do that, go to design view again, select “Sub”,
“Mul”, “Div” and “Mod” buttons at a time, open property window, select Events, select Click - Event and now we
will find a drop down beside, click on it which will list the Event Handler - “Buttons_Click” select it which will bind
the “Event Handler” with all 4 buttons. To verify this go to Source View and there we find the binding code as below:

OnClick="Buttons_Click"

Now go to “Calculator1.aspx.cs” file and write the below code over there:
Code under Page_Load:
if (!IsPostBack)
{
txtNum1.Focus();
}

Code under Buttons_Click Event Handler:


int Num1 = int.Parse(txtNum1.Text);
int Num2 = int.Parse(txtNum2.Text);
int result = 0;
Button b = sender as Button;
if (b.ID == "btnAdd")
result = Num1 + Num2;
else if (b.ID == "btnSub")
result = Num1 - Num2;

24
else if (b.ID == "btnMul")
result = Num1 * Num2;
else if (b.ID == "btnDiv")
result = Num1 / Num2;
else if(b.ID == "btnMod")
result = Num1 % Num2;
txtResult.Text = result.ToString();

When an Event Handler is bound with multiple controls we can identify the control which is raising the
Event (Click in our case) by using the “sender” parameter of Event Handler, because we are already aware that every
Control is a class and a control that is placed on the Form is an Instance of that class, so whenever a Control Instance
raises an Event immediately that instance is captured in the “sender” parameter which of type “object” (default
parent class of all classes).

Because “sender” is of type “object” it is not capable of accessing any of the child class members, for
example in the above case “Button” is the child class, and to overcome this problem we need to convert “sender”
back into it’s original format (Button in our case) as we have performed in our above code and then we can read it’s
ID or Text or any other property and implement the logic specific to the control.

2. “EventArgs (or child class of EventArgs) e”: to understand about this parameter, add a new Web Form in the
project naming it as “Calculator2.aspx” and write the below code in its “<div>” tag:

<table align="center">
<caption>Calculator</caption>
<tr>
<td>Enter 1<sup>st</sup> number:</td>
<td><asp:TextBox ID="txtNum1" runat="server" /></td>
</tr>
<tr>
<td>Enter 2<sup>nd</sup> number:</td>
<td><asp:TextBox ID="txtNum2" runat="server" /></td>
</tr>
<tr>
<td>Result Generated:</td>
<td><asp:TextBox ID="txtResult" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnAdd" runat="server" Text="Add" CommandName="+" />
<asp:Button ID="btnSub" runat="server" Text="Sub" CommandName="-" />
<asp:Button ID="btnMul" runat="server" Text="Mul" CommandName="*" />
<asp:Button ID="btnDiv" runat="server" Text="Div" CommandName="/" />
<asp:Button ID="btnMod" runat="server" Text="Mod" CommandName="%" />
</td>
</tr>
</table>

25
In the above case we have set a CommandName property for each Button and this value can be accessed
and used in the Command Event of Button. Now let’s write 1 Event Handler method for all the 5 buttons and to do
that go to design view of the Web Form, select “Add” button, open property window, select Events, select Command
Event and beside it specify a name to the Event Handler i.e., “Buttons_Command” and click on it which will generate
an Event Handler with the given name.

Now to bind the Event Handler with remaining 4 buttons, go to design view again, select “Sub”, “Mul”, “Div”
and “Mod” buttons at a time, open property window, select Events, select Command Event and now we will find a
drop down beside, click on it which will list the Event Handler i.e., “Buttons_Command” select it which will bind the
“Event Handler” with all 4 buttons. Now go to “Calculator2.aspx.cs” file and write the below code there:

Code under Page_Load:


if (!IsPostBack) {
txtNum1.Focus();
}

Code under Buttons_Command:


int Num1 = int.Parse(txtNum1.Text);
int Num2 = int.Parse(txtNum2.Text);
int Num3 = 0;
switch(e.CommandName)
{
case "+":
Num3 = Num1 + Num2;
break;
case "-":
Num3 = Num1 - Num2;
break;
case "*":
Num3 = Num1 * Num2;
break;
case "/":
Num3 = Num1 / Num2;
break;
case "%":
Num3 = Num1 % Num2;
break;
}
txtResult.Text = Num3.ToString();

In the above case we have specified a CommandName to each Button and we can access that
CommandName value under the Event Handler by using “e” of type CommandEventArgs which is nothing but a child
class of EventArgs class, so once we can access the CommandName we can easily identify the Control which is raising
the Event and implement the logic as we have done in the above case.

Note: Same as CommandName we can also use CommandArguments property also but CommandName is of type
string and CommandArguments is of type object, and these 2 can be accessed under Command Event.

26
TextBox Control: we use this control for taking input from the users and we can use this Control in 16 different ways
like Single Line Text, Multi Line Text, Password, etc.

Important members of TextBox Control are:


1. TextMode: By using this property we can set the behavior for the control and this property can be set with any
of the following values:
SingleLine [d] Date Month Number
MultiLine DateTime Time Range
Password DateTimeLocal URL Search
Color Week Email Phone

2. ReadOnly: It’s a Boolean property with default value as false and if set as true, control becomes non editable.
3. Rows: This property is to specify the no. of display rows we want, when the TextMode is set as Multiline.
4. MaxLength: This is to specify the maximum no. of char’s that must be accepted into the Textbox control.
5. AutoPostBack: This is a Boolean property with default value as false, whereas if we set it as true this control
gets the capability of submitting the page to server i.e., it can perform a Postback.
6. TextChanged: This is the default Event of the control which fires when the text property has been changed.

To work with TextChanged event of the TextBox add a new Web Form under the project naming it as
“ColorDialog.aspx” and write the below code under “<form>” tag by deleting existing “<div>” tag over there:

<div id="div1" runat="server">


<br />Change Color: <asp:TextBox ID="txtColor1" runat="server" TextMode="Color" />
<br /><br />
</div>
<asp:Button ID="Button1" runat="server" Text="Button" />

Now go to design view of Web Form, double click on TextBox to generate a “TextChanged” - “EventHandler”
for it and write the below code in corresponding “Event Handlers” defined in “aspx.cs” file:

Code under txtColor1_TextChanged:


div1.Attributes.Add("style", "background-color:" + txtColor1.Text);

Now run the Web Form and select a color under “ColorDialog”, but the background color of corresponding
“<div>” control will not change even if we implemented logic under the “TextChanged” event of TextBox, because
TextBox control is not capable of Submitting the page to server and to overcome this problem, after selecting a Color
in Color Dialog we need to click on the Button we placed below which will Submit the page to server and then the
logic we implemented under “TextChanged” event of Textbox’s will execute.

How the logic is executing when the Button is clicked?


Ans: When a control raises an event but not capable of submitting the page to server, until the page is submitted to
Server the event which is raised gets cached and executes when the page is submitted to the server next time and
we call them as “Cached Events”.

Cached Event: this event will store page data, which gets processed when the page is submitted to the server by a
Postback.

27
In our previous example, if we want the logic to be executed immediately after changing the color, without
waiting for the Button to be click, do the following:
Step 1: Delete the Button on the form.
Step 2: Set the AutoPostBack property of the TextBox as true so that this control will get the capability of submitting
the page to server immediately when the Text (Color) is changed.

Understanding Page Submission: as learnt earlier the process of sending values that are entered by a user in controls
of a page to the Web Server is known as Page Submission and it is of 2 types:
1. Postback Submission
2. Cross Page Submission

Postback Submission: To understand this in detail, let’s create a Login Form and to do that add a new Web Form in
the project naming it as “LoginForm.aspx” and write the below code under “<div>” tag:

<table align="center">
<caption>Login Form</caption>
<tr>
<td>Enter Name:</td>
<td><asp:TextBox ID="txtName" runat="server" /></td>
</tr>
<tr>
<td>Enter Password:</td>
<td><asp:TextBox ID="txtPwd" runat="server" TextMode="Password" MaxLength="16" /></td>
</tr>
<tr>
<td>Enter Email:</td>
<td><asp:TextBox ID="txtEmail" runat="server" TextMode="Email" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="bntSubmit" runat="server" Text="Submit" />
<asp:Button ID="btnReset" runat="server" Text="Reset" />
</td>
</tr>
<tr>
<td colspan="2">
<asp:Label ID="lblStatus" runat="server" ForeColor="Red" />
</td>
</tr>
</table>

Now go to design view, double click on the “Login Button” & “Reset Button” to generate required event
handlers and write the below code in “LoginPage.aspx.cs” file:

Code under Page_Load:


if(!IsPostBack)
txtName.Focus();

28
Code under Login Button Click:
if (txtName.Text == "admin" && txtPwd.Text == "admin#123" && txtEmail.Text == "[email protected]")
{
lblStatus.Text = "Valid User";
}
else
{
lblStatus.Text = "Invalid User";
}

Code Under Reset Button Click:


txtName.Text = txtPwd.Text = txtEmail.Text = lblStatus.Text = "";
txtName.Focus();

Note: in the above Page we have performed a Postback Submission i.e., the Page has submitted the data, back to
itself and was validated. In Postback Submission we can read controls values directly on server by using their name
& associated properties, for example we have read the value of TextBox by using its Text property is our above code.

Cross Page Submission: this is a process of submitting a page to another page and to understand Cross Page
Submission add 2 new Web Forms in the project naming them as “Contact.aspx” and “Respond.aspx”. Write the
below code under “<div>” tag of “Contact.aspx”:

<table align="center">
<caption>Contact Details</caption>
<tr>
<td>Name:</td>
<td><asp:TextBox ID="txtName" runat="server" /></td>
</tr>
<tr>
<td>Phone No:</td>
<td><asp:TextBox ID="txtPhone" runat="server" MaxLength="10" /></td>
</tr>
<tr>
<td>Email Id:</td>
<td><asp:TextBox ID="txtEmail" runat="server" TextMode="Email" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnSubmit" runat="server" Text="Submit" PostBackUrl="~/Respond.aspx" />
<asp:Button ID="btnReset" runat="server" Text="Reset" />
</td>
</tr>
</table>

Now go to design view, double click on the “Reset Button” to generate the event handler and write the
below code in “Contact.aspx.cs” file:

29
Code under Page_Load:
if(!IsPostBack)
txtName.Focus();

Code under Reset Button:


txtName.Text = txtPhone.Text = txtEmail.Text = "";
txtName.Focus();

Run “Contact.aspx”, fill in the details and click on Login button, which will send a request from the browser
to “Respond.aspx” because for Submit Button we have set “PostBackUrl” Property with the value “Respond.aspx”
and we call this as “Cross Page Submission”.

In the process of “Cross Page Submission” all values that are entered into the Controls of “Contact.aspx”
page will be submitted to “Respond.aspx” page, and at this time, lot of information is transferred from the browser
to server like: Session State, Application State, Request Cookie Collection, Response Cookie Collection, Header
Collection, Form Collection, Query String Collection, Server Variable Collection, etc.

Form Collection will contain the information of controls and their values in a “name/value” pair
combination, so in “Respond.aspx” page we can read Form Collection values with the help of “name” using the
Request object and consume their values.

To test that go to “Respond.aspx.cs” file and write the below code under “Page_Load” Method:
string Name = Request.Form["txtName"];
string Phone = Request.Form["txtPhone"];
string Email = Request.Form["txtEmail"];
Response.Write("<h3>Hello " + Name + ", we have received your contact details.</h3>");
Response.Write("Contact Phone: " + Phone + "<br />");
Response.Write("Contact Email: " + Email + "<br />");

Note: in the above, “Request.Form” refers to “Form Collection” and the parameter we pass to it is the “name”
corresponding to the value we want to read.

When data is submitted from 1 page to another page, data transfer from source page to target page will be
done in any of the 2 methods: Get Method or Post Method.

For Html Form’s the default method is “get” and if we want to change it we require to use “method”
attribute on the “<form>” element and specify it as “post” as following:
<form id="form1" method="post">

For ASPX Form’s the default method is “post” and if we want to change it we require to use “method”
attribute on the “<form>” element and specify it as “get” as following:
<form id="form1" runat="server" method="get">

Currently “Contact.aspx” is using an ASPX Form and so the submit method is “post” and if we want to
change it as “get”, go to “Contact.aspx” file and add “method” attribute to “<form>” tag with value as “get” and it
should now look as following:
<form id="form1" runat="server" method="get">

30
Run “Contact.aspx” Form again, enter values into the controls and click on “Submit” button which will
Submit, Control values to “Respond.aspx” but the difference is when the submit method is Post, values will go to
target page as “Form Collection”, whereas when the Submit method is Get, values will go to target page as “Query
String Collection”, so right now “Respond.aspx” page will not display any values that we entered in “Contact.aspx”
page. To resolve the problem, go to “Respond.aspx.cs” file and change “Request.Form” as “Request.QueryString” in
“Page_Load” method which should now look as below:
string Name = Request.QueryString["txtName"];
string Phone = Request.QueryString["txtPhone"];
string Email = Request.QueryString["txtEmail"];

Note: when we are not sure whether the submit method is “Get” or “Post” then we can directly read the values
using Request object without specifying the Query String or Form as below:
string Name = Request["txtName"];
string Phone = Request["txtPhone"];
string Email = Request["txtEmail"];

Differences between Get and Post:


1. In case of Get the data that has to be transferred from browser to server will be concatenated to the URL of
page we are requesting (target page) in the form of a “Query String” and we can view those values in the Address
Bar of our browser, whereas in case of Post, data will be passed through “Http Headers” which is not at all visible
to the end user.

Note: Http Headers let the client and server pass additional information with an Http Request or Http Response.

2. Get is faster in transfer when compared to Post whereas Post is secured compared to Get.
3. Get is not recommended for transporting sensitive info like password, credit card details, etc. as the values are
visible in address bar whereas Post is secured method of transporting because, data is transferred through HTTP
Headers by using secure HTTP protocol, so we can make sure that data is secured.
4. In case of Get we have limitations on the data being submitted i.e., the maximum length of a URL can be 2048
characters only whereas we don’t have any size limitations for data in Post.
5. In case of Get we access data from “Query String Collection” whereas in case of Post we access data from “Form
Collection” on the target pages.

How do we specify the URL of target page for a Cross Page Submission?
Ans: we specify the URL of target page for “Cross Page Submission” using the “PostBackUrl” property of Button
whereas in other web technologies we specify that by using “action” attribute of form. We can use that in ASP.NET
also and to test that delete the “PostBackUrl” property associated with “Submit” Button, then go to “<form>” tag
and add action attribute to it, which should now look as below:

<form id="form1" runat="server" method="get" action="Respond.aspx">

Run the page again and watch, now also when we click on “Submit” button, page will be submitted to
“Respond.aspx”. The drawback in this approach is not only “Submit” button of our page, “Reset” button of our page
also will do “Page Submission” to “Respond.aspx”, and to avoid this problem, without using form’s “action” attribute
we use button’s “PostBackUrl” attribute, so that “Submit” button performs “Cross Page Submission” and “Reset”
button will perform “Postback Submission”.

31
Transferring control from 1 page to another page: we can transfer control from 1 page to another page, in a Web
Application and that can be performed in 2 different ways:
1. Server.Transfer
2. Response.Redirect

To check transferring of the control from 1 page to another page add 3 new Web Forms in the project
naming them as: LoginPage.aspx, SuccessPage.aspx and FailurePage.aspx. Now go to LoginPage.aspx, define style
for body tag and set a background-color to it: <body style="background-color:lawngreen"> and then write the below
code in “<div>” tag:

<table align="center">
<caption>Login Page</caption>
<tr>
<td>User Name:</td>
<td><asp:TextBox ID="txtName" runat="server" /></td>
</tr>
<tr>
<td>Password:</td>
<td><asp:TextBox ID="txtPwd" runat="server" TextMode="Password" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnReset" runat="server" Text="Reset" />
<asp:Button ID="btnLogin" runat="server" Text="Login" />
</td>
</tr>
</table>

Now generate Click Event Handlers for Login and Reset Button, and write the below code in
“LoginPage.aspx.cs” file:

Code under Page_Load:


if(!IsPostBack) {
txtName.Focus();
}

Code under Reset Button:


txtName.Text = txtPwd.Text = "";
txtName.Focus();

Code under Login Button:


if(txtName.Text == "admin" && txtPwd.Text == "admin")
Server.Transfer("SuccessPage.aspx");
else
Response.Redirect("FailurePage.aspx");

32
Now go to “SuccessPage.aspx” and set “style” attribute for “<body>” tag which should look as below:
<body style="background-color:deepskyblue">

Now go to “FailurePage.aspx” and set “style” attribute for “<body>” tag which should look as below:
<body style="background-color:gold">

Now run “LoginPage.aspx” enter valid credentials and click on “Login” button which will take you to
“SuccessPage.aspx” and when we enter any in-valid credentials and click on “Login” button it will take you to
“FailurePage.aspx”.

Server.Transfer: in this case the transfer between source and target pages will be performed within the server only
i.e., when we enter valid credentials and click on the Login button first it goes to “LoginPage” because it is a
“Postback” and from there “Server.Transfer” will transfer the control to SuccessPage as following:

Response.Redirect: in this case the transfer between source and target pages will be performed thru the browser
i.e., when we enter in-valid credentials and click on the Login button first it goes to “LoginPage” because it is a
“PostBack” and from there “Response.Redirect” will send a re-direction (302) response to the browser, asking the
browser to make a new request to server for “FailurePage”, so browser will make a request to the server for
“FailurePage” and receives the page as response, as following:

Differences between Server.Transfer and Response.Redirect methods:


1. In case of Server.Transfer, transfer between pages is performed directly on the Web Server it-self, whereas in
case of Response.Redirect, transfer between pages is performed from the browser.
2. Server.Transfer is faster in execution because it will not have any extra round trips between the browser and
server whereas in case of Response.Redirect there will be extra round trips between the browser and server, so
execution is not faster.
3. In case of Server.Transfer the URL in browser’s Address bar will not be updated with new page Address, so we
can’t bookmark the page whereas it happens in case of Response.Redirect, so we can bookmark the page.
4. In case of Server.Transfer we can transfer only to the pages of same site whereas in the case of
Response.Redirect we can transfer to pages of same site as well as other sites on the same server as well as
other servers also.

33
Accessing Source Page values in Target Pages when the control is transferred from one Page to another Page:
In case of Server.Transfer, target page i.e., “SuccessPage.aspx” can directly access values from source page
i.e., “LoginPage.aspx” and this can be done in 2 different ways:
1. Target pages can directly read Form Collection or Query String Collection values that are submitted to Source
Page by using Request object and to test this write the below code in Page_Load method of
“SuccessPage.aspx.cs” file:
string Name = Request.Form["txtName"];
Response.Write($"Hello {Name}, welcome to the site.");

2. Using PreviousPage property in Target Page we can get the reference of Source Page and then access all the
members of Source Page i.e., Controls & its Members as well as other member of Page like Properties, Methods,
Events etc. To test this, re-write the code present in Page_Load method of SuccessPage.aspx.cs file as below:
Page lp = PreviousPage;
Control ctrl = lp.FindControl("txtName");
TextBox tb = (TextBox)ctrl;
string Name = tb.Text;
Response.Write($"Hello {Name}, welcome to the site.");
or
Control ctrl = PreviousPage.FindControl("txtName");
TextBox tb = (TextBox)ctrl;
string Name = tb.Text;
Response.Write($"Hello {Name}, welcome to the site.");
or
TextBox tb = (TextBox)PreviousPage.FindControl("txtName");
string Name = tb.Text;
Response.Write($"Hello {Name}, welcome to the site.");
or
string Name = ((TextBox)PreviousPage.FindControl("txtName")).Text;
Response.Write($"Hello {Name}, welcome to the site.");

In case of Response.Redirect target page i.e., “FailurePage” can’t access any values of source page i.e.,
“LoginPage” directly, so if we want the values of source page in target page then we need to explicitly transfer those
values as a “Query String” by concatenating to the Url of the Page to where we are transferring the control. To test
this, first go to “LoginPage.aspx.cs” file and re-write the statement “Response.Redirect” which is present in the else
part of Login Button - Click Event Handler as below:

Old Code:
Response.Redirect("FailurePage.aspx");

New Code:
Response.Redirect("FailurePage.aspx?Name=" + txtName.Text);

Now we can read this value in “FailurePage” from the “QueryString” Collection by using the Request object
and to test that write this code in “Page_Load” Event Handler of “FailurePage.aspx.cs” file:

string Name = Request.QueryString["Name"];


Response.Write($"Hello {Name}, your credentials are in-valid.");

34
RadioButton and CheckBox Controls: we use these controls to provide the users with a list of values to choose from,
so that users can select from those values. Radio Buttons are used in-case we want to provide an option for single-
selection and Checkbox’s are used in-case we want to provide an option for multi-selection. Both Radio Button and
Check Box Controls provides a boolean property called “Checked” using which we can recognize whether the control
is selected or not, which returns true if selected and false if not selected.

Note: in-case of Radio Button control we need to explicitly tell from how many Radio Button’s 1 value should be
selected and to do that we need to use “Group Name” attribute and group the Radio Button’s so that 1 Radio Button
can be selected from each group.

To work with “Check Box” and “Radio Button” controls add a new Web Form in our project naming it as
“RadioAndCheck.aspx” and write the below code under “<div>” tag:

Name:
<asp:TextBox ID="txtName" runat="server" /> <br />

Gender:
<asp:RadioButton GroupName="Gender" ID="rbMale" runat="server" Text="Male" />
<asp:RadioButton GroupName="Gender" ID="rbFemale" runat="server" Text="Female" />
<asp:RadioButton GroupName="Gender" ID="rbTrans" runat="server" Text="Transgender" /> <br />

Eating Habbit:
<asp:RadioButton GroupName="Habbit" ID="rbVeg" runat="server" Text="Vegetarian" />
<asp:RadioButton GroupName="Habbit" ID="rbNonVeg" runat="server" Text="Non Vegetarian" />
<asp:RadioButton GroupName="Habbit" ID="rbVegan" runat="server" Text="Vegan" /> <br />

Hobbies:
<asp:CheckBox ID="cbReading" runat="server" Text="Reading Books" />
<asp:CheckBox ID="cbPlaying" runat="server" Text="Playing Games" />
<asp:CheckBox ID="cbWatching" runat="server" Text="Watching Movies" />
<asp:CheckBox ID="cbPainting" runat="server" Text="Drawing & Painting" /> <br />

<asp:Button ID="btnSubmit" runat="server" Text="Submit Values" /> <br />


<asp:Label ID="lblMsg" runat="server" ForeColor="Red" />

Now generate a Click Event Handler form “Display Values” button, import the namespace “System.Text”
and write the below code in “RadioAndCheck.aspx.cs” file:

using System.Text;
Code under Page Load Event:
if (!IsPostBack) {
txtName.Focus();
}

Code under Display Button Click Event:


StringBuilder sb = new StringBuilder();

35
if (txtName.Text.Trim().Length > 0)
sb.Append($"Name: {txtName.Text}<br />");

if (rbMale.Checked)
sb.Append($"Gender: Male<br />");
else if(rbFemale.Checked)
sb.Append($"Gender: Female<br />");
else if(rbTrans.Checked)
sb.Append($"Gender: Transgender<br />");

if (rbVeg.Checked)
sb.Append($"Eating Habbit: Vegetarian<br />");
else if((rbNonVeg.Checked))
sb.Append($"Eating Habbit: Non-Vegetarian<br />");
else if(rbVegan.Checked)
sb.Append($"Eating Habbit: Vegan<br />");

List<string> list = new List<string>();


if (cbPlaying.Checked)
list.Add("Playing Games");
if (cbReading.Checked)
list.Add("Reading Books");
if (cbWatching.Checked)
list.Add("Watching Movies");
if (cbPainting.Checked)
list.Add("Drawing & Painting");

if (list.Count > 0)
sb.Append($"Hobbies: {String.Join(", ", list)}");

lblMsg.Text = sb.ToString();

List Controls: These controls are also used for providing the users with a list of values to choose from. We have 4
List Controls in ASP.NET Web Forms and those are:
1. DropDownList
2. ListBox
3. RadioButtonList
4. CheckBoxList

 DropDownList: default visible items are 1 and we can select only 1 item.
 ListBox: default visible items are multiple, and we can select 1 or more items.
 RadioButtonList: default visible items are multiple, but we can select only 1 item.
 CheckBoxList: default visible items are multiple, and we can select 1 or more items.

To work with these controls first we need to add values into them, and every value of a List Control is known
as a ListItem (class) and each value is an instance of this class. Every ListItem is associated with 4 attributes:

36
 Text
 Value
 Enabled
 Selected
 Text refers to the “Display Member” of the control i.e., what user views.
 Value refers to the “Value Member” of the control i.e., this is not visible to end users but used for implementing
the background logic.
 Enabled is a Boolean property with default value true and if set as false this ListItem is not visible to end users.
 Selected is a Boolean property with default value false and if set as true this ListItem is selected by default.

To work with List Controls, add a new Web Form in our project naming it as “ListControls1.aspx”, add 1
DropDownList, ListBox, RadioButtonList and CheckBoxList controls on the Form.

Adding List Item’s into List Controls: to add List Item’s into List Controls we are provided with 5 different options,
those are:

1. By using the Items property in properties window we can add List Item’s into a List Control and to do that, in
the design view of Web Form select “DropDownList”, go to its properties, select Items property and click on the
button beside it which open “ListItem Collection Editor” window, click on the “Add Button” which will add a new
ListItem in the LHS and now on the RHS it will display the 4 attributes where we can enter “Text & Value” for
each ListItem. Follow this process and add 6 Countries into the Control with below Text & Value.
Text Value
India C1
Japan C2
China C3
France C4
America C5
Australia C6

Note: This action will write all the necessary code in Source file and to view that code go to Source View and watch
the “Inner Html” of “DropDownList” which will be as following:
<asp:ListItem Value="C1">India</asp:ListItem>
<asp:ListItem Value="C2">Japan</asp:ListItem>
<asp:ListItem Value="C3">China</asp:ListItem>
<asp:ListItem Value="C4">France</asp:ListItem>
<asp:ListItem Value="C5">America</asp:ListItem>
<asp:ListItem Value="C6">Australia</asp:ListItem>

2. Same as the above code what VS has generated for “DropDownList”, we can also manually write that code in
Source View and to test that write the following code as “Inner Html” to “ListBox”:
<asp:ListItem Text="Kerala" Value="S1" />
<asp:ListItem Text="Tamilnadu" Value="S2" />
<asp:ListItem Text="Karnataka" Value="S3" />
<asp:ListItem Text="Telangana" Value="S4" />
<asp:ListItem Text="Maharastra" Value="S5" />
<asp:ListItem Text="Andhra Pradesh" Value="S6" />

37
3. We can also add Item’s to List Controls thru “C# Code” in Code View by calling “Items.Add” method on the
“ListControl” and this method is an overloaded method which is provided with 2 overloads:
<ListControl>.Items.Add(string Item)
<ListControl>.Items.Add(ListItem Item)

Note: in case of the first overload, we are passing string as a parameter and internally it creates a “ListItem” and the
“Text & Value” will be same i.e., the string what we passed over there only will be taken as “Text & Value” also,
whereas in case of the second overload we need to explicitly create a “ListItem” with a “Text & Value”, and add it to
the List Control. To test the above go to “ListControl1.aspx.cs” file and write the below code in “Page_Load” Event
Handler:
RadioButtonList1.Items.Add("Delhi");
RadioButtonList1.Items.Add("Kolkata");
RadioButtonList1.Items.Add("Mumbai");
RadioButtonList1.Items.Add(new ListItem("Chennai", "City4"));
RadioButtonList1.Items.Add(new ListItem("Bengaluru", "City5"));
RadioButtonList1.Items.Add(new ListItem("Hyderabad", "City6"));

4. Same as the above we have another method “Items.AddRange” and by using this we can add an Array of List
Item’s at a time into the control.
<ListControl>.Items.AddRange(ListItem[] Items)

To test the above go to “ListControls1.aspx.cs” file and write the below code in “Page_Load” Event Handler:
ListItem color1 = new ListItem("Red", "Color1");
ListItem color2 = new ListItem("Blue", "Color2");
ListItem color3 = new ListItem("White", "Color3");
ListItem color4 = new ListItem("Green", "Color4");
ListItem color5 = new ListItem("Purple", "Color5");
ListItem color6 = new ListItem("Magenta", "Color6");
ListItem[] colors = new ListItem[] { color1, color2, color3, color4, color5, color6 };
CheckBoxList1.Items.AddRange(colors);
Or
ListItem[] colors = new ListItem[]
{
new ListItem("Red", "Color1"),
new ListItem("Blue", "Color2"),
new ListItem("White", "Color3"),
new ListItem("Green", "Color4"),
new ListItem("Purple", "Color5"),
new ListItem("Magenta", "Color6")
};
CheckBoxList1.Items.AddRange(colors);
Or
CheckBoxList1.Items.AddRange(new ListItem[] {
new ListItem("Red", "Color1"),
new ListItem("Blue", "Color2"),
new ListItem("White", "Color3"),

38
new ListItem("Green", "Color4"),
new ListItem("Purple", "Color5"),
new ListItem("Magenta", "Color6")
});

5. By using “DataSource” property of List Control’s we can assign values from a DataSource like a File or Database.
<ListControl>.DataSource = <Data_Table>;
<ListControl>.DataTextField = <Column_Name>;
<ListControl>.DataValueField = <Column_Name>;
<ListControl>.DataBind();

Behavior of each List Control:


1. DropDownList: This control is used in-case we want to provide the option for single selection.
2. ListBox: This control by default supports single selection only whereas if we want multi-selection then we need
to set “SelectionMode” property of the control as “Multiple” because, default is “Single”.
3. RadioButtonList: This control is also like DropDownList control, providing support for single selection only
whereas in case of RadioButtonList we find a Radio Button beside each item for selection.
4. CheckBoxList: this control works same as a RadioButtonList, but the only difference is it supports Multi-Selection
with a CheckBox beside each item for selection.

Note: RadioButtonList and CheckBoxList provides a property “RepeatDirection” and by using it we can specify the
direction in which “List Items” are laid out, default is “Vertical” direction and can be changed to “Horizontal”. By
using the “RepeatLayout” property we can set layout for “List Items” which is by default “Table” but can be changed
to “Flow”, “OrderedList” and “UnOrderedList” (OrderedList and UnOrderList layout will not work in case the
“RepeatDirection” is set as Horizontal i.e., will work only in case of Vertical). By using “RepeatColumns” property we
can specify the number of columns to layout the “List Items”.

Accessing values from ListControls: to access values from List Controls we are provided with a set of Members under
them as following:
1. Items: by using this property we can access all the Items of a ListControl which returns them in the form of
ListItem Array.
<ListControl>.Items => ListItem[]
2. SelectedItem: by using this property we can access the “SelectedItem” form the ListControl which will return
the value as a ListItem.
<ListControl>.SelectedItem => ListItem (Text, Value, Enabled, and Selected)
3. SelectedValue: this property returns the “Value” that is associated with a selected “ListItem” in the form of a
string.
<ListControl>.SelectedValue => String (Only Value)
4. Text: this property is also same as “SelectedValue” only which returns the “Value” that is associated with a
selected ListItem in the form of a string.
<ListControl>.Text => String (Only Value)
5. SelectedIndex: this property returns the index position of the selected “ListItem” in the form of int.
<ListControl>.SelectedIndex => int
6. GetSelectedIndices(): this is a method present under “ListBox” control that returns an array of indices
corresponding to the SelectedItems.
<ListBox>.GetSelectedIdices => int[]

39
Note: the first 5 members are available under all the controls whereas the last member i.e., “GetSelectedIndices” is
specific to “ListBox” control.

XML: Extensible Markup Language


 This is also a markup language like HTML but used for describing the content of a Text Document.
 This is used in the industry for transporting the data from 1 machine to another machine apart from Excel and
CSV (Comma Separated Values).
 This can also be used as a Temporary Database in scenarios where we don’t have access to a Live Database.
 XML is Platform Independent which can be used in any O.S. as well as every application provides options to read
data from XML.
 Just like HTML, XML data is also present under Tags, but the difference is HTML tags are pre-defined whereas
XML tags are user-defined.
 An XML document should be saved with “.xml” extension.
 An XML document can have 1 & only 1 root element.
 A simple XML documents looks as following:

<Employees>
<Employee SerialNo="1">
<Id>1001</Id>
<Name>Scott</Name>
<Job>Manager</Job>
<Salary>50000</Salary>
</Employee>
<Employee SerialNo="2">
<Id>1002</Id>
<Name>Smith</Name>
<Job>Salasman</Job>
<Salary>15000</Salary>
</Employee>
<!--Enter multiple employees data-->
</Employees>

 XML is case sensitive, so we need to strictly follow the same case for starting and ending tag.
<Id>101</Id> => Valid
<Id>101</ID> => Invalid
 To understand XML, we need a software known as XML Parser and this is built into every browser.
 XML tags also can have attributes, for example we have defined “SerialNo” as an attribute for “Employee” tag,
but values to those attributes must be enclosed in double quotes (Mandatory).

Note: our “aspx” code in ASP.NET completely follows XML syntax’s only.

Loading Data into List Control’s from an XML File: to load data into List Controls from XML File do the below.

Step 1: Add a Web Form naming it is as “ListControls2.aspx” and write the following code under its “<div>” tag:
<table align="center" border="1">
<caption>Product Catalog</caption>

40
<tr>
<td align="center"><asp:DropDownList ID="DropDownList1" runat="server" /></td>
<td align="center"><asp:ListBox ID="ListBox1" runat="server" SelectionMode="Multiple" /></td>
<td align="center"><asp:RadioButtonList ID="RadioButtonList1" runat="server" /></td>
<td align="center"><asp:CheckBoxList ID="CheckBoxList1" runat="server" /></td>
</tr>
<tr>
<td align="center"><asp:Button ID="Button1" runat="server" Text="Show Selected Product" /></td>
<td align="center"><asp:Button ID="Button2" runat="server" Text="Show Selected Products" /></td>
<td align="center"><asp:Button ID="Button3" runat="server" Text="Show Selected Product" /></td>
<td align="center"><asp:Button ID="Button4" runat="server" Text="Show Selected Products" /></td>
</tr>
<tr>
<td><asp:Label ID="Label1" runat="server" ForeColor="Red" /></td>
<td><asp:Label ID="Label2" runat="server" ForeColor="Red" /></td>
<td><asp:Label ID="Label3" runat="server" ForeColor="Red" /></td>
<td><asp:Label ID="Label4" runat="server" ForeColor="Red" /></td>
</tr>
</table>

Step 2: In “Add New Item” window, choose XML File item, name it as “Products.xml” and write the below code.
<Products>
<Product>
<Id>101</Id>
<Name>Television</Name>
</Product>
<Product>
<Id>102</Id>
<Name>Microwave</Name>
</Product>
<Product>
<Id>103</Id>
<Name>Washing Machine</Name>
</Product>
<Product>
<Id>104</Id>
<Name>Refrigerator</Name>
</Product>
<Product>
<Id>105</Id>
<Name>Home Theatre</Name>
</Product>
<Product>
<Id>106</Id>
<Name>Mixer Grinder</Name>
</Product>

41
<Product>
<Id>107</Id>
<Name>Blu-ray Player</Name>
</Product>
<Product>
<Id>108</Id>
<Name>Split A/C</Name>
</Product>
<Product>
<Id>109</Id>
<Name>Air Cooler</Name>
</Product>
<Product>
<Id>110</Id>
<Name>Window A/C</Name>
</Product>
</Products>

Step 3: Now go to design view of the Web Form, generate Event Handlers for all the 4 Buttons and write the below
code in “ListControls2.aspx.cs” file:

using System.Data;
Code under Page Load Event:
if (!IsPostBack) {
string xmlFilePath = Server.MapPath("~/Products.xml");
DataSet ds = new DataSet();
ds.ReadXml(xmlFilePath);

DropDownList1.DataSource = ds;
DropDownList1.DataTextField = "Name";
DropDownList1.DataValueField = "Id";
DropDownList1.DataBind();
DropDownList1.Items.Insert(0, "-Select Product-");

ListBox1.DataSource = ds;
ListBox1.DataTextField = "Name";
ListBox1.DataValueField = "Id";
ListBox1.DataBind();

RadioButtonList1.DataSource = ds;
RadioButtonList1.DataTextField = "Name";
RadioButtonList1.DataValueField = "Id";
RadioButtonList1.DataBind();

CheckBoxList1.DataSource = ds;
CheckBoxList1.DataTextField = "Name";
CheckBoxList1.DataValueField = "Id";

42
CheckBoxList1.DataBind();
}
Code under Button1 Click Event:
if (DropDownList1.SelectedIndex > 0) {
ListItem li = DropDownList1.SelectedItem;
Label1.Text = li.Value + ": " + li.Text;
}
Code under Button2 Click Event:
Label2.Text = "";
foreach(int index in ListBox1.GetSelectedIndices()) {
ListItem li = ListBox1.Items[index];
Label2.Text += li.Value + ": " + li.Text + "<br />";
}
Code under Button3 Click Event:
if (RadioButtonList1.SelectedItem != null) {
ListItem li = RadioButtonList1.SelectedItem;
Label3.Text = li.Value + ": " + li.Text;
}
Code under Button4 Click Event:
Label4.Text = "";
foreach(ListItem li in CheckBoxList1.Items) {
if(li.Selected) {
Label4.Text += li.Value + ": " + li.Text + "<br />";
}
}

DataSet is a class, present under “System.Data” namespace which can read the data from an XML File or Database
and hold it in a Table format.

MapPath is a method of “HttpServerUtility” class, and this method returns the Physical Path of a file when we pass
Virtual Path of the file.

ASP.NET Web Configuration File


The Microsoft .NET Framework, and ASP.NET, uses XML-formatted “.config” files to configure applications.
The .NET Framework relies on “.config” files to define configuration options. The .config files are text-based XML
files. Multiple “.config” files can, and typically do, exist on a single system. The behavior of an ASP.NET Application
is affected by different settings in the configuration files like “machine.config” and “web.config”.

Machine.config: System-wide configuration settings for .NET Framework are defined in the Machine.config file. The
Machine.config file is in the %SystemRoot%\Microsoft.NET\Framework\%VersionNumber%\CONFIG\ folder. The
default settings that are contained in the Machine.config file can be modified to affect the behavior of Microsoft
.NET Applications on the whole system.

Web.config: You can change the ASP.NET configuration settings for a single application if you create a Web.config
file in the root folder of the application. When you do this, the settings in the Web.config file override the settings

43
in the Machine.config file. The Web.config file must contain only entries for configuration items that override the
settings in the Machine.config file. At a minimum, the Web.config file must have the <configuration> element and
the <system.web> element. These elements will contain individual configuration elements as following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration><system.web></system.web></configuration>

The first line of the Web.config file describes the document as XML-formatted and specifies the character
encoding type. This first line must be the same for all “.config” files. The lines that follow mark the beginning and
the end of the <configuration> element and the <system.web> element of the Web.config file. By themselves, these
lines do nothing. However, the lines provide a structure that permits you to add future configuration settings. You
add the majority of the ASP.NET Configuration Settings between the <system.web> and </system.web> lines.

The ASP.NET configuration system features an extensible infrastructure that enables you to define
configuration settings at the time your ASP.NET applications are first deployed so that you can add or revise
configuration settings at any time with minimal impact on operational Web Applications and Servers.

The ASP.NET configuration system provides the following benefits:


 Configuration information is stored in XML-based text files. You can use any standard text editor or XML parser
to create and edit ASP.NET configuration files.
 Multiple configuration files, all named Web.config, can appear in multiple directories on an ASP.NET Web
application server. Each Web.config file applies configuration settings to its own directory and all child
directories below it. Configuration files in child directories can supply configuration information in addition to
that inherited from parent directories, and the child directory configuration settings can override or modify
settings defined in parent directories. The root configuration file named Machine.config provides ASP.NET
configuration settings for the entire Web server.
 At run time, ASP.NET uses the configuration information provided by the Web.config files in a hierarchical virtual
directory structure to compute a collection of configuration settings for each unique URL resource. The resulting
configuration settings are then cached for all subsequent requests to a resource. Note that inheritance is defined
by the incoming request path (the URL), not the file system paths to the resources on disk (the physical paths).
 ASP.NET detects changes to configuration files and automatically applies new configuration settings to Web
resources affected by the changes. The server does not have to be rebooted for the changes to take effect.
Hierarchical configuration settings are automatically recalculated and recached whenever a configuration file in
the hierarchy is changed.
 The ASP.NET configuration system is extensible. You can define new configuration parameters and write
configuration section handlers to process them.
 ASP.NET help protect configuration files from outside access by configuring Internet Information Services (IIS)
to prevent direct browser access to configuration files. HTTP access error 403 (forbidden) is returned to any
browser attempting to request a configuration file directly.

Various Sections in Web.config file:


<system.web>: this element contains information about how the ASP.NET hosting layer manages application
behavior.

<system.codedom>: this element contains compiler configuration settings for language providers installed on a
computer in addition to the default providers that are installed with the .NET Framework, such as the
CSharpCodeProvider and the VBCodeProvider.

44
<system.net>: this element contains settings that specify how the .NET Framework connects to the network i.e., it
contains network connection details.

<appSettings>: this element stores custom application configuration information, such as file paths, XML Web
service URLs, or any other custom configuration information for an application. Information is stored in the
<appSettings> as key/value pairs and those elements are accessed in code using the ConfigurationSettings class.

<connectionStrings>: this element contains initialization information that is passed as a parameter from an
application to a data source. Information is stored in the <connectionStrings> as key/value pairs and those elements
are accessed in code using the ConfigurationSettings class.

Validation Controls
Validation is an important part of any Web Application. Whenever the user gives input in a Web Page, it
must always be validated before sending it across various layers of an application. If we get the user input without
any validation, then chances are that data might be wrong. So, validation is a good idea to do whenever we are
taking input from the user. In Web Application validations are performed in 2 different levels:

1. Client-Side Validation
2. Server-Side Validation

Client-Side Validation: When a validation is done on the client’s browser, then it is known as Client-Side validation.
We use Java Script to do Client-Side validations. Since many years, developers are using Java Script for Client-Side
validations. Client-side validation is very good, but we must be dependent on browser and scripting language
support. Client-side validation is considered convenient for users as they get instant feedback. The main advantage
is that it prevents a page from being submitted to the server until the client validation is executed successfully.

Server-Side Validation: When a validation occurs on the server, then it is known as Server-Side validation. Server-
Side validation is a secure form of validation. The main advantage of Server-Side validation is that if the user
somehow bypasses the Client-Side validation by disabling “Java Script” on his browser, we can still catch the problem
on Server. Server-Side provides more security and ensures that no invalid data is processed by the application.
Server-Side validation is done by writing the custom logic for validating the input, and developer point of view Server-
Side is preferable because it will not fail, it is not dependent on browser and scripting languages.

Validation Controls in ASP.NET: To simplify validations in ASP.NET we are provided with validation controls and
these controls will perform data validations on the “Client Side” as well as on the “Server Side” i.e., first they will
perform client-side validations by using Java Script, and if at all validations fail it will stop the page being submitted
to the server, and in-case if the client disables Java Script on his browser then page will be submitted to server even
when the validations fail and in such scenarios Validation Controls will re-validate data on the server-side again. So,
at any cost server-side validation will work, whether client-side validation is executed or not, so we have safety of
validation check.

An important aspect of creating ASP.NET Web Pages for user input is to be able to check that the
information users enter is valid. ASP.NET provides a set of controls known as Validation Controls that provide an
easy-to-use and powerful way to check for errors and, if necessary, display messages to the user. The following is
the list of Validation Controls we have in ASP.NET:

45
 RequiredFieldValidator
 CompareValidator
 RangeValidator
 RegularExpressionValidator
 CustomValidator
 ValidationSummary

Validation Controls are classes which are inherited from the class “BaseValidator” hence they inherit its
properties, events, and methods. Therefore, it would help us to look at the properties and the methods of that base
class, which are common for all the validation controls:

1. ControlToValidate: by using this property we need to specify the “Id” of Input Control which must be validated
by the Validation Control.
2. Display: this is an Enumerated Property using which we can set how the “Error Message” is shown on the
browser and it can be set with any of the following values like: Static[d], Dynamic and None.
3. EnableClientScript: this is a Boolean property which indicates whether client-side validation should take place
or not. The default value is true and if set as false then client-side validations will not take place.
4. Enabled: this is a Boolean property with default value true and if set as false then validator gets disabled i.e., it
will not validate the input control.
5. ErrorMessage: this property is used to specify an Error Message that must be displayed when the validation
fails, and this message is also copied by the “Validation Summary” control.
6. Text: this is also like “Error Message” property only, but when both the properties are set with a value, first
preference is given to “Text” only which is displayed at the place where validation control is placed whereas
Error Message values will be used by the “Validation Summary” control.
7. SetFocusOnError: this is a Boolean property with default value false and when set as true will set the focus back
in to the Input Control which has been validated by the Validation Control if the validation fails.
8. ValidationGroup: this property is used to group a set of controls on the page, so that Validations in 1 group will
not affect validations of another group while submitting the Page.
9. IsValid: this is a Boolean property which indicates whether the value of the input control is valid or not.
10. ForeColor: this property is to specify the color in which Error Messages should be displayed.

ASP.NET Web Forms have provided Validation Controls since the initial releases. Prior to ASP.NET 4.5 in a
normal validation scenario, when we use a validator to validate any control and use client-side validation, some Java
Script is generated and rendered as HTML. Also, some supportive Java Script files are also get loaded by the browser
for the validation. Unobtrusive Java Script is the way of writing Java Script language in which we properly separate
Document Content and Script Content thus allowing us to make a clear distinction between them. This approach is
useful in so many ways as it makes our code less error prone, easy to update and debug.

From ASP.NET 4.5 we need to explicitly specify how ASP.NET globally enables the built-in validator controls
to use Unobtrusive Java Script for client-side validation logic and we can set it with any of the 2 values like “None”
or “Web Forms”. If this key’s value is set to “None”, the ASP.NET application will use the pre - 4.5 behavior (Java
Script inline in the pages) for client-side validation logic. If this key’s value is set to “Web Forms”, ASP.NET uses Html
5 data-attributes and late bound Java Script from an added script reference for client-side validation logic. We can
set the unobtrusive validation mode in Global.asax file or in the individual Web Form or Web.Config.

46
Option 1: To set Unobtrusive Validation Mode in Global.asax file we need to set the UnobtrusiveValidationMode
property of ValidationSettings class in the Application_Start Event Handler by importing the namespace
“System.Web.UI” as following:
ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None;

Option 2: To set Unobtrusive Validation Mode in a Web Form we need to set the UnobtrusiveValidaionMode
property of ValidationSettings class in Page_Load Event Hander of each Web Form as following:
this.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None;

Option 3: To set unobtrusive validation mode in Web.config file we need to add a new key under <appSettings> tag
with the name “ValidationSettings:UnobtrusiveValidationMode” and value as “none” as below. If <appSettings> tag
is present, then directly add the following:
<add key="ValidationSettings:UnobtrusiveValidationMode" value="none" />

If <appSettings> tag is not present, then write it as following:


<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="none" />
</appSettings>

RequiredFieldValidator: This validation control is used to check whether the input control is left empty or not i.e., it
should either be entered with a value or selected with a value. This control has a property which is specific to itself:

1. InitialValue: this property is to specify a value, which the Validation Control should not take into consideration
while validating the Input Control.

Add a Web Form in the project naming it as “Validations1.aspx” and write the below code under its <div> tag:
Enter Name: <asp:TextBox ID="txtName" runat="server" />
<asp:ReqiredFieldValidator ID="rfvName" runat="server" ControlToValidate="txtName" ForeColor="Red"
ErrorMessage="Can't leave the field empty." Display="Dynamic" SetFocusOnError="true" />
<br />
Select Country:
<asp:DropDownList ID="ddlCountries" runat="server">
<asp:ListItem Text="-Select Country-" Value="NS" />
<asp:ListItem Text="India" Value="Country1" />
<asp:ListItem Text="Japan" Value="Country2" />
<asp:ListItem Text="China" Value="Country3" />
<asp:ListItem Text="England" Value="Country4" />
<asp:ListItem Text="America" Value="Country5" />
<asp:ListItem Text="Australia" Value="Country6" />
</asp:DropDownList>
<asp:RequiredFieldValidator ID="rfvCountry" runat="server" ControlToValidate="ddlCountries" ForeColor="Red"
ErrorMessage="Please select a country." InitialValue="NS" Display="Dynamic" SetFocusOnError="true" />
<br />
<asp:Button ID="btnSubmit" runat="server" Text="Submit Data" />
<br />
<asp:Label ID="lblMsg" runat="server" />

47
Now goto “aspx.cs” file and write the below code in it:
Code under Page_Load Event Handler:
if (!IsPostBack) {
txtName.Focus();
}

Code under Submit Page Button Click Event Handler:


lblMsg.Text = $"Hello {txtName.Text}, the country you belongs to is: {ddlCountries.SelectedItem.Text}";

Now run the Web Form and watch the output, where we notice when the 2 input controls are not filled
with a value and Submit Button is clicked, page will not be submitted to Server whereas when we fill values and click
on Submit Button then the page will be submitted to Server and displays message under the Label control.

When we implement data validations logic by using Java Script we will face a problem i.e., if Java Script is
disabled by client on his browser, then page will be submitted to server even when the validations fail and executes
the logic on server even if the logic is dependent on the validations. To test this disable Java Script on your browser
and test the page again so that now even if we did not fill the values in input controls and click on the Submit Button
will submit page to Server and displays the previous message in Label control.

Whereas the advantage with our Validation Controls is even if Java Script is disabled and page is submitted
to server, still validation controls will re-validate input controls on the server and sets the Validation Controls
“IsValid” property with a Boolean value which is true when the validation is success and false if the validation fails.
So we can implement logic under the server by checking the condition as following:

if (rfvName.IsValid && rfvCountry.IsValid) {


lblMsg.ForeColor = System.Drawing.Color.Green;
lblMsg.Text = "Hello user the name you have entered is: " + txtName.Text + " and your selected country is: " +
ddlCountries.SelectedItem.Text;
}
else {
lblMsg.ForeColor = System.Drawing.Color.Red;
lblMsg.Text = "Data validations failed.";
}

Note: the problem we face with above code is when we have multiple validations controls, checking each Validation
Controls “IsValid” value will become complicated and we can avoid this by using Page Classes “IsValid” property
because internally each validation control will first perform data validations and sets their “IsValid” property value
as true or false based on success or failure of the validations and finally sets the Page Class “IsValid” property as true
if all the Validation Controls “IsValid” value is true, whereas if any Validation Controls “IsValid” property is false then
Page Class “IsValid” property value also will be false. We can simplify the “if condition” in our previous code as
following:
if (rfvName.IsValid && rfvCountry.IsValid) => if (IsValid)

Currently validations are getting performed when we click on the Submit Button, whereas if we want the
validations to be performed when the focus is leaving the control add the following code in Page_Load Event Handler
of the if condition:

48
txtName.Attributes.Add("onblur", "ValidatorValidate(rfvName)");
ddlCountries.Attributes.Add("onblur", "ValidatorValidate(rfvCountry)");

The above statements will bind the “Validation Controls”, “Java Script” function to the controls “onblur”
event so that Event get fired when the focus is leaving the controls.

RangeValidator: this validation control is used to check whether the value entered into an input control is with-in a
specified range or not. This control is associated with these properties in specific:

1. MinimumValue: this is to specify the least value that can be entered into the input control being validated.
2. MaximumValue: this is to specify the highest value that can be entered into the input control being validated.
3. Type: this is to specify the Data Type for the values which are being compared and can be set with any of the
following values: String [d], Integer, Double, Date and Currency.

Note: none of the Validation Controls except RequiredFieldValidator can check for empty values, so while using
other Validation Controls if we want to perform an empty value check we need to use a RequiredFieldValidator
control also along with other validation controls. 1 validation control can be associated with 1 and only 1 input
control whereas 1 input control can be associated with any no. of validation controls.

Add a new Web Form in our project naming it as “Validations2.aspx” and design it as following:

Note: under the images folder of the project which we added earlier, add a calendar image for Image Button.

To design the above write the below code under <div> tag of the “Validations2.aspx” file:
<table align="center">
<caption>Journey Planner</caption>
<tr>
<td>Enter Name:</td>
<td><asp:TextBox ID="txtName" runat="server" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" /></td>
</tr>
<tr>
<td>Enter Age:</td>
<td><asp:TextBox ID="txtAge" runat="server" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" /><br />

49
<asp:RangeValidator ID="RangeValidator1" runat="server" /></td>
</tr>
<tr>
<td>Date of Journey:</td>
<td>
<asp:TextBox ID="txtDate" runat="server" />
<asp:ImageButton ID="imgDate" runat="server" ImageUrl="~/Images/Calendar.ico" Width="20"
Height="20" ImageAlign="AbsMiddle" />
<asp:Calendar ID="cldDate" runat="server" Visible="false" />
</td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" /><br />
<asp:RangeValidator ID="RangeValidator2" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center"><asp:Button ID="btnConfirm" runat="server" Text="Confirm Booking" /></td>
<td></td>
</tr>
<tr>
<td colspan="3"><asp:Label ID="lblMsg" runat="server" /></td>
</tr>
</table>

In design view select all 5 Validation Controls at a time, hit “F4” and set these 3 properties in property window:
Display: Dynamic ForeColor: Red SetFocusOnError: True

Now go to properties of each Validation Control and set the below properties:
RequiredFieldValidator1:
Id: rfvName ControlToValidate: txtName ErrorMessage: Name field can't be left empty.

RequiredFieldValidator2:
Id: rfvAge ControlToValidate: txtAge ErrorMessage: Age field can't be left empty.

RequiredFieldValidator3:
Id: rfvDate ControlToValidate: txtDate ErrorMessage: Journey date can't be left empty.

RangeValidator1:
Id: rvAge ControlToValidate: txtAge MinimumValue: 18 MaximumValue: 65
ErrorMessage: Traveler’s age should be between 18 - 65 years. Type: Integer

RangeValidator2:
Id: rvDate ControlToValidate: txtDate Type: Date
ErrorMessage: Travel date should be with-in 90 days from current date.

Now go to “Validations2.aspx.cs” file and write the following code:


Code under Page_Load:
rvDate.MinimumValue = DateTime.Now.ToShortDateString();
rvDate.MaximumValue = DateTime.Now.AddDays(90).ToShortDateString();

50
if(!IsPostBack) {
txtName.Focus();
}

Code under Image Button Click:


if(cldDate.Visible) {
cldDate.Visible = false;
}
else {
cldDate.Visible = true;
}

Code under Calendar Selection Changed:


txtDate.Text = cldDate.SelectedDate.ToShortDateString();
cldDate.Visible = false;

Code under Confirm Button Click:


if(IsValid) {
lblMsg.ForeColor = System.Drawing.Color.Green;
lblMsg.Text = "Your booking is confirmed.";
}
else {
lblMsg.ForeColor = System.Drawing.Color.Red;
lblMsg.Text = "Validations failed please re-check your data.";
}

Note: When we run the Web Form we face a problem i.e., when we click on the ImageButton to launch the Calendar
the ImageButton requires to perform a PostBack, but the Validation Control will not allow that to happen until all
the Validations are successful so to avoid that problem use ValidationGroup property of ImageButton and set it with
some value, for example: “DateGroup”, so that when we click on ImageButton it will validate only the controls which
comes under DateGroup and currently we don’t have any other control coming under this group.

CompareValidator: this control is used for performing 3 types of validations, those are:
1. Compare the value of an Input Control with another Input Control.
2. Compare the value of an Input Control with a given fixed value.
3. Data Type Check.

Properties specific to CompareValidator:


1. ControlToCompare: this property is to specify the Id of an Input Control with whom ControlToValidate has to be
compared.
2. ValueToCompare: this property is to specify a value with what ControlToValidate must be compared.
3. Operator: this property is to specify the type of comparison that must be performed, and it can be set with any
of the following values: Equal [d], NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual and
DataTypeCheck.
4. Type: this is to specify the Data Type for the values which are being compared and can be set with any of the
following values: String [d], Integer, Double, Date and Currency.

51
Add a new Web Form in our project naming it as “Validations3.aspx” and design it as following:

To design the above write the below code under <div> tag of the “Validations3.aspx” file:
<table align="center">
<caption>Registration Form</caption>
<tr>
<td>Enter Name:</td>
<td><asp:TextBox ID="txtName" runat="server" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" /></td>
</tr>
<tr>
<td>Enter Password</td>
<td><asp:TextBox ID="txtPwd" runat="server" TextMode="Password" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" /></td>
</tr>
<tr>
<td>Confirm Password:</td>
<td><asp:TextBox ID="txtCPwd" runat="server" TextMode="Password" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" /><br />
<asp:CompareValidator ID="CompareValidator1" runat="server" /></td>
</tr>
<tr>
<td>Date of Birth:</td>
<td>
<asp:TextBox ID="txtDate" runat="server" />
<asp:ImageButton ID="imgDate" runat="server" ImageUrl="~/Images/Calendar.ico" Width="20"
Height="20" ImageAlign="AbsMiddle" ValidationGroup="DateGroup" />
<asp:Calendar ID="cldDate" runat="server" Visible="false" />
</td>
<td>
<asp:CompareValidator ID="CompareValidator2" runat="server" /><br />
<asp:CompareValidator ID="CompareValidator3" runat="server" />
</td>
</tr>

52
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnRegister" runat="server" Text="Register" />
</td>
<td>&nbsp;</td>
</tr>
<tr>
<td colspan="3"><asp:Label ID="lblMsg" runat="server" /></td>
</tr>
</table>

Now select all the 6 Validation Controls at a time, hit “F4” and set the following properties in property window:
Display: Dynamic ForeColor: Red SetFocusOnError: True

Now go to properties of each Validation Control and set the following properties:
RequiredFieldValidator1:
Id: rfvName ControlToValidate: txtName ErrorMessage: Name field can't be left empty.

RequiredFieldValidator2:
Id: rfvPwd ControlToValidate: txtPwd ErrorMessage: Password field can't be left empty.

RequiredFieldValidator3:
Id: rfvCPwd ControlToValidate: txtCPwd ErrorMessage: Confirm password field can't be left empty.

CompareValidator1:
Id: cvCPwd ControlToValidate: txtCPwd ControlToCompare: txtPwd Type: String
ErrorMessage: Confirm password should match with password. Operator: Equal

CompareValidator2:
Id: cvDate1 ControlToValidate: txtDate Operator: DataTypeCheck
ErrorMessage: Entered value is not in a valid date format. Type: Date

CompareValidator3:
Id: cvDate2 ControlToValidate: txtDate Operator: LessThanEqual
ErrorMessage: You need to attain 18 years of age for registration. Type: Date

Now goto “Validations3.aspx.cs” file and write the following code:


Code under Page_Load:
if(!IsPostBack) {
txtName.Focus();
}
cvDate2.ValueToCompare = DateTime.Now.AddYears(-18).ToShortDateString();

Code under Image Button Click:


if (cldDate.Visible) {
cldDate.Visible = false;
}

53
else {
cldDate.Visible = true;
}

Code under Calendar Selection Changed:


txtDate.Text = cldDate.SelectedDate.ToShortDateString();
cldDate.Visible = false;

Code under Register Button Click:


if (IsValid) {
lblMsg.ForeColor = System.Drawing.Color.Green;
lblMsg.Text = "Your registration is successful.";
}
else {
lblMsg.ForeColor = System.Drawing.Color.Red;
lblMsg.Text = "Validations failed please re-check your data.";
}

RegularExpressionValidator: This control will validate input by using some special characters known as Regular
Expressions or Regex and these are some special characters using which we can perform data validations without
writing complex logic.

Understanding with Regular Expressions:


B => Braces => [] {} ()
C => Carrot => ^ => Represents start of an expression
D => Dollar => $ => Represents end of an expression

Braces:
[] => these are used to specify the characters which are allowed.
E.g: [a-m] or [A-K] or [0-6] or [A-Za-z0-9]
{} => these are used to specify the no. of characters that are allowed.
E.g: {1} or {4, 7} or {4,}
() => these are used to specify a list of options which are accepted.
E.g: (com|net|in|edu)
[A-K] => accepts 1 alphabet between A to K.
[a-m]{5} => accepts 5 lower-case alphabets between a to m.
[a-z]{3}[0-9]{5} => accepts 3 lower-case alphabets in the first followed by 5 numeric.

Note: in all the above 3 cases after the validating expression, it will accept anything we enter over there and to
overcome this problem we need to make the expressions rigid as following:
^[a-z]{3}[0-9]{5}$ => same as the last expression above but this is rigid expression i.e., accepts only 8 chars.

Special characters in regular expressions: there are some special characters with pre-defined logic.
\s => accepts whitespace
\S => doesn’t accept whitespace
\d => accepts only numeric values.

54
\D => accepts only non-numeric values.
\w => accepts only alpha-numeric values.
\W => accepts only non-alphanumeric values.

Validation Expressions using Regular Expressions:


\d{6} => Indian Postal Code
\d{3}-\d{7} => Indian Railway PNR
\d{4} \d{4} \d{4} => Aadhar Number
\d{4} \d{4} \d{4} \d{4} => Credit Card Number
http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)? => Website URL Validation.
\w+[\w-\.]*\@\w+((-\w+)|(\w*))\.[a-z]{2,3} => Email Validation
[6-9]\d{9} => Mobile No. validation that checks No. starts with 6 or 7 or
8 or 9 and will be maximum 10 and minimum 10 digits.
[0][6-9]\d{9} => Mobile No. validation that checks No. starts with 0 and
after that 6 or 7 or 8 or 9 and will be maximum 11 and
minimum 11 digits.
^[0][6-9]\d{9}$|^[6-9]\d{9}$ => Mobile No. validation which checks if the No. starts with 0
then it is 11 digit or else it is 10 digit.
^\d{6,8}$|^[6-9]\d{9}$ => Validation for either 6-8 digits landline no or 10 digit
Mobile No. that starts with 6 or 7 or 8 or 9.

Note: We can use Regular Expression in ASP.NET by using the RegularExpressionValidator control and specify the
Regular Expression under its “ValidationExpression” property.

Properties specific to RegularExpressionValidator:


1. ValidationExpression: by using this property we need to specify the “Validation Expression” for the validation,
either by choosing from a list of pre-defined expressions and this can be done by clicking on the button beside the
property which will launch “Regular Expression Editor” and it lists a set of pre-defined expressions for Email Id
Validation, Website URL Validation, etc or else default value will be Custom using which we can enter or specify our
own Validation Expression.

Add a new Web Form in our project naming it as “Validations4.aspx” and design it as following:

<table align="center">
<caption>Company Registration Form</caption>
<tr>
<td>Company Name:</td>

55
<td><asp:TextBox ID="txtName" runat="server" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" /></td>
</tr>
<tr>
<td>Contact No:</td>
<td><asp:TextBox ID="txtPhone" runat="server" /></td>
<td><asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" /></td>
</tr>
<tr>
<td>Email Id:</td>
<td><asp:TextBox ID="txtEmail" runat="server" /></td>
<td><asp:RegularExpressionValidator ID="RegularExpressionValidator2" runat="server" /></td>
</tr>
<tr>
<td>Website Url:</td>
<td><asp:TextBox ID="txtUrl" runat="server" /></td>
<td><asp:RegularExpressionValidator ID="RegularExpressionValidator3" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center"><asp:Button ID="btnRegister" runat="server" Text="Register" /></td>
<td>&nbsp;</td>
</tr>
<tr>
<td colspan="3"><asp:Label ID="lblMsg" runat="server" /></td>
</tr>
</table>

Now select all the 4 Validation Controls at a time, hit “F4” and set the following properties in property window:
Display: Dynamic ForeColor: Red SetFocusOnError: True

Now go to properties of each Validation Control and set the following properties:
RequiredFieldValidator1:
Id: rfvName ControlToValidate: txtName ErrorMessage: Comapany name field can't be left empty.

RegularExpressionValidator1:
Id: revPhone ControlToValidate: txtPhone ValidationExpression: ^\d{6,8}$|^[6-9]\d{9}$
ErrorMessage: Contact no. can either be Land Phone (6-8 digits) or Mobile (10 digits).

RegularExpressionValidator2:
Id: revEmail ControlToValidate: txtEmail ErrorMessage: Given input is an invalid Email Id format.
ValidationExpression: Click on the button beside and select “Internet e-mail Address” in Regular
Expression Editor.

RegularExpressionValidator3:
Id: revUrl ControlToValidate: txtUrl ErrorMessage: Given input is an invalid Website Url format.
ValidationExpression: Click on the button beside and select “Internet URL” in Regular Expression Editor.

56
Now go to aspx.cs file and write the following code:
Code under Page_Load:
if(!IsPostBack) {
txtName.Focus();
}

Code under Register Button Click:


if (IsValid) {
lblMsg.ForeColor = System.Drawing.Color.Green;
lblMsg.Text = "Your company registration is successful.";
}
else {
lblMsg.ForeColor = System.Drawing.Color.Red;
lblMsg.Text = "Your company registration failed because of validation errors.";
}

CustomValidator: this control doesn’t have any pre-defined logic to perform Data Validations i.e., we need to
implement all the logic on our own just like implementing manual Java Script code but the advantage with this is we
can implement logic to perform Client Side Validation by using Java Script code as well as we can also implement
logic to re-validate the data by using C# code on Server Side Validation, so that in case Java Script is disabled at
Client’s Browser still data gets validated on the Server.

Note: We don’t require (optional) setting “ControlToValidate” property for CustomValidator so this Validator is
capable of validating more than 1 Input Control also.

Member’s specifc to CustomValidator:


1. ClientValidationFunction: by using this property we need to specify the name of Java Script function in which we
have implemented logic for Client-Side Validation.
2. ServerValidate: this is an event under which we need implement the logic to perform Server Side Validation.

Add a new Web Form in our project naming it as “Validations5.aspx” and design it as following:

<table align="center">
<caption>Feedback Form</caption>
<tr>
<td>Name:</td>

57
<td><asp:TextBox ID="txtName" runat="server" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" /></td>
</tr>
<tr>
<td>Phone No:</td>
<td><asp:TextBox ID="txtPhone" runat="server" /></td>
<td rowspan="2"><asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" /><br />
<asp:CustomValidator ID="CustomValidator1" runat="server" /><br />
<asp:RegularExpressionValidator ID="RegularExpressionValidator2" runat="server" /></td>
</tr>
<tr>
<td>Email Id:</td>
<td><asp:TextBox ID="txtEmail" runat="server" /></td>
</tr>
<tr>
<td>Comments:</td>
<td><asp:TextBox ID="txtComments" runat="server" Rows="3" TextMode="MultiLine" /></td>
<td><asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" /><br />
<asp:CustomValidator ID="CustomValidator2" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center"><asp:Button ID="btnSubmit" runat="server" Text="Submit" /></td>
<td>&nbsp;</td>
</tr>
<tr>
<td colspan="3"><asp:Label ID="lblMsg" runat="server" /></td>
</tr>
</table>

Now select all the 6 Validation Controls at a time, hit “F4” and set the following properties in property window:
Display: Dynamic ForeColor: Red SetFocusOnError: True

Now go to properties of each Validation Control and set the following properties:
RequiredFieldValidator1:
Id: rfvName ControlToValidate: txtName ErrorMessage: Name field can't be left empty.

RequiredFieldValidator2:
Id: rfvComments ControlToValidate: txtComments ErrorMessage: Comments field can't be left empty.

RegularExpressionValidator1:
Id: revPhone ControlToValidate: txtPhone ValidationExpression: ^\d{8}$|^[6-9]\d{9}$
ErrorMessage: Phone no. can either be landline (8 digits) or mobile (10 digits).

RegularExpressionValidator2:
Id: revEmail ControlToValidate: txtEmail ErrorMessage: Given input is an invalid Email Id format.
ValidationExpression: Click on the button beside and select “Internet e-mail Address" in Regular
Expression Editor.

58
CustomValidator1:
Id: cvPhoneOrEmail ErrorMessage: Either Phone No. or Email Id must be provided.
ClientValidationFunction: PhoneOrEmail

Now go to events of CustomValidator1 and double click on “ServerValidate” which will generate an Event
Handler (cvPhoneOrEmail_ServerValidate) for implementing server-side validation code.

CustomValidator2:
Id: cvComments ControlToValidate: txtComments ClientValidationFunction: Check50Chars
ErrorMessage: Comments should be minimum 50 chars of length.
Now go to events of CustomValidator2 and double click on “ServerValidate” which will generate an Event
Handler (cvComments_ServerValidate) for implementing server-side validation code.

Now go to “Source View” and write the below code inside of <head> section:
<script>
function PhoneOrEmail(source, args) {
if (txtPhone.value.trim().length == 0 && txtEmail.value.trim().length == 0) {
args.IsValid = false;
}
else {
args.IsValid = true;
}
}
function Check50Chars(source, args) {
if (args.Value.trim().length < 50) {
args.IsValid = false;
}
else {
args.IsValid = true;
}
}
</script>

Now go to “aspx.cs” file and write the following code:


Code under Page_Load:
if(!IsPostBack) {
txtName.Focus();
}

Code under cvPhoneOrEmail_ServerValidate:


if (txtPhone.Text.Trim().Length == 0 && txtEmail.Text.Trim().Length == 0) {
args.IsValid = false;
}
else {
args.IsValid = true;
}

59
Code under cvComments_ServerValidate:
if (args.Value.Trim().Length < 50) {
args.IsValid = false;
}
else {
args.IsValid = true;
}

Code under Submit Button Click:


if (IsValid) {
lblMsg.ForeColor = System.Drawing.Color.Green;
lblMsg.Text = "Your feedback is received, we will contact you asap.";
}
else {
lblMsg.ForeColor = System.Drawing.Color.Red;
lblMsg.Text = "Your feedback has errors and not been taken.";
}

ValidationSummary: this control doesn’t perform any Data Validations but used only for displaying Error Messages
i.e., without displaying Error Messages beside the Input Controls we can display all the Error Messages at one
location either on top of the Page or bottom of the Page. When we place this Control on a Page it will automatically
inherit the Error Messages that are associated with all Validation Controls that are present on that Page. To test
workings with ValidationSummary Control in our current page i.e., “Validations5.aspx”, go to design view and, drag
and drop the ValidationSummary Control just below the table and set the ForeColor property value as “Red”.

Now run the Web Form and watch the output i.e., if any Validations fail all those Error Messages will be
displayed by the ValidationSummary Control in the place where we placed it because this Control will inherit all the
Error Messages of the 6 Validation Controls present on the page. But in this case, we also see the Error Messages
beside the Input Controls and to avoid them set the Text Property of Validation Controls so that Text value will be
displayed beside Input Controls and Error Messages will be displayed by the ValidationSummary control and to test
this go to the properties of all 6 Validation Controls on the Page and under the Text enter the value as “*”. Now run
and watch the difference in output which will display “*” beside the Input Control where the validation failed, and
all the Error Messages will be displayed by ValidationSummary control.

Properties specific to ValidationSummary Control:


1. ShowSummary: this is a Boolean property with the default value true and if set as false will not display the
ErrorMessage on Screen.

2. ShowMessageBox: this is a Boolean property with the default value false and if set as true will display the Error
Messages in MessageBox.

3. ShowValidationErrors: this is a Boolean property with the default value as true and if set as false Error Messages
will not be displayed either on the Screen or in a Message Box.

4. DisplayMode: this property is to specify the format how Error Messages must be displayed, and we can choose
from any of the below 3 values: BulletedList [d], List and SingleParagraph.

60
Master Pages
One attribute of a well-designed Web Site is a consistent site-wide page layout. Take the www.nareshit.com
website for example; every page has the same content at the top and bottom of the page. At the very top of each
page displays a light gray bar with a list of locations where the branches are located. Beneath that are the company
logo, and the core sections: Home, All Courses, Software Training, Services, and so forth. Likewise, the bottom of the
page includes information about clients, Address, contact details, quick links etc.

Another attribute of a well-designed site is the ease with which the site's appearance can be changed. For
instance, the look and feel can be changed in the future, perhaps the menu items along the top will expand to include
a new section or may be a radically new design with different colors, fonts, and layout will be unveiled. Applying
such changes to the entire site should be a fast and simple process that does not require modifying the thousands
of web pages that make up the site.

Creating a site-wide page template in ASP.NET is possible using Master Pages. In a nutshell, a Master Page
is a special type of ASP.NET page that defines the markup that is common among all Content Pages (a Content Page
is an ASP.NET page that is bound to the Master Page). Whenever a Master Page's layout or formatting is changed,
all its Content Pages output is immediately updated, which makes applying site-wide appearance and changes as
easy by updating and deploying a single file i.e., Master Page.

Understanding How Master Pages Work: Building a website with a consistent site-wide page layout requires that
each web page emit common formatting markup for example, while each page on www.nareshit.com have their
own unique content, each of these pages also render a series of common <div> elements that display the top-level
section links: Home, All Courses, Software Training, Services, and so on.

There are a variety of techniques for creating web pages with a consistent look and feel. A naive approach
is to simply copy and paste the common layout markup into all web pages, but this approach has several downsides.
For starters, every time a new page is created, you must remember to copy and paste the shared content into the
page. Such copying and pasting operations are ripe for error as you may accidentally copy only a subset of the shared
markup into a new page.

The shortcomings were cited in ASP.NET version 2.0 and Visual Studio 2005 with the introduction of master
pages. A master page is a special type of ASP.NET page that defines the site-wide markup and the regions where
associated content pages can define their custom markup and those regions are defined by “ContentPlaceHolder”
controls. The “ContentPlaceHolder” control simply denotes a position in the master page's control hierarchy where
custom content can be injected by a content page.

Below figure shows how a master page might look like. Note that the master page defines the common
site-wide layout - the markup at the top, bottom, and right of every page - as well as a “ContentPlaceHolder” in the
middle-left where the unique content of each individual web page must come and sit.

61
Once a master page has been defined it can be bound to a new ASP.NET page and those ASP.NET pages
(content pages), include a Content control for each of the master page's ContentPlaceHolder controls. When the
content page is visited through a browser the ASP.NET engine creates the master page's control hierarchy and injects
the content page's control hierarchy into the appropriate places and the combined control hierarchy is rendered
and the resulting HTML is returned to the end user's browser. Below figure illustrates this concept:

Creating a Master Page: To add a Master Page in our site, open the “Add New Item” window and select the option
“Web Forms Master Page” and name it as “Site.master” (.master is the extension of a Master Page). The first line in
the declarative markup is the @Master directive and this is like the @Page directive that appears in our Web Pages
and all other attributes will be same as @Page directive attributes only.

Initially the code in Master Page will be as below:


<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="ControlsDemo.Site" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"></asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>

Now if we look into the code of the file we find a “ContentPlaceHolder” control named “head” and this
control appears within the <head> section and can be used to declaratively add content in to the <head> element
like style and script code. We also find another “ContentPlaceHolder” control named “ContentPlaceHolder1” and
this control appears within the Web Form and serves as the region for the content pages - user interface. Delete
code which is present inside of <form> tag along with the “ContentPlaceHeader” and write the below code in it:

<div id="divHeader" style="background-color: lightpink; color: aqua; text-align: center; font-size: xx-large">
Naresh I Technologies
</div>

62
<div id="divMenu" style="background-color: beige; text-align: center">
<asp:HyperLink ID="hlHome" runat="server" NavigateUrl="~/Home.aspx" Text="Home" />&nbsp;
<asp:HyperLink ID="hlMission" runat="server" NavigateUrl="~/Mission.aspx" Text="Mission" />&nbsp;
<asp:HyperLink ID="hlAbout" runat="server" NavigateUrl="~/About.aspx" Text="About" />
</div>

<div id="divContent">
<asp:ContentPlaceHolder ID="body" runat="server" />
</div>

<div id="divFooter" style="background-color: azure">


<fieldset style="border: dotted blue; color: brown">
<legend>Contact Us</legend>
Address: Opp. Satyam Theatre, Ameerpet, Hyderabad – 16 <br />
Phone: 2374 6666 <br />
Email: [email protected] <br />
Website: www.nareshitc.om </fieldset>
</div>

Creating Content Pages: with the above master page created, we are now ready to start creating ASP.NET Web
Pages that are bound to the Master Page. Such Pages are referred to as Content Pages and we need to create 3
Content Pages now with the name: Home.aspx, Mission.aspx and About.aspx.

Add a new ASP.NET Web Form to the project and bind it to “Site.master” Master Page and to do that open
“Add New Item” window, select the “Web Form with Master Page” template, enter the name as “Home.aspx” and
click “Add”, which opens “Select a Master Page” dialog box from where you can choose the Master Page to use. This
action will add a Content Page which contains Page Directive that points to its Master Page and also we find
“Content” controls binding to Master Page’s “ContentPlaceHolder” controls. Currently we have 2
“ContentPlaceHolder” controls on Master Page, so we find 2 “Content” controls on this page and the code will be as
following in “Home.aspx”:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"


CodeBehind="Home.aspx.cs" Inherits="ControlsDemo.Home" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server"></asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" runat="server"></asp:Content>

Note: Title attribute is to set a title for our page, give a value to title as “Home Page” and then write the following
code under the 2 “Content” controls:

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">


<style>
p{
text-align: justify; color: palevioletred; font-family: Arial; text-indent: 50px;
}
ol {
color: cadetblue; background-color: burlywood
}

63
</style>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="body" runat="server">


<div style="background-color: aqua; color: coral;font-family:'Arial Unicode MS';font-size:larger;font-weight: bold">
Home Page
</div>
<p>We have set the pace with online learning. Learn what you want, when you want, and practice with the
instructor-led training sessions, on-demand video tutorials which you can watch and listen. </p>
<ol>
<li>150+ Online Courses</li>
<li>UNLIMITED ACCESS</li>
<li>EXPERT TRAINERS</li>
<li>VARIETY OF INSTRUCTION</li>
<li>ON-THE-GO-LEARNING</li>
<li>PASSIONATE TEAM</li>
<li>TRAINING INSTITUTE OF CHOICE</li>
</ol>
</asp:Content>

Same as the above add 2 more Content Pages naming them as “Mission.aspx” and “About.aspx”, set the
title as “Mission Page” for “Mission.aspx” and “About Page” for “About.aspx”, and write below code under them:

Mission.aspx:
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<style>
p{
text-align: justify; color: blue; font-family: Calibri; text-indent: 50px;
}
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" runat="server">
<div style="background-color: aqua; color: coral;font-family:'Arial Unicode MS';font-size:larger;font-weight: bold">
Our Mission
</div>
<p>We appreciate you taking the time today to visit our web site. Our goal is to give you an interactive tour of our
new and used inventory, as well as allow you to conveniently get a quote, schedule a service appointment, or apply
for financing. The search for a luxury car is filled with high expectations. Undoubtedly, that has a lot to do with the
vehicles you are considering, but at Motors, we think you should also have pretty high expectations for your
dealership. </p>
</asp:Content>

About.aspx:
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<style>
p{
text-align: justify; color: green; font-family: 'Agency FB'; text-transform: capitalize; text-indent: 50px;

64
}
</style>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="body" runat="server">


<div style="background-color: aqua; color: coral;font-family:'Arial Unicode MS';font-size:larger;font-weight: bold">
About Us
</div>
<p>NareshIT (Naresh i Technologies) is a leading Software Training Institute and provides Job Guarantee Program
through Nacre in Hyderabad, Chennai, Bangalore, Vijayawada and across the world with Online Training services.
Managed and Lead by IT Professionals with more than a decade experience in leading MNC companies. We are most
popular for our training approach that enables students to gain real-time exposure on cutting-edge technologies.
</p>
</asp:Content>

Now run any of the above 3 Content Pages and we notice that they merge with Master Page we have
created above and launches, click on any menu in the top will launch other pages in the site.

ViewState
Web applications are stateless i.e., these applications do not persist (save) the data of 1 request, for using
it in the next request. When an application is stateless, the server does not store any state about the client session.
To test this, add a new Web Form naming it as “HitCount.aspx” and write the following code in its <div> tag:

<asp:Button ID="btnCount" runat="server" Text="Hit Count"/>


<br/>
<asp:Label ID="lblCount" runat="server" ForeColor="Red"/>

Now goto “HitCount.aspx.cs” file and write the following code in it:
Declarations:
int Count = 0;

Code under Hit Count Button Click:


Count += 1;
lblCount.Text = "Hit Count: " + Count;

Now run the Web Form and click on the button for any no. of times still it will display the output as 1 only
because every time we click on the button, server will create the instance of our page class, initializes “Count” with
“0”, increments the value of Count to “1” in click of the Button, sends the output to client machine and destroys the
page instance, and this process repeats every time we click on the button so every time the value of Count is “1”
only and this is called as “Stateless” behavior. To overcome the above problem, we use ViewState which is a
technique used to store user data on page at the time of post back of a web page.

Syntax of storing a value into ViewState:


ViewState[string name] = value (Object);

Syntax of accessing a value from ViewState:


Object value = ViewState[string name];

65
To resolve the problem in our previous page, rewrite the code under click of the button as following:
if (ViewState["Counter"] == null) {
Count = 1;
}
else {
Count = (int)ViewState["Counter"] + 1;
}
ViewState["Counter"] = Count;
lblCount.Text = "Hit Count: " + Count;

Note: Same as the above every ASP.NET Server Control will also maintain the state of its values and we call it as
ControlState which will hold the values of controls and restores the value to control after page Postback.

Where does Web Application store ViewState Values?


Ans: Web Applications, store ViewState values on the same page only i.e., while rendering the output of a page it
writes ViewState values into that rendered output and sends them to the browser, so we can view those values using
“View Page Source” option of the browser and there we find a “Hidden Field” with the name “__ViewState” that
contains ViewState values stored in “Base64 Encrypted String” format. Next time when the page is submitted to the
Server all the ViewState values are carried to the Server and there Server will read and decrypt those values.

Drawbacks of ViewState:
1. ViewState values are transported between Browser and Server every time we perform a Post Back, so in case if
we store huge volumes of data in ViewState then transporting all that data between Browser and Server will
increase the network traffic.
2. ViewState values are accessible only with the same page i.e., we can’t access the ViewState values of 1 page in
another page.

Processing of a Web Page by the Web Server

When the request comes from a client for the first time to a page, ASPNET_ISAPI.dll on the Web Server will
take the request, creates a new class “ASP.hitcount_aspx” inheriting from the class “HitCount” which is defined on
“HitCount.aspx.cs” and “HitCount.aspx.designer.cs” files, compiles the new class and loads the compiled code into
memory and starts the life cycle of page, and if at all the request comes for the second time (Post Back) for the page
which is already compiled and loaded into memory, without recompiling the page again, the compiled code in the
memory will be used for starting the life cycle of page.

66
Page Life Cycle: Life cycle of a page describes how a Web Page gets processed on the server i.e., when browser sends
a request for that page.

Page Request: The page request occurs before the page life cycle begins, i.e., when the page is requested by a user,
server determines whether the page needs to be parsed and executed (therefore beginning the life cycle of a page)
or whether a cached version of the page can be sent in response without processing the page.

Various stages in the life cycle of a page will be as following:


Stage1: Start => in this stage the page properties such as request and response are created and set, and at this stage
the page also determines whether the request is a post back or a new request (get) and sets the IsPostBack property,
which will be true if it’s a Post Back request or else false if it’s a first or get request.

Stage2: Initialization => during this stage all the controls on the page will be created and each controls Unique Id
property will be set.

Stage3: Load => in this stage if the current request is a post back, control properties are loaded with information
retrieved from View State (Control State).

Stage4: Validation => in this stage any server-side validations that are required will be performed and sets the IsValid
property of individual validator controls and then of the page.

Stage5: Event Handling => if the request is a post back, then all the controls corresponding event handlers are called
(which is required only) along with any Cached Events also. In the First request to page only Page Events will fire
whereas in a Postback request, Page Events and Control Events (which is required) will fire.

Stage6: Rendering => in this stage the page is rendered i.e., converts into HTML and before rendering view state and
control state is saved for the page and all controls.

Note: during the rendering stage, page calls the RenderControl method on each control and writes its output to the
Output Stream object of Page’s Response property.

Stage7: UnLoad: => after the page has been rendered and the output is sent to client, it’s ready to discard and
Unload event is raised, and at this stage the Request and Response properties are destroyed, and cleanup is
performed.

Page Events: Within each stage of page life cycle, page raises certain events which can be used for performing certain
actions and this is the list of Page Life Cycle - Events that we will use most frequently.
1. PreInit
2. Init
3. InitComplete
4. PreLoad
5. Load
-Control Events (All Postback and Cached Events)
6. LoadComplete
7. PreRender
8. PreRenderComplete

67
9. SaveStateComplete
-RenderControl Method Calling
10. UnLoad

1. PreInit: Raises after the start stage is completed and before the initialization stage begins. We use this event for
performing the following actions:
I. Check the IsPostBack property to determine whether this is the first-time page is being processed.
II. Setting a Master Page dynamically.

2. Init: Raises after all controls have been initialized and any skin settings have been applied. The Init event of
individual controls occurs before the Init event of page. Use this event to read or initialize control properties.

3. InitComplete: Raised at the end of page's initialization stage. Only one operation takes place between Init and
InitComplete events i.e., tracking of view state is turned on. View state tracking enables controls to persist any values
that are programmatically added to the ViewState collection. Until view state tracking is turned on, any values added
to view state are lost across post backs. Controls typically turn on view state tracking immediately after they raise
their Init event. Use this event to make any changes to view state that we want to make sure are persisted after the
next post back.

4. PreLoad: Raised after the page, loads view state for itself and all controls, and after it starts processing post back
data that is included with the Request object.

5. Load: Page object calls the OnLoad method on Page, and then recursively does the same for each child control
until all controls are loaded. The Load event of individual controls occurs after the Load event of page. Use this event
to get or set properties of controls and to establish database connections.

Control events: use these events to handle specific control events such as a Button control’s Click event or a TextBox
control’s TextChanged event. In a post back request, if the page contains validation controls, check the IsValid
property of Page before performing any processing.

6. LoadComplete: Raised at the end of event-handling stage and use this event for performing any tasks that require
for all the controls on page that have been loaded.

7. PreRender: Raises after Page object has created all controls that are required to render the page, including child
controls of Custom Controls. Page object raises this PreRender event on itself and then recursively does the same
for each child control. Use this event to make any final changes to contents of page or its controls because hereafter
rendering stage begins.

8. PreRenderComplete: Raises after all controls on page are ready for render.

9. SaveStateComplete: Raises after View State and Control State have been saved for page and for all controls. Any
changes to the page or controls at this point that affects rendering will not be retrieved on the next post back.

Render: This is not an event but a method and at this stage of processing, Page calls this method on each control.
All ASP.NET Web Server Controls has a RenderControl method which writes the control’s markup to “Output Stream”
that must be sent to the browser as output.

68
10. Unload: Raised for each control and then for page. Use this event to do any final cleanup such as closing control-
specific database connections.

Note: During unload stage - page and its controls rendering is completed, so you cannot make any further changes
to the response stream and if you attempt to call a method such as “Response.Write” will throw an exception.

To test and understand about Page Events add a new Web Form under the project naming it as
“PageEvents.aspx”, place a button on it and set the Text as “Post Back”. Now go to “aspx.cs” file, copy the method
“Page_Load” present in the class and paste it for 9 more times in the same class and rename the 9 methods as
following: “Page_PreInit”, “Page_Init”, “Page_InitComplete”, “Page_PreLoad”, “Page_LoadComplete”,
“Page_PreRender”, “Page_PreRenderComplete”, “Page_SaveStateComplete” and “Page_Unload”, and write a
statement in each method describing about the event as following:

Code under Page_PreInit: Response.Write("Pre-Init Event Fired. <br />");


Code under Page_Init: Response.Write("Init Event Fired. <br />");
Code under Page_InitComplete: Response.Write("InitComplete Event Fired. <br />");
Code under Page_PreLoad: Response.Write("PreLoad Event Fired. <br />");
Code under Page_Load: Response.Write("Load Event Fired. <br />");
Code under Page_LoadComplete: Response.Write("LoadComplete Event Fired. <br />");
Code under Page_PreRender: Response.Write("PreRender Event Fired. <br />");
Code under Page_PreRenderComplete: Response.Write("PreRenderComplete Event Fired. <br />");
Code under Page_SaveStateComplete: Response.Write("SaveStateComplete Event Fired. <br />");
Code under Page_Unload: //Response.Write("Unload Event Fired. <br />");

Now generate a Click Event Handler for Button and write the following code in it:
Response.Write("<font color='red'>");
Response.Write("Button Click Event Fired. <br />");
Response.Write("</font>");

Now run the Web Form and watch the output, we notice all the events getting fired in a sequence, now
click on the button to perform a Postback which will also fire Click Event along with all the other Events whereas
click event will fire after the Load Event and before the LoadComplete event.

Series of actions that are performed between the first request and postback request of a page:

69
AutoEventWireup attribute of Page Directive: ASP.NET supports an automatic way to bind Page Events to its Event
Handlers if the AutoEventWireup attribute of the Page directive is set to true (default is also true only), provided
Event Handler names follow a naming convention i.e., “Page_<Event Name>” for example “Page_Load”, whereas if
we set the attribute value as false or we don’t follow the naming convention then Event Handlers should be explicitly
bound to their corresponding events under Constructor of the page as following:

public PageEvents()
{
this.PreInit += Page_PreInit;
this.Init += Page_Init;
this.InitComplete += Page_InitComplete;
this.PreLoad += Page_PreLoad;
this.Load += Page_Load;
this.LoadComplete += Page_LoadComplete;
this.PreRender += Page_PreRender;
this.PreRenderComplete += Page_PreRenderComplete;
this.SaveStateComplete += Page_SaveStateComplete;
this.Unload += Page_Unload;
}

Data Source Communication with ADO.NET


Note: To test the examples in this document first download the file “Northwind.sql” to create Northwind Database
from “Google Class Room” and run the SQL (Script) file and to do that double click on the “Northwind.sql” file which
will prompt for Credentials to open under “Sql Server Management Studio”. After it got opened execute the code
which will create the Northwind Database on our SQL Server.

Add a Web Form in our project naming it as “Northwind_Customers_Select.aspx”, and write the below
code under the “<div>” tag:
<asp:Label ID="lblTable" runat="server" />

Now go to “Northwind_Customers_Select.aspx.cs” file and write the below code:

using System.Text;
using System.Data.SqlClient;
Code under Page Load Event:
//Write the below code if you are using SQL Server Authentication:
SqlConnection con = new SqlConnection("Data Source=Server;User Id=Sa;Password=123;Database=Northwind");

//Write the below code if you are using Windows Authentication:


SqlConnection con = new SqlConnection("Data Source=Server;Integrated Security=SSPI;Database=Northwind");

SqlCommand cmd = new SqlCommand("Select CustomerID, CompanyName, ContactName, City, Region,


PostalCode, Country, Phone From Customers", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();

70
StringBuilder sb = new StringBuilder();

sb.Append("<table border='1' align='center'>");


sb.Append("<caption>Customer Details</caption>");

//Building the header row:


sb.Append("<tr>");
for (int i = 0; i < dr.FieldCount; i++) {
sb.Append("<th>" + dr.GetName(i) + "</th>");
}
sb.Append("</tr>");

//Building the data rows:


while (dr.Read()) {
sb.Append("<tr>");
for (int i = 0; i < dr.FieldCount; i++) {
sb.Append("<td>" + dr.GetValue(i) + "</td>");
}
sb.Append("</tr>");
}

sb.Append("</table>");
con.Close();
lblTable.Text = sb.ToString();

Loading multiple tables into DataReader: it is possible to load more than 1 table into a DataReader, by passing
multiple Select Statements as CommandText to Command separated by a semicolon. We need to use the NextResult
method of DataReader class to navigate the next tables after processing a table.

To test this add a new Web Form in the project naming it as “Northwind_MultipleTables.aspx”, and write
the below code under the “<div>” tag:
<asp:GridView ID="gvCustomers" runat="server" Caption="Customer Details" HorizontalAlign="Center" />
<hr />
<asp:GridView ID="gvEmployees" runat="server" Caption="Employee Details" HorizontalAlign="Center" />

Note: GridView is a control which is used for displaying data in a table format without manually creating a table as
we have done in our first example.

Now go to “Northwind_MultipleTables.aspx.cs” file and write the below code:

using System.Data.SqlClient;
Code under Page Load Event:
SqlConnection con = new SqlConnection("Data Source=Server;User Id=Sa;Password=123;Database=Northwind");
SqlCommand cmd = new SqlCommand("Select CustomerId, ContactName, City, Country, Phone From Customers;
Select EmployeeId, LastName, FirstName, BirthDate, HireDate From Employees", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();

71
gvCustomers.DataSource = dr;
gvCustomers.DataBind();
dr.NextResult();
gvEmployees.DataSource = dr;
gvEmployees.DataBind();
con.Close();

Storing Connection Strings in Web.config file: in our previous examples whenever we are connecting to a Data
Source we are writing “Connection String”. Writing this “Connection String” each and every time will have an affect
on the size of the application and moreover if any changes occur in the future to “Connection String”, then we need
to modify that in each and every Web Form, which will be a complex task again. To overcome the above problems,
without writing “Connection String” in each and every Web Form we can put that “Connection String” in
“Web.config” file, so that we don’t require to write that in multiple Web Forms and also when there is a change we
can modify it directly in “Web.config” file.

To store “Connection String” in the “Web.config” file we use “<connectionStrings>” tag and to test it open
“Web.config” file and write the following code under “<configuration>” tag:

<connectionStrings>
<add name="NorthwindDBCS" providerName="System.Data.SqlClient"
connectionString="User Id=Sa;Password=123;Data Source=Server;Database=Northwind" />
</connectionStrings>

Reading values from Web.config file into our application: to read values from Web.config file in a Web Form we
need to take the help of ConfigurationManager class which is present in “System.Configuration” namespace, and we
need to read the values as below:

string ConStr = ConfigurationManager.ConnectionStrings["NorthwindDBCS"].ConnectionString;

From now without writing Connection String’s again and again in our Web Forms, we can read them from
Web.config file by using the above statement and consume it wherever it is required as below:

SqlConnection con = new SqlConnection(ConStr);

To simply the process of reading Connection String values into our Web Form i.e., without writing lengthy
code every time, add a new class into our Project naming it as “ReadCS.cs” and write the below code under the class:

using System.Configuration;
public class ReadCS {
public static string Northwind {
get { return ConfigurationManager.ConnectionStrings["NorthwindCS"].ConnectionString; }
}
}

Now in all our Web Forms we can read the Connection String directly by calling the property we have
defined as following:
SqlConnection con = new SqlConnection(ReadCS.Northwind);

72
GridView Control
This Control is designed to display the data on a Web Form in table structure and also this Control has
various features like Paging, Sorting, Customizing, Editing, etc.

Paging with GridView: this is a mechanism of displaying data on a Web Form as Block of Records, generally used
when we have huge volumes of data. To perform paging with a GridView Control first we need to set AllowPaging
property as “true (default is false)” and then we need to specify the no. of records that has to be displayed within
each page by setting PageSize Property with a numeric value (default is 10).

PagerSettings is a property of GridView using which we need to specify the type of paging the Control has to use
with the help of “Mode” attribute and this can be set as “NextPrevious or Numeric [d] or NextPreviousFirstLast or
NumericFirstLast”. Here we can also specify the position where “Navigation Buttons” should be displayed and also
the “Text or Image” values for Next, Previous, First and Last buttons.

PageIndexChanging is an event under which we need to implement the logic for navigating to next pages by setting
the “PageIndex” property, which is “0” by default. To identify the Index of page where user wants to navigate in
runtime, we can use “NewPageIndex” attribute of “PageIndexChanging” event.

To test paging, add a new Web Form naming it as “Northwind_Customers_GridView_Paging.aspx”, place a


GridView Control on it, set the AllowPaging property value as true and write the below code in “aspx.cs” file:

using System.Data;
using System.Data.SqlClient;
Declarations:
DataSet ds;
Code under Page Load Event:
if (Session["CustomersDS"] == null) {
SqlDataAdapter da = new SqlDataAdapter("Select CustomerID, CompanyName, ContactName, City, Country,
PostalCode, Phone From Customers", ReadCS.Northwind);
ds = new DataSet();
da.Fill(ds, "Customers");
Session["CustomerDS"] = ds;
LoadData();
}
else {
ds = (DataSet)Session["CustomerDS"];
}
private void LoadData() {
GridView1.DataSource = ds;
GridView1.DataBind();
}
Code under GridView PageIndexChanging Event:
GridView1.PageIndex = e.NewPageIndex;
LoadData();
Note: session’s are used to store & retrieve values of a user across all the pages of site i.e., it is “Single User Global
Data”. Session is also an intrinsic object and it is of type “HttpSessionState”, and can be used for State Management
just like ViewState.

73
Sorting with GridView: this is a mechanism of arranging data on a Web Form in ascending or descending order based
on any particular column of a table. To perform “Sorting” with “GridView” Control, first we need to set AllowSorting
property as “true (default is false)” so that “Column Names” in GridView looks like “Hyper Links” providing an option
to click on them.

Sorting is an event under which we need to implement the logic that is required for sorting the data based on
Selected Column which can be identified in our code by using SortExpession property of the Sorting event and this
event fires when the column names (Hyper Links) are clicked by the user in runtime.

To test sorting with GridView add a new Web Form naming it as


“Northwind_Employees_GridView_Sorting.aspx”, place a GridView control on it, set the “AllowSorting” property
as true and write the below code in “aspx.cs” file:

using System.Data;
using System.Data.SqlClient;
Declarations:
DataSet ds;
Code under Page Load Event:
if (Session["EmployeesDS"] == null) {
SqlDataAdapter da = new SqlDataAdapter("Select EmployeeId, LastName, FirstName, Title, BirthDate, City,
Country, PostalCode, HomePhone From Employees Order By EmployeeId Asc", ReadCS.Northwind);
ds = new DataSet(); da.Fill(ds, "Employees");
Session["EmployeesDS"] = ds;
GridView1.DataSource = ds;
GridView1.DataBind();
Session["SortOrder"] = "EmployeeId Asc";
}
else {
ds = (DataSet)Session["EmployeesDS"];
}
Code under GridView Sorting Event:
string[] sarr = Session["SortOrder"].ToString().Split(' ');
if(sarr[0] == e.SortExpression) {
if (sarr[1] == "Asc") {
Session["SortOrder"] = e.SortExpression + " Desc";
}
else {
Session["SortOrder"] = e.SortExpression + " Asc";
}
}
else
Session["SortOrder"] = e.SortExpression + " Asc";
DataView dv = ds.Tables["Employees"].DefaultView;
dv.Sort = Session["SortOrder"].ToString();
GridView1.DataSource = dv;
GridView1.DataBind();

74
Customizing a GridView: generally, when we bind a “Data Source” to “GridView” Control it will automatically display
all the columns that are being retrieved by us, because GridView control has a mechanism of “auto-generating”
columns and display the data as a HTML Table., so that “Column Names” will be displayed as “Header Text” and
“Column Values” will be displayed in the body. We can customize a GridView so that we can display different “Header
Text” apart from “Column Names”, define styles for “Header Text”, “Item Text” as well as we can also use different
type of controls for displaying data and even, we can perform “Editing” of the data, but to do these all first we need
to set “AutoGenerateColumns” property of the control as “false (default is true)”. Once we set
“AutoGenerateColumns” property value as “false”, it is our responsibility to add each and every column individually
to the GridView control with the help of some special fields like:

 BoundField: Displays the value of a column in a Data Source. This is the default column type of the GridView
control.
 ButtonField: Displays a command button for each item in the GridView control. This enables you to create a
column of custom button controls, such as the Add or the Remove button.
 CheckBoxField: Displays a check box for each item in the GridView control. This column field type is commonly
used to display fields with a Boolean value.
 CommandField: Displays pre-defined command buttons to perform Select, Edit, or Delete operations.
 HyperLinkField: Displays the value of a field in a Data Source as a hyperlink. This column field type enables you
to bind a second field to the hyperlink's URL.
 ImageField: Displays an image for each item in the GridView control.
 TemplateField: Displays user-defined content for each item in the GridView control, according to a specified
template. This column field type enables you to create a custom column field.

To test these, first create a new Database in SQL Server naming it as “ASPDB” and under the Database
create a new Table naming it as Customer, and insert few records into it using the below script code:

Create Table Customer (Custid Int Primary Key, Name Varchar(50), Balance Money, City Varchar(50), Status Bit
Default 1 Not Null);
Go
Insert Into Customer Values (101, 'Teja', 22000.00, 'Chennai', 1)
Insert Into Customer Values (102, 'Raju', 50000.00, 'Hyderabad', 1)
Insert Into Customer Values (103, 'Vijay', 40000.00, 'Vijayawada', 1)
Insert Into Customer Values (104, 'Suresh', 30000.00, 'Bengaluru', 1)
Insert Into Customer Values (105, 'Naidu', 35000.00, 'Visakhapatnam', 1)
Go

Open Web.config file and add another Connection String below “NorthwindDBCS” Connection String as below:
<add name="ASPDBCS" connectionString="Data Source=Server;Database=ASPDB;User Id=Sa;Password=123" />

Open ReadCS.cs file and add another Property below “Northwind” Property as below:
public static string ASPDB {
get {
return ConfigurationManager.ConnectionStrings["ASPDBCS"].ConnectionString;
}
}
Add a new Web Form, naming it as “ASPDB_Customer_GridView_Customize.aspx” and write the below
code under its <div> tag:

75
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" HorizontalAlign="Center" >
<HeaderStyle BackColor="LightYellow" ForeColor="PaleVioletRed" />
<RowStyle BackColor="Tan" ForeColor="Teal" />
<AlternatingRowStyle BackColor="Teal" ForeColor="Tan" />
<Columns>
<asp:BoundField DataField="Custid" HeaderText="Cust-ID" ItemStyle-HorizontalAlign="Center" />
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="Balance" HeaderText="Balance" ItemStyle-HorizontalAlign="Right" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:CheckBoxField DataField="Status" HeaderText="Is-Active" ItemStyle-HorizontalAlign="Center" />
Or
<asp:TemplateField HeaderText="Is-Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:RadioButton ID="rbStatus" runat="server" Enabled="false" Checked='<%# Eval("Status") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

Now go to “ASPDB_Customer_GridView_Customize.aspx.cs” file and write the below code:


using System.Data.SqlClient;
Code under Page Load Event:
SqlConnection con = new SqlConnection(ReadCS.ASPDB);
SqlCommand cmd = new SqlCommand(
"Select Custid, Name, Balance, City, Status From Customer Order By Custid", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
GridView1.DataSource = dr;
GridView1.DataBind();
con.Close();

Data editing with GridView: we can edit data that is present in “GridView Control” and update those changes back
to the corresponding table in Database. To perform editing of the data, first “GridView Control” requires an “Edit”
& “Delete” button, and to generate these buttons we have 3 options:

1. Set the properties AutoGenerateDeleteButton and AutoGenerateEditButton as true.


2. Add Edit & Delete options using “CommandField”, by manually generating the columns as following:
<asp:CommandField ShowEditButton="true" ShowDeleteButton="true" />
3. Manual generation of those buttons by using Template Field.

To perform editing operations, we need to write logic under 4 events of the GridView those are: RowEditing,
RowCancelingEdit, RowUpdating and RowDeleting.
 RowEditing: Occurs when a row's Edit button is clicked which changes Edit button to Update and Cancel buttons
and here, we need to set the GridViews - EditIndex to selected rows Index.
 RowCancelingEdit: Occurs when the Cancel button of a row in edit mode is clicked which changes back to Edit
button and Delete button, we need to set the GridViews - EditIndex to -1.

76
 RowUpdating: Occurs when a row's Update button is clicked and here, we need to implement the logic for
updating the row and finally set the GridViews - EditIndex to -1.
 RowDeleting: Occurs when a row's Delete button is clicked and here, we need to implement the logic for
deleting the row.

Now to test editing with GridView, add a new Web Form in the project naming it as
“ASPDB_Customer_GridView_Editing.aspx” and write the following code under its <div> tag:

<asp:GridView ID="GridView1" runat="server" HorizontalAlign="Center" AutoGenerateColumns="False">


<HeaderStyle BackColor="Yellow" ForeColor="Red" />
<RowStyle BackColor="Tan" ForeColor="Teal" />
<AlternatingRowStyle BackColor="Teal" ForeColor="Tan" />
<Columns>
<asp:BoundField HeaderText="Custid" DataField="Custid" ItemStyle-HorizontalAlign="Center" ReadOnly="true"
ItemStyle-Width="100" />
<asp:BoundField HeaderText="Name" DataField="Name" ItemStyle-Width="100" />
<asp:BoundField HeaderText="City" DataField="City" ItemStyle-Width="100" />
<asp:BoundField HeaderText="Balance" DataField="Balance" ItemStyle-HorizontalAlign="Right"
ItemStyle-Width="100" />
<asp:CheckBoxField HeaderText="Status" DataField="Status" ItemStyle-HorizontalAlign="Center"
ReadOnly="true" ItemStyle-Width="100" />
<asp:TemplateField HeaderText="Actions" ItemStyle-HorizontalAlign="Center" ItemStyle-BackColor="White"
ItemStyle-ForeColor="Blue" ItemStyle-Width="100">
<ItemTemplate>
<asp:LinkButton ID="btnEdit" runat="server" Text="Edit" CommandName="Edit" />
<asp:LinkButton ID="btnDelete" runat="server" Text="Remove" CommandName="Delete"
OnClientClick="return confirm('Are you sure of deleting the record?');" />
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="btnUpdate" runat="server" Text="Update" CommandName="Update" />
<asp:LinkButton ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<table border="1" align="center">
<tr style="background-color: aqua">
<td style="width: 90px"><asp:TextBox ID="txtCustid" runat="server" Width="90" /></td>
<td style="width: 90px"><asp:TextBox ID="txtName" runat="server" Width="90" /></td>
<td style="width: 90px"><asp:TextBox ID="txtCity" runat="server" Width="90" /></td>
<td style="width: 90px"><asp:TextBox ID="txtBalance" runat="server" Width="90" /></td>
<td style="width: 90px"><asp:CheckBox ID="cbStatus" runat="server" Width="90" Checked="false" /></td>
<td style="width: 100px; background-color: white" align="center">
<asp:LinkButton ID="btnInsert" runat="server" Text="Insert" /></td>
</tr>
</table>

77
Now go to design view of the Web Form, select “GridView”, open the Property Window, go to it Events,
double click on “RowEditing”, “RowCancelingEdit”, “RowUpdating” and “RowDeleting” events to generate Event
Handlers for implementing the logic and write the below code in “ASPDB_Customer_GridView_Editing.aspx.cs”:

using System.Data;
using System.Data.SqlClient;
Declarations:
SqlCommand cmd;
SqlConnection con;
Code under Page Load Event Handler:
con = new SqlConnection(ReadCS.ASPDB);
cmd = new SqlCommand();
cmd.Connection = con;
if (!IsPostBack) {
LoadData();
}
private void LoadData()
{
cmd.CommandText = "Select Custid,Name,Balance,City,Status From Customer Where Status=1 Order By Custid";
if (con.State != ConnectionState.Open) {
con.Open();
}
SqlDataReader dr = cmd.ExecuteReader();
GridView1.DataSource = dr;
GridView1.DataBind();
con.Close();
}
Code under GridView RowEditing Event Handler:
GridView1.EditIndex = e.NewEditIndex;
LoadData();
Code under GridView RowCancelingEdit Event Handler:
GridView1.EditIndex = -1;
LoadData();
Code under GridView RowUpdating Event Handler:
try {
int Custid = int.Parse(GridView1.Rows[e.RowIndex].Cells[0].Text);
string Name = ((TextBox)GridView1.Rows[e.RowIndex].Cells[1].Controls[0]).Text;
decimal Balance = decimal.Parse(((TextBox)GridView1.Rows[e.RowIndex].Cells[2].Controls[0]).Text);
string City = ((TextBox)GridView1.Rows[e.RowIndex].Cells[3].Controls[0]).Text;

cmd.CommandText =
$"Update Customer Set Name='{Name}', Balance={Balance}, City='{City}' Where Custid={Custid}";
con.Open();
if (cmd.ExecuteNonQuery() > 0) {
GridView1.EditIndex = -1;

78
LoadData();
}
}
catch (Exception ex) {
Response.Write("<script>alert('" + ex.Message.Replace("'", "") + "')</script>");
}
finally {
con.Close();
}
Code under GridView RowDeleting Event Handler:
try {
int Custid = int.Parse(GridView1.Rows[e.RowIndex].Cells[0].Text);
cmd.CommandText = $"Update Customer Set Status=0 Where Custid={Custid}";
con.Open();
if (cmd.ExecuteNonQuery() > 0) {
LoadData();
}
}
catch (Exception ex) {
Response.Write("<script>alert('" + ex.Message.Replace("'", "") + "')</script>");
}
finally {
con.Close();
}
Code under Insert Button Click Event Handler:
try {
int Custid = int.Parse(txtCustid.Text);
string Name = txtName.Text;
string City = txtCity.Text;
decimal Balance = decimal.Parse(txtBalance.Text);
int Status = Convert.ToInt32(cbStatus.Checked);
cmd.CommandText = $"Insert Into Customer (Custid, Name, City, Balance, Status) Values({Custid}, '{Name}',
'{City}', {Balance}, {Status})";
con.Open();
if(cmd.ExecuteNonQuery() > 0) {
LoadData();
cbStatus.Checked = false;
txtCustid.Text = txtName.Text = txtCity.Text = txtBalance.Text = "";
}
}
catch(Exception ex) {
Response.Write("<script>alert('" + ex.Message.Replace("'", "") + "')</script>");
}
finally {
con.Close();
}

79
Design Patterns
Design patterns represent the best practices used by experienced object-oriented software developers.
Design patterns are solutions to general problems that software developers faced during software development.
These solutions were obtained by trial and error by numerous software developers over quite a substantial period.

Design patterns have been evolved over a long period of time and they provide best solutions to certain
problems faced during software development. Learning these patterns helps un-experienced developers to learn
software design in an easy and faster way. Design patterns are solutions to software design problems you find again
and again in real-world application development.

What is Gang of Four (GOF)?


In 1994, four authors Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides published a book titled
“Design Patterns - Elements of Reusable Object-Oriented Software” which initiated the concept of Design Pattern in
software development. These authors are collectively known as Gang of Four (GOF). The book is divided into 2 parts,
first part explaining about the “Pros and Cons” of Object-Oriented Programming and in the second, explaining the
evolution of 23 Software Design Patterns.

Types of Design Patterns:


As per the design pattern reference book “Design Patterns - Elements of Reusable Object-Oriented
Software”, there are 23 design patterns which can be classified in to three categories: Creational, Structural and
Behavioral patterns.

Creational Patterns: These design patterns provide a way to create objects while hiding the creation logic, rather
than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects
need to be created for a given use case.

Structural Patterns: These design patterns concern class and object composition. Concept of inheritance is used to
compose interfaces and define ways to compose objects to obtain new functionalities.

Behavioral Patterns: These design patterns are specifically concerned with communication between objects.

Creational Patterns:
 Abstract Factory Creates an instance of several families of classes.
 Builder Separates object construction from its representation.
 Factory Method Creates an instance of several derived classes.
 Prototype A fully initialized instance to be copied or cloned.
 Singleton A class of which only a single instance can exist.

Structural Patterns:
 Adapter Match interfaces of different classes.
 Bridge Separates an object’s interface from its implementation.
 Composite A tree structure of simple and composite objects.
 Decorator Add responsibilities to objects dynamically.
 Facade A single class that represents an entire subsystem.
 Flyweight A fine-grained instance used for efficient sharing.
 Proxy An object representing another object.

80
Behavioral Patterns:
 Chain of Responsibility A way of passing a request between a chain of objects
 Command Encapsulate a command request as an object.
 Interpreter A way to include language elements in a program.
 Iterator Sequentially accessing the elements of a collection.
 Mediator Defines simplified communication between classes.
 Memento Capture and restore an object's internal state.
 Observer A way of notifying change to several classes
 State Alter an object's behavior when its state changes.
 Strategy Encapsulates an algorithm inside a class.
 Template Method Defer the exact steps of an algorithm to a subclass.
 Visitor Defines a new operation to a class without change.

Architectural Patterns
An architectural pattern is a general, reusable solution to a commonly occurring problem in software
architecture within a given context. These are like software design pattern only but have a broader scope.

Software application architecture is the process of defining a structured solution that meets all the technical
and operational requirements, while optimizing common quality attributes such as performance, security, and
manageability.

It involves a series of decisions based on a wide range of factors, and each of these decisions can have
considerable impact on the quality, performance, maintainability, and overall success of the application. The
architectural patterns address various issues in software engineering, such as computer hardware performance
limitations, high availability and minimization of a business risk and cost.

List of Architectural Patterns:


 Blackboard system
 Broker pattern
 Event - driven architecture
 Implicit invocation
 Layers
 Microservices
 Model - View - Controller (MVC)
 Presentation - abstraction - control
 Model - View - Presenter (MVP)
 Model - View - View Model (MVVM)
 Entity - component - system
 Multitier architecture (often called as 3-tier or n-tier)
 Naked objects
 Operational data store (ODS)
 Peer - to - peer
 Pipe and filter architecture
 Service - oriented architecture
 Space - based architecture

81
What is MVC?
Ans: The Model-View-Controller (MVC) is an architectural pattern which separates an application into three main
components: Models, Views, and Controllers. This pattern helps to achieve separation of concerns. Using this
pattern, user requests are routed to a Controller which is responsible for working with the Model to perform user
actions by retrieving results of queries. The Controller chooses the View to display to user and provides it with any
Model data it requires. The below diagram shows the three main components and which ones reference to others:

MODEL: The Model in an MVC Application represents the state of the application and any Data Logic or operations
that should be performed by it. Data logic should be encapsulated in the model, along with any implementation logic
for persisting the state of the application.

VIEW: Views are responsible for presenting content through the user interface. There should be minimal logic within
views, and any logic in them should relate to presenting content.

Controller: Controllers are the components that handle user interaction, work with the model, and ultimately select
a view to render. In an MVC Application, the view only displays information; the controller handles and responds to
user input and interaction. In the MVC Pattern, the controller is the initial entry point, and is responsible for selecting
which model types to work with and which view to render (hence its name - it controls how the application responds
to a given request).

History of MVC: MVC traditionally used for Desktop Graphical User Interfaces (GUIs) and later this architecture has
become popular for designing Web Applications and even Mobile and other Clients. Popular programming languages
like Java, .NET, Ruby, PHP, Python, Java Script, and others have their own MVC Frameworks that are currently being
used in Web Application development.
Language MVC Framework
Java Spring, Structs
PHP Cake PHP, Code Igniter, Zend Framework, Laravel
Perl Catalyst, Dancer
Python Django, Flask, Grok
Ruby Ruby on Rails, Nitro
Java Script Angular, Spine
.NET ASP.NET MVC, ASP.NET Core MVC
Trygve Reenskaug introduced MVC into Smalltalk-76 while working at Xerox Palo Alto Research Center in
the 70’s. In the 1980’s, Jim Althoff and others implemented a version of MVC for the Smalltalk-80 class library.
Although originally developed for desktop computing, MVC has been widely adopted as architecture for Web
Applications in major programming languages. Several MVC Web Frameworks have been designed that enforce the
MVC patterns that are listed above.

MVC pattern has subsequently evolved giving rise to variants such as hierarchical model -view - controller
(HMVC), model - view - adapter (MVA), model - view - presenter (MVP), model - view - view model (MVVM), and
others that adapted MVC for different contexts.

82
ASP.NET MVC: this edition of MVC works only on .NET Framework.
Date Version
December 2007 ASP.NET MVC CTP
March 2009 ASP.NET MVC 1.0
March 2010 ASP.NET MVC 2
January 2011 ASP.NET MVC 3
August 2012 ASP.NET MVC 4
October 2013 ASP.NET MVC 5
January 2014 ASP.NET MVC 5.1
July 2014 ASP.NET MVC 5.2.0
August 2014 ASP.NET MVC 5.2.2
February 2015 ASP.NET MVC 5.2.3
February 2018 ASP.NET MVC 5.2.4
May 2018 ASP.NET MVC 5.2.5
May 2018 ASP.NET MVC 5.2.6
November 2018 ASP.NET MVC 5.2.7
April 2022 ASP.NET MVC 5.2.8
June 2022 ASP.NET MVC 5.2.9

ASP.NET Core MVC Versions: this edition of MVC is designed to work on .NET Core (Windows, Linux & Mac OS)
Date Version
August 2016 ASP.NET Core MVC 1.0
November 2016 ASP.NET Core MVC 1.1
August 2017 ASP.NET Core MVC 2.0
May 2018 ASP.NET Core MVC 2.1
December 2018 ASP.NET Core MVC 2.2
September 2019 ASP.NET Core MVC 3.0
December 2019 ASP.NET Core MVC 3.1
November 2020 ASP.NET Core MVC 5.0
November 2021 ASP.NET Core MVC 6.0
November 2022 ASP.NET Core MVC 7.0
November 2023 ASP.NET Core MVC 8.0
November 2024 ASP.NET Core MVC 9.0

Note: There is no separate versioning for ASP.NET Core. It is the same as .NET Core Versions.

83
ASP.NET MVC 5
Developing an ASP.NET MVC 5 Application: This is the last version of MVC from .NET Framework and the next
version is first named as MVC 6 but later changed to ASP.NET Core MVC and ported to .NET Core. So, first let’s learn
working with ASP.NET MVC 5.

Creating an MVC Project and to do this, open Visual Studio 2022 => Click on “Create a new project” on RHS
of the window, now in the new window opened, under “All Languages” Dropdown select “C#”, under “All Platforms”
Dropdown select “Windows”, under “All Project Types” Dropdown select “Web”, now in the below list select
“ASP.NET Web Application (.NET Framework)” and click on “Next” button, now in the new Window opened, under
“Project Name” TextBox enter “MVCTestProject1” as name of our project, under “Location” TextBox enter
“<drive>:\ASP”, under “Framework” Dropdown List, choose the latest version of “.NET Framework” i.e., “.NET
Framework 4.8.1” and click on “Create” button which will launch a new Window with the name “Create a new
ASP.NET Web Application” and under this select the following options: choose “Empty Project Template”, in the RHS
select “MVC” CheckBox under “Add folders & core references”, uncheck all the other Checkbox’s over there and
click on the “Create” button which will create the project.

Note: Same as the above create another new project naming the project as “MVCTestProject2”, but now under
“Create a new ASP.NET Web Application” Choose “MVC Project Template”, uncheck all the other Checkbox’s over
there and click on the “Create” button to create the project.

MVC Project Structure: when we create a new project either by choosing “Empty Project Template and select MVC
CheckBox” or “MVC Project Template”, a set of files and folders are added in the project as following:

1. Connected Services: This is used for integrating Microsoft Azure Service into Visual Studio, so that we can easily
host and manage our application to Azure Portal from Visual Studio it-self.

2. App_Data: this folder contains local Data Source files like “.mdf” files, “.xml” files, “Excel” files, etc.

3. App_Start: this folder contains a set of files which contains classes, and these classes get executed when the
application starts execution. App_Start folder can contain following files in it:
1. BundleConfig.cs => Contains BundleConfig Class
2. FilterConfig.cs => Contains FilterConfig Class
3. IdentityConfig.cs => Contains IdentityConfig Class
4. RouteConfig.cs => Contains RouteConfig Class
5. Startup.Auth.cs => Contains Startup Class

Note: if we opened an “Empty Project Template” then “App_Start” folder contains only “RouteConfig.cs” file,
whereas if we opened an “MVC Project Template” then “App_Start” folder contains “BundleConfig.cs”,
“FilterConfig.cs” and “RouteConfig.cs” files.

4. Content: this folder contains static files like “.css” files, “image” files, etc.

Note: if we open an “Empty Project Template” then Content folder will not be existing whereas if we open an “MVC
Project Template” then this folder exists with a set of “.css” (Bootstrap) files in it.

5. Controllers: this folder contains Controller classes where each Controller should be defined in a separate file.

84
Note: if we open an “Empty Project Template” then Controllers folder is empty, whereas if we open an “MVC Project
Template” then this folder will contain 1 default Controller with the name “HomeController” under the file
“HomeController.cs”.

6. Models: this folder contains Model classes i.e., classes representing the Entities and Properties representing the
Attributes of Entities as well as all the Methods to manipulate the data.

Note: if we open an “Empty Project Template” or “MVC Project Template” also this folder will exist but will be empty.

7. Scripts: this folder contains Java Script or jQuery files that are used for development of the application.

Note: if we open an “Empty Project Template” then Scripts folder will not exist, whereas if we open an “MVC Project
Template” then this folder will exist with a set of “.js” (jQuery, jQuery Validations, etc) files in it.

8. Views: this folder contains all the View files (UI) that are required for this application and the extension of these
files will be “.cshtml” in case we are working with “C#” Language or else if we are working with “VB” Language then
extension of the files will be “.vbhtml” and these files contains both “C# / VB” and Html code in them.

Note: if we open an “Empty Project Template” then Views folder comes with a file in it i.e., “web.config”, whereas
if we open an “MVC Project Template” then this folder will contain 2 sub folder in it with the names “Home” and
“Shared” and these folders will contain a set of “.cshtml” files, and apart from that “Views” folder also contain
“_ViewStart.cshtml” and “web.config” files.

Under the Views folder, for every Controller it will create a folder to store all the Views that are associated
with that Controller, for example if there is a Controller with the name “HomeController” then there will be a “Home”
folder created under Views folder to store all the Views associated with the “HomeController” class.

Under the Views folder, we can also have Shared folder containing all the Views that are common for all
the Controllers in the application, for example Layout View, Error View, etc.

9. Global.asax: this is a file that contains a Global Configuration class, and, in this class, we define a set of methods:
“Application_Start”, “Application_End”, “Application_Error” that executes for application-level actions and other
methods like: “Session_Start” and “Session_End” that executes for session level actions.

10. Packages.config: this contains information of packages that are used under this project, so that anyone can easily
understand if there are any 3rd party packages consumed for the development of this application.

11. Web.config: this is a configuration file for the whole application which contains configuration settings like “App
Settings”, “Connection Strings”, “Network Settings”, “Compiler Settings”, etc.

Controller
It is a class that handles user requests i.e., this class is responsible for taking all the incoming requests for
an MVC Application. The parent class for all Controllers we define should be the class “Controller” which is in turn a
child of class “ControllerBase” and both the classes are defined in “System.Web.Mvc” namespace.

85
Note: Every Controller class should suffix the word “Controller” to it, for example if we want to define a controller
with the name “Home” then it should be named as “HomeController” and this is only a convention but not a rule.

To test working with Controllers, create a new ASP.Net Web Application Project, naming it as
“MVCTestProject3”, select Empty Project Template, check the MVC CheckBox, un-check all the other Checkbox’s and
click on the Create button.

Adding a Controller to our MVC Project: We can add a Controller to an MVC Project in 2 different ways:
1. Manually defining Controller class.
2. Using scaffolding to define Controller class.

Option 1: Manually defining a Controller class: open Solution Explorer => right click on the Controllers folder =>
select Add => New Item or Class => now in the “Add New Item” window select Class, name it as “TestController.cs”
and click on the “Add” button. Now in the class do the following:

Step 1: Import the namespace “System.Web.Mvc”.

Step 2: Inherit our TestController class with Controller class which should now look as below:
public class TestController : Controller

Note: Every Controller class contains methods in it known as Action methods and there should be minimum 1 Action
method in a Controller class.

Step 3: Let’s define 2 action methods in the class as below:


public string Index()
{
return "Hello from Test Controller - Index Action Method.";
}
public string Show()
{
return "Hello from Test Controller - Show Action Method.";
}

Step 4: Press F5 to run the project, which will launch the Browser and by default it displays “http://localhost:port”
in the address bar, add “/Test/Index” to it, to run the Index Action method or “/Test/Show” to it, to run Show Action
method, which should look as below:
http://localhost:port/Test/Index
http://localhost:port/Test/Show

In the above URL => “Test” is the name of Controller class, and “Index or Show” are names of the Action
methods we want to invoke.

Hosting a Web Application in IIS from Visual Studio: by default Visual Studio runs our project using IIS Express Web
Server and if we want to run under Local IIS, re-open Visual Studio in Administrator Mode and re-load our project,
then go to Solution Explorer, right click on the Project and select Properties which will open the “Project Property
Window”. In the LHS select Web and then in the RHS we find the option “Servers” and in that we will find a
DropDownList showing the value “IIS Express” selected, change the selection to “Local IIS” in the DropDownList

86
which will change the “Project URL” in the TextBox below and now the value will be:
http://localhost/MVCTestProject3 and beside the TextBox we will find a Button with the caption “Create Virtual
Directory” click on it which will host or deploy the application in IIS, click on the Save button in “Standard Tool Bar”
and close “Project Property Window”.

Now hit F5 to run the project which will display http://localhost/MVCTestProject3 in the address bar add,
“/Test/Index” to it, to run the Index Action method or “/Test/Show” to run Show Action method, which should now
look as below:
http://localhost/MVCTestProject3/Test/Index
http://localhost/MVCTestProject3/Test/Show

Default Action Method and Default Controller in an MVC Application:


We can even execute the Index Action Method using the below URL also:
IIS Express: http://localhost:port/Test
Local IIS: http://localhost/MVCTestProject3/Test

Note: in the above case even if Action method name is not specified in the URL still it will launch “Index” Action
method because the default Action method for all controllers is Index. Same as that the default Controller for MVC
App., is “HomeController” and to test that add a new class in the Project naming it as “HomeController” and write
the below code under the class by importing “System.Web.MVC” namespace and inherit the class from Controller:

public string Index()


{
return "Hello from Home Controller - Index Action Method.";
}
public string Show()
{
return "Hello from Home Controller - Show Action Method.";
}

Now when we run the project it will execute the Home Controller’s - Index Action method and the URL in
the address bar will be as below:

IIS Express: http://localhost:port


Local IIS: http://localhost/MVCTestProject3

The below URL’s when used will give you the following results:
IIS Express:
http://localhost:port //Invokes Home Controller’s Index
http://localhost:port/Home //Invokes Home Controller’s Index
http://localhost:port/Home/Index //Invokes Home Controller’s Index
http://localhost:port/Home/Show //Invokes Home Controller’s Show

http://localhost:port/Test //Invokes Test Controller’s Index


http://localhost:port/Test/Index //Invokes Test Controller’s Index
http://localhost:port/Test/Show //Invokes Test Controller’s Show

87
Local IIS:
http://localhost/MVCTestProject3 //Invokes Home Controller’s Index
http://localhost/MVCTestProject3/Home //Invokes Home Controller’s Index
http://localhost/MVCTestProject3/Home/Index //Invokes Home Controller’s Index
http://localhost/MVCTestProject3/Home/Show //Invokes Home Controller’s Show

http://localhost/MVCTestProject3/Test //Invokes Test Controller’s Index


http://localhost/MVCTestProject3/Test/Index //Invokes Test Controller’s Index
http://localhost/MVCTestProject3/Test/Show //Invokes Test Controller’s Show

Option 2: Using Scaffolding to define Controller class.


ASP.NET Scaffolding is a code generation framework for ASP.NET Web Applications. From Visual Studio
2013 Microsoft included code generators for MVC and Web API Projects. We use this scaffolding in our project when
we want to quickly add code that interacts with Data Models. Using scaffolding will reduce the amount of time to
develop standard operations in our project.

To add a controller using scaffolding open Solution Explorer => right click on Controllers folder => select
Add => Controller => now in the “Add New Scaffolded Item” window select “MVC 5 Controller – Empty” template
and click on the “Add” button which will then open a window asking for a name, enter the name as “DemoController”
and click on “Add” button which adds the Controller class as below:

public class DemoController : Controller


{
// GET: Demo
public ActionResult Index()
{
return View();
}
}
When we use Scaffolding to add a Controller, by default the class will inherit from “Controller” class and
this will also import “System.Web.Mvc” namespace. Now delete all the existing code in class and write the below
code over there:

public string Index()


{
return "Hello from Demo Controller - Index Action Method.";
}
public string Show()
{
return "Hello from Demo Controller - Show Action Method.";
}

IIS Express:
http://localhost:port/Demo //Invokes Demo Controller's Index
http://localhost:port/Demo/Index //Invokes Demo Controller's Index
http://localhost:port/Demo/Show //Invokes Demo Controller's Show

88
Local IIS:
http://localhost/MVCTestProject3/Demo //Invokes Demo Controller's Index
http://localhost/MVCTestProject3/Demo/Index //Invokes Demo Controller's Index
http://localhost/MVCTestProject3/Demo/Show //Invokes Demo Controller's Show

Where is the information of default controller “Home” and default action method “Index” were specified?
Ans: Those details are present in “RouteConfig.cs” file, which is present in “App_Start” folder. To verify that open
“RouteConfig.cs” file and there we find a class with the name “RouteConfig” and code in the class will be as below:

public class RouteConfig


{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}

What is Routing?
Ans: Routing enables you to use URL’s that do not have to map to specific files in a Web Site. Because URL does not
have to map to a file, you can use URL’s that are descriptive of the user’s action and therefore easily understood by
the users. In ASP.NET Web Forms application that does not use routing, an incoming request for a URL typically maps
to a physical file that handles the request, such as an “.aspx” file. For example, a request for /Products.aspx?id=4
maps to a file that is named “Products.aspx” that contains the code and markup for rendering a response to the
browser. The Web Page uses a query string value “id=4” to determine what type of content to display.

By using routing, we can define URL patterns that map to request-handler, but that do not necessarily
include the names of those files in URL. In addition, we can also include placeholders in a URL Pattern so that variable
data can be passed to the request-handler without requiring a query string. For example, in this URL:
/Products/Show/4, routing parser can pass the values Products, Show, and 4 to the request-handler if the route is
defined by using the URL pattern “{controller}/{action}/{id}”. The request-handler would receive a dictionary
collection in which the value associated with the key-controller is Products, the value for the key-action is Show, and
the value for the key-id is 4. In a request that is not managed by URL routing, the “/Products/Show/4” fragments
would be interpreted as the path of a file in the application.

Routes: A route is a URL Pattern that is mapped to a request-handler. A request-handler can be a class that processes
the request, such as a Controller in an MVC Application. To define a route, you create an instance of the Route class
by specifying the URL Pattern, the defaults, and optionally a name for the route. You add the route to the application
by adding the Route object to the static Routes property of the RouteTable class. The routes property is a
RouteCollection object that stores all the routes for the application.

We typically do not have to write code to add routes in an MVC application. Visual Studio project templates
for MVC include pre-configured URL Routes. These are defined in RouteConfig class, which is defined in

89
“RouteConfig.cs” file and then registered in “Application_Start” method of “MVCApplication” class defined under
“Global.asax” file by calling “RouteConfig.RegisterRoutes”.

URL Patterns: This can contain literal values and variable placeholders (referred to as URL Parameter’s). The literals
and placeholders are in segments of the URL which are delimited by the slash (/) character. When a request is made,
the URL is parsed into segments and placeholders, and the variable values are provided to the request-handler. This
process is like the way the data in query strings is parsed and passed to the request-handler. In both cases variable
information is included in the URL and passed to the request-handler in the form of “key-value” pairs. For query
strings both the keys and the values are in the URL. For routes, keys are the placeholder names defined in the URL
Pattern, and only the values are in URL.

In an URL Pattern, you define placeholders by enclosing them under curly braces {}. You can define more
than one placeholder in a segment, but they must be separated by a literal value. For example, {language}-
{country}/{action} is a valid route pattern. However, {language}{country}/{action} is not a valid pattern, because
there is no literal value or delimiter between the placeholders. Therefore, routing cannot determine where to
separate the value for language placeholder from the value for the country placeholder.

Can we define multiple routes in RouteConfig class?


Ans: Yes, we can define multiple routes in the RouteConfig class, so that MVC Framework evaluates each route in
sequence. It starts with the first configured route, and if the incoming URL doesn’t satisfy the URL Pattern of the
route, then it will evaluate the second route and so on.

To understand this open “RouteConfig.cs” file and add the below code above “default” route:
routes.MapRoute(
name: "Student",
url: "NIT/Students",
defaults: new { controller = "Student", action = "Index" }
);
Now we have added a new route with the name Students, so MVC Framework will first evaluate this route
to check if the incoming request satisfy the URL pattern or not, and if not satisfied then it will go to default route
which is existing.

Now add a new Controller in the Controllers folder using “Scaffolding”, name it as “StudentController” and
re-write the existing Index action method in the class as below:

public string Index()


{
return "Hello from Student Controller - Index Action method.";
}

URL to access the above action method should be as following:


IIS Express: http://localhost:port/NIT/Students
Local IIS: http://localhost/MVCTestProject3/NIT/Students

Note: while defining multiple routes it’s better to define the default route in last otherwise all incoming requests
will be handled by default route only and to understand that change the sequence of the routes we defined in
RouteConfig class and try to access the Student Controller with the above URL will give you “Not Found – 404” error.

90
Passing parameters to Controller’s Action methods: we can define parameters to Action methods, and values to
those parameters can be sent in different ways like Route Parameters, Query Strings and Input Controls.

Using Route Parameters: by default, we can pass 1 parameter to any action method i.e., “id” because it was defined
in “default route” under the class “RouteConfig” and to check that, open “RouteConfig.cs” file and watch the value
of “URL” which will be as following:
url: "{controller}/{action}/{id}"

Note: by default, this “id” is optional, and we can find that under “defaults” in the next line.
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

If required we can send this “id” value to the action method and that value can be used inside the action
method and to use it, Action method should have “id” as parameter.

To test this, let’s add a new controller under our current project i.e., “MVCTestProject3” with the name
“ParamsController”, delete the existing Index action method and write the below methods under the class:

//Passing value to id is mandatory


public string Index1(int id) {
return "The value of id is: " + id;
}
//Passing value to id is optional and if not passed value will be "0"
public string Index2(int id = 0) {
return "The value of id is: " + id;
}
//Passing value to id is optional and if not passed value will be "null"
public string Index3(int? id) {
return "The value of id is: " + id;
}

Execute the above methods as following:


IIS Express:
http://localhost:port/Params/Index1 //Invalid
http://localhost:port/Params/Index1/100 //Valid
http://localhost:port/Params/Index2 //Valid, but value of id is 0
http://localhost:port/Params/Index2/200 //Valid
http://localhost:port/Params/Index3 //Valid, but value of id is null
http://localhost:port/Params/Index3/300 //Valid

Local IIS:
http://localhost/MVCTestProject3/Params/Index1 //Invalid
http://localhost/MVCTestProject3/Params/Index1/100 //Valid
http://localhost/MVCTestProject3/Params/Index2 //Valid, but value of id is 0
http://localhost/MVCTestProject3/Params/Index2/200 //Valid
http://localhost/MVCTestProject3/Params/Index3 //Valid, but value of id is null
http://localhost/MVCTestProject3/Params/Index3/300 //Valid

91
Note: the parameter name in all the 3 Index action methods should be “id” only (not case sensitive and can be of
any type) because it is the same name we have in “RouteConfig.cs” file, so we can’t change it in our action methods
and if we try to use a different name to the parameter other than “id” then the value we passed thru the route will
not be taken by the action method and to test that define 2 new action methods in the “ParamsController” class as
below:

//Passing value to x is mandatory and if passed also it will not take it because of parameter name mis-match
public string Index4(int x) {
return "The value of id is: " + x;
}
//Passing value to x is optional and if passed also it will not take it because of parameter name mis-match
public string Index5(int? x) {
return "The value of id is: " + x;
}

Execute the above methods as following:


IIS Express:
http://localhost:port/Params/Index4 //Invalid because there is no value for x
http://localhost:port/Params/Index4/400 //Invalid because the value is not taken to x
http://localhost:port/Params/Index5 //Valid and the value for x is null
http://localhost:port/Params/Index5/500 //Valid, but now also the value for x is null only

Local IIS:
http://localhost/MVCTestProject3/Params/Index4 //Invalid because there is no value for x
http://localhost/MVCTestProject3/Params/Index4/400 //Invalid because the value is not taken to x
http://localhost/MVCTestProject3/Params/Index5 //Valid and the value for x is null
http://localhost/MVCTestProject3/Params/Index5/500 //Valid, but now also the value for x is null only

The name “Id” which is defined in “RouteConfig” under the default route is not specified to be of a particular
type so while using it in our action method we can specify any type to it and to test that define a new action method
in the “ParamsController” class as following:

//Passing value to Id is option because it is defined as type string & strings are by default Nullable (reference types)
public string Index6(string Id) {
return "The value of id is: " + Id;
}

Execute the above method as following:


IIS Express:
http://localhost:port/Params/Index6 //Valid and value of Id is null
http://localhost:port/Params/Index6/Hello //Valid and value of Id is Hello
http://localhost:port/Params/Index6/600 //Valid and value of Id is 600
http://localhost:port/Params/Index6/true //Valid and value of Id is true
http://localhost:port/Params/Index6/34.56 //Invalid, because of the special character decimal

Local IIS:
http://localhost/MVCTestProject3/Params/Index6 //Valid and value of Id is null

92
http://localhost/MVCTestProject3/Params/Index6/Hello //Valid and value of Id is Hello
http://localhost/MVCTestProject3/Params/Index6/600 //Valid and value of Id is 600
http://localhost/MVCTestProject3/Params/Index6/true //Valid and value of Id is true
http://localhost/MVCTestProject3/Params/Index6/34.56 //Invalid, because of the special character decimal

Passing multiple parameters to Action method: If we want to pass multiple parameters to Action methods, we can
change the default route “URL” in RouteConfig class, for example if we want to have 2 parameters to our action
methods re-write the “URL” as following:
url: "{controller}/{action}/{id}/{name}"

Now in the below, change the defaults as following:


defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, name = UrlParameter.Optional }

Now we can define action methods to accept 2 parameters with the names “id” & “name” and to test that
add 2 new Action methods under our “ParamsController” class as following:

//Passing value to Id is mandatory and Name is optional


public string Index7(int Id, string Name) {
return $"Value of Id is: {Id} and value of Name is: {Name}";
}
//Passing values to Id and Name are optional
public string Index8(int? Id, string Name) {
return $"Value of Id is: {Id} and value of Name is: {Name}";
}

Execute the above methods as following:


IIS Express:
http://localhost:port/params/Index7 //Invalid because Id is mandatory parameter
http://localhost:port/params/Index7/700 //Valid, in this case Name will be null value
http://localhost:port/params/Index7/700/Raju //Valid
http://localhost:port/Params/Index7/Raju/700 //Invalid because parameter values not in order
http://localhost:port/Params/Index7?Id=700&Name=Raju //Valid, as we are passing values by specifying names
http://localhost:port/Params/Index7?Name=Raju&Id=700 //Valid, as we are passing values by specifying names

Local IIS:
http://localhost/MVCTestProject3/params/Index7 //Invalid because Id is mandatory parameter
http://localhost/MVCTestProject3/params/Index7/700 //Valid, in this case Name will be null value
http://localhost/MVCTestProject3/params/Index7/700/Raju //Valid
http://localhost/MVCTestProject3/Params/Index7/Raju/700 //Invalid because parameter values not in order
http://localhost/MVCTestProject3/Params/Index7?Id=700&Name=Raju //Valid
http://localhost/MVCTestProject3/Params/Index7?Name=Raju&Id=700 //Valid

IIS Express:
http://localhost:port/params/Index8 //Valid, in this case Id & Name will be null value
http://localhost:port/params/Index8/800 //Valid, in this case Name will be null value
http://localhost:port/params/Index8/800/Raju //Valid

93
http://localhost:port/Params/Index8/Raju/800 //Valid, in this case id will be null value
http://localhost:port/Params/Index8?Name=Raju //Valid, in this case id will be null value
http://localhost:port/Params/Index8?Id=800&Name=Raju //Valid, as we are passing values by specifying names
http://localhost:port/Params/Index8?Name=Raju&Id=800 //Valid, as we are passing values by specifying names

Local IIS:
http://localhost/MVCTestProject3/params/Index8 //Valid
http://localhost/MVCTestProject3/params/Index8/800 //Valid
http://localhost/MVCTestProject3/params/Index8/800/Raju //Valid
http://localhost/MVCTestProject3/Params/Index8/Raju/800 //Valid
http://localhost/MVCTestProject3/Params/Index8?Name=Raju //Valid
http://localhost/MVCTestProject3t/Params/Index8?Id=800&Name=Raju //Valid
http://localhost/MVCTestProject3/Params/Index8?Name=Raju&Id=800 //Valid

Using Query String: by using Query String’s also we can pass values to Action methods and to test that add a new
Action method into the “ParamsController” class as following:

public string Index9(int Pid, string Pname, double Price) {


return $"Pid: {Pid}; Pname: {Pname}; Price: {Price}";
}

Now run the application by using the following URL:


IIS Express:
http://localhost:port/Params/Index9/101/Shoes/3500 //Invalid
http://localhost:port/Params/Index9?Pid=101&Pname=Shoes&Price=3500 //Valid
http://localhost:port/Params/Index9?Pname=Shoes&Price=3500&Pid=101 //Valid
http://localhost:port/Params/Index9?Price=3500&Pid=101&Pname=Shoes //Valid

Local IIS:
http://localhost/MVCTestProject3/Params/Index9/101/Shoes/3500 //Invalid
http://localhost/MVCTestProject3/Params/Index9?Pid=101&Pname=Shoes&Price=3500 //Valid
http://localhost/MVCTestProject3/Params/Index9?Pname=Shoes&Price=3500&Pid=101 //Valid
http://localhost/MVCTestProject3/Params/Index9?Price=3500&Pid=101&Pname=Shoes //Valid

Note: Without defining any parameters to the Action method also we can read Query String values in our code, to
test that add a new Action method into the “ParamsController” class as following:

public string Index10() {


int Pid = int.Parse(Request.QueryString["Pid"]);
string Pname = Request.QueryString["Pname"];
double Price = double.Parse(Request.QueryString["Price"]);
return $"Pid: {Pid}; Pname: {Pname}; Price: {Price}";
}

Now run the application by using the following URL:


IIS Express:
http://localhost:port/Params/Index10 //Invalid

94
http://localhost:port/Params/Index10/101/Shoes/3500 //Invalid
http://localhost:port/Params/Index10?Pid=101&Pname=Shoes&Price=3500 //Valid
http://localhost:port/Params/Index10?Pname=Shoes&Price=3500&Pid=101 //Valid
http://localhost:port/Params/Index10?Price=3500&Pid=101&Pname=Shoes //Valid

Local IIS:
http://localhost/MVCTestProject3/Params/Index10 //Invalid
http://localhost/MVCTestProject3/Params/Index10/101/Shoes/3500 //Invalid
http://localhost/MVCTestProject3/Params/Index10?Pid=101&Pname=Shoes&Price=3500 //Valid
http://localhost/MVCTestProject3/Params/Index10?Pname=Shoes&Price=3500&Pid=101 //Valid
http://localhost/MVCTestProject3/Params/Index10?Price=3500&Pid=101&Pname=Shoes //Valid

Note: re-write the above method as below and this will not cause any error when values are not passed because of
Convert.ToIn32 and Convert.ToDouble methods which we used in place of int.Parse and double.Parse methods.

public string Index11() {


int Pid = Convert.ToInt32(Request.QueryString["Pid"]);;
string Pname = Request.QueryString["Pname"];
double Price = Convert.ToDouble(Request.QueryString["Price"]);
return $"Pid: {Pid}; Pname: {Pname}; Price: {Price}";
}

Now run the application by using the following URL:


IIS Express:
http://localhost:port/Params/Index11 //Valid

Local IIS:
http://localhost/MVCTestProject3/Params/Index11 //Valid

Now let’s write another 2 methods to understand about Query String’s, 1 with-out parameters and 1 with
parameters.

public string Validate1() {


string Name = Request["Name"];
string Pwd = Request["Pwd"];
if (Name == "Raju" && Pwd == "Admin")
return "Valid User";
else
return "Invalid User";
}
public string Validate2(string Name, string Pwd) {
if (Name == "Raju" && Pwd == "Admin")
return "Valid User";
else
return "Invalid User";
}

95
We can execute the above methods as following:
IIS Express:
http://localhost:port/Params/Validate1?Name=Raju&Pwd=Admin //Valid
http://localhost:port/Params/Validate1?Pwd=Admin&Name=Raju //Valid
http://localhost:port/Params/Validate2?Name=Raju&Pwd=Admin //Valid
http://localhost:port/Params/Validate2?Pwd=Admin&Name=Raju //Valid

Local IIS:
http://localhost/MVCTestProject3/Params/Validate1?Name=Raju&Pwd=Admin //Valid
http://localhost/MVCTestProject3/Params/Validate1?Pwd=Admin&Name=Raju //Valid
http://localhost/MVCTestProject3/Params/Validate2?Name=Raju&Pwd=Admin //Valid
http://localhost/MVCTestProject3/Params/Validate2?Pwd=Admin&Name=Raju //Valid

Action Methods: The methods that we defined under the Controller class for performing user interactions are known
as Action methods i.e., users will directly call these methods for performing actions.

To define Action Methods, we need to follow a set of rules:


1. Action methods must be public, so every public method in a Controller class is an Action method only.
2. Action methods cannot be static because behind the screen instance of the Controller class is used for calling
the Action methods.
3. It is not suggested to overload Action methods, but if required we can still do that by decorating the method
with “ActionName” attribute.

[ActionName("SayHello1")]
public string SayHello()
{
return "Hello how are you?";
}
[ActionName("SayHello2")]
public string SayHello(string Name)
{
return "Hello " + Name + " how are you?";
}

Note: in the above case we need to call the method with the “ActionName” we have defined, but not with the
original method name, to test this define the above methods inside of “ParamsController” class and then we need
to call them as below:

We can execute the above methods following:


IIS Express:
http://localhost:port/Params/SayHello1
http://localhost:port/Params/SayHello2?Name=Raju

Local IIS:
http://localhost/MVCTestProject3/Params/SayHello1
http://localhost/MVCTestProject3/Params/SayHello2?Name=Raju

96
4. If we want to define any non-action methods in a controller class, make sure they are not public or else decorate
them with “NonAction” attribute and in this case when we try to access those methods from browser we get
“404 Not Found” error.

<private or internal or protected or private protected or protected internal> string Display()


{
return "Non-Action Method";
}
Or
[NonAction]
public string Display()
{
return "Non-Action Method";
}

5. Action methods are generally value returning and very importantly in an MVC Application - Action Methods
return type is an “ActionResult”, where “ActionResult” is a class type and under this class there are a set of child
classes and we call all those classes as Action Result’s only, and we can use any of those child classes as a return
type of our Action method.

List of ActionResult child classes are:


ActionResult
 FileResult
 FilePathResult
 FileStreamResult
 FileContentResult
 JsonResult
 ViewResult
 EmptyResult
 ContentResult
 RedirectResult
 JavaScriptResult
 PartialViewResult
 HttpStatusCodeResult
 RedirectToRouteResult

General signature of an Action method will be as following:


public <ActionResult> <Name>( [<Parameter List>] )
{
-Implement all the required logic here
-return an ActionResult
}

Note: The most important ActionResult of an Action method is “ViewResult”, and a View in an MVC Application is
the UI (User Interface) which contains all the presentation logic in it. The extension of a View will be “.cshtml” in
case the programming language is “C#” or “.vbhtml” in case the programming language is “VB.NET”.

97
6. An Action method to return an “ActionResult”, we are provided with a set of methods known as “Helper
Methods” and these helper methods are defined under Controller class, which is the parent or base class for
all the controllers we define.

Helper Methods Action Results


File FileResult
Json JsonResult
View ViewResult
--- EmptyResult
Content ContentResult
Redirect RedirectResult
JavaScript JavaScriptResult
PartialView PartialViewResult
HttpNotFound HttpStatusCodeResult
RedirectToRoute RedirectToRouteResult
RedirectToAction RedirectToRouteResult

Note: all the above helper methods are defined under the class “Controller” and to see them go to
“ParamsController.cs” file and in that file, right click on the “Controller” class and select the option “Go to Definition”
which will take you to the pre-defined Controller class and display’s the metadata of that class.

Views
View is the second important component in an MVC Application which acts as a UI (User Interface) for
presenting the data or results to end users as well as for accepting data from users. Views are stored under “Views”
folder and under this folder a separate folder is maintained for storing the Views associated with each Controller
i.e., if we have an “EmployeeController” then under the Views folder we will have “Employee” folder for storing all
the Views that are associated with “EmployeeController” and so on.

Note: if a Controller is added by using Scaffolding, then automatically it will also add an associated folder for storing
its Views, under the Views folder, whereas this will not happen if we define a Controller with manual coding and in
that case, it is our responsibility to do that. Under the Views folder we can also maintain a folder with the name
“Shared” for storing the Views that are common for multiple Controllers.

What does a View contain in it?


Ans: A View contains code for presentation or presentation logic which is a combination of “C# or VB” and HTML
(CSS and Java Script also). When a request is sent for a View by the client, the logic implemented in the View gets
processed and finally everything gets converted into Text (HTML) and we call this process as “Rendering”.

What is rendering?
Ans: Unfortunately, Internet still has bandwidth limitations and not every person is running on the same OS, same
Web Browser or same Device, and these issues make it necessary to stick with HTML (Text Format) as our mark-up
language of choice.

So, in all the Server-Side technologies including ASP.NET; Web Server will process all the logic implemented
by us using any language and converts the result into Text (HTML) which we call it as “Rendering” and then that
HTML will be sent to clients as response.

98
Views in ASP.NET MVC are processed by “View Engines” to render the results and we are provided with a
support of 2 different View Engines, those are:
1. Web Forms Engine
2. Razor Engine

Web Forms Engine: this is the default View Engine that is introduced along with MVC in 2008 and the coding style
will exactly be like ASP.NET Web Forms, and the extension of View Files here is “.aspx.cs” or “.aspx.vb”.

Razor Engine: this is introduced in MVC 3.0 and in this case, View Files will be having an extension of “.cshtml” or
“.vbhtml” based on the language we use for developing the Views.

Note: Razor Engine is the most advanced View Engine and the most recommended also. Views that are created for
Razor Engine are known as Razor Views and these Views can contain either “HTML and C# or VB” code in them with
an easy to use syntax.

Sample Web Form View with for loop:


<%
for(int i=1;i<=10;i++)
{
%>
<h3>Hello World</h3>
<%
}
%>

Sample Razor View with for loop:


@{
for(int i=1;i<=10;i++)
{
<h3>Hello World</h3>
}
}

Note: apart from the above 2 View Engines, ASP.NET MVC also supports many other third-party View Engines also
like “NHaml”, “Brail”, “NDjango”, “Spark”, “Hasic” etc.

Creating Action methods returning ViewResult: create a new ASP.NET Web Application project naming it as
“MVCActionResults”; choose “Empty Project Template”, check “MVC” CheckBox and click on the Create Button.

Now add a Controller in to the Controllers folder of the project naming it as “HomeController” and by
default the class contains a method with the name “Index” and it’s return type will be “ActionResult”, change it as
“ViewResult” (not mandatory) or leave the same and add 2 more Action methods in the class as below:

public ViewResult Register()


{
return View();
}

99
public ViewResult Login()
{
return View();
}

Adding Views for Action Methods: we place Views under Views folder of the project and whenever a Controller is
added to the project using Scaffolding, automatically a new folder gets added to the Views folder with the name of
that Controller, so under the Views folder we will now find a folder with the name “Home” as we added a controller
with the name “Home” and all Views that are associated with this Controller are generally placed into that Home
folder.

Now let’s add 3 Views i.e., 1 for each Action method and to do that right click on the Home folder, select
Add => “View”, this will open a new window with the name “Add New Scaffolded Item”, in that select “MVC 5 View”
and click “Add” which opens a new window “Add View”, in that window under “View Name” TextBox specify the
view name as “Index” (will by default show the name as “View”), leave the “Template” TextBox with its existing value
i.e., “Empty (without model)”, un-check all other Checkbox’s on the screen and click on “Add” button which will add
the View with some HTML Code in it.

Now in the view file write the below code under the “<div>” tag:
<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>
<h2>Click on the links below to navigate:</h2>
<h3>
<a href="/Home/Register">Register</a> <br />
<a href="/Home/Login">Login</a> <br />
<a href="/Home/ForgotPassword">Forgot Password</a><br />
<a href="/Home/ResetPassword">Reset Password</a><br />
<a href="/Home/Contact">Contact Us</a><br />
<a href="/Home/Mission">Mission</a><br />
<a href="/Home/About">About Us</a><br />
</h3>

Add another view same as the above with the name Register and write the below code in its <div> tag:
<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>
<h3 style="text-align:center;text-decoration:underline">Registration Page</h3>
<table align="center">
<tr><td>Name:</td><td><input type="text" id="txtName" name="txtName" /></td></tr>
<tr><td>User Id:</td><td><input type="text" id="txtUid" name="txtUid" /></td></tr>
<tr><td>Password:</td><td><input type="password" id="txtPwd" name="txtPwd" /></td></tr>
<tr><td>Confirm Password:</td><td><input type="password" id="txtCPwd" name="txtCPwd" /></td></tr>
<tr><td>Mobile:</td><td><input type="tel" id="txtMobile" name="txtMobile" /></td></tr>
<tr><td>Email Id:</td><td><input type="email" id="txtEmail" name="txtEmail" /></td></tr>
<tr>
<td colspan="2" align="center">
<input type="submit" id="btnRegister" value="Register" />
<input type="reset" id="btnReset" value="Reset" />
</td>

100
</tr>
</table>
<h4 style="text-align:center;color:red">
Click here to go to <a href="/Home/Index">Home Page.</a>
</h4>

Now add another view same as the above with the name Login and write the below code in its <div> tag:
<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>
<h3 style="text-align:center;text-decoration:underline">Login Page</h3>
<table align="center">
<tr><td>User Id:</td><td><input type="text" id="txtUid" name="txtUid" /></td></tr>
<tr><td>Password:</td><td><input type="password" id="txtPwd" name="txtPwd" /></td></tr>
<tr>
<td colspan="2" align="center">
<input type="submit" id="btnLogin" value="Login" />
<input type="reset" id="btnReset" value="Reset" />
</td>
</tr>
</table>
<h4 style="text-align:center;color:red">
Click here to go to <a href="/Home/Index">Home Page.</a>
</h4>

Now run the project which will launch the “Index” view first because we are already aware that, default
Controller is Home and default Action method is Index (listed in RouteConfig class). Index View will provide Links
for launching Login and Register views, click on them to launch the corresponding Views.

Note: while launching a View we don’t require to specify the View Name in the Helper method => “View()” because
View names matches with the Action method names.

Can the Action method name and View name be different?


Ans: Yes, Action method name and View name can be different, and if they are different, we need to explicitly pass
View name or path of that View as a parameter to the Helper method. To test this, add 2 new Views naming them
as “ForgotPwd” and “ResetPwd”.

Write the below code under “<div>” tag of “ForgotPwd.cshtml” file:


<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>
<div style="text-align:center;background-color:cyan">
Forgot your password? Enter your registered Email Id, to receive a reset password link.
<br />
Email Id: <input type="email" id="txtEmail" name="txtEmail" />
<input type="submit" id="btnSubmit" value="Submit" />
</div>
<h4 style="text-align:center;color:red">
Click here to go to <a href="/Home/Index">Home Page.</a>
</h4>

101
Write the below code under “<div>” tag of “ResetPwd.cshtml” file:
<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>
<div style="text-align:center;background-color:cyan">
<h4>Reset Password</h4>
<table align="center">
<tr><td>New Password:</td><td><input type="password" id="txtPwd" name="txtPwd" /></td></tr>
<tr><td>Confirm Password:</td><td><input type="password" id="txtCPwd" name="txtCPwd" /></td></tr>
<tr>
<td colspan="2" align="center">
<input type="submit" id="btnSubmit" value="Submit" />
<input type="reset" id="btnReset" value="Reset" />
</td>
</tr>
</table>
</div>
<h4 style="text-align:center;color:red">Click here to go to <a href="/Home/Index">Home Page.</a></h4>

Now go to “HomeController” class and add 2 new Action Methods in the class as following:
public ViewResult ForgotPassword()
{
return View("ForgotPwd");
}
public ViewResult ResetPassword()
{
return View("~/Views/Home/ResetPwd.cshtml");
}

Note: in the above case Action method names are not matching with View names so we are explicitly passing View
name as parameter to the Action method and that can be done in any of the above 2 ways.

Is it mandatory to place the View exactly under the folder representing the Controller?
Ans: No, it is not mandatory i.e., we can place them in “Shared” folder also which will be present inside of the Views
folder. To test this, add a new folder under Views folder naming it as “Shared” and add a View into the folder naming
it as “Contact.cshtml” and write the below code under its “<div>” tag:

<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>


<div style="background-color:cyan">
<fieldset style="border: 5px solid coral">
<legend>Contact Us:</legend>
&nbsp;&nbsp;Phone: 2374 6666 <br />
&nbsp;&nbsp;Whatsapp: 81791 91999 <br />
&nbsp;&nbsp;Email: [email protected] <br />
&nbsp;&nbsp;Website: www.nareshit.com <br />
&nbsp;&nbsp;Address: 2nd Floor, Durga Bhavani Plaza, Satyam Theatre Road, Ameerpet, Hyderabad - 500016
</fieldset>
</div>
<h4 style="text-align:center;color:red">Click here to go to <a href="/Home/Index">Home Page.</a></h4>

102
Now go to “HomeController” class and add a new Action Methods in the class as below:
public ViewResult Contact()
{
return View();
}

Note: in the above case the View gets launched even if it is not present inside of the Home folder because View
Engine will first search in the Home folder and if not found, then it will search in the Shared folder to find the View.
Apart from the Shared folder we can also place it in any other folders also but if we do so, we need to explicitly
specify path of the View to the Helper method, and to test this add another new folder in Views folder with the
name as “Test”, and under the new folder add a View naming it as “Mission.cshtml” and write the below code under
its “<div>” tag:

<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>


<div style="background-color:burlywood">
<h3 style="text-align: center;color:chartreuse">Our Mission</h3>
<p style="text-align: justify; font-size:16px; text-indent:50px; color:brown">To enrich the knowledge & skill sets of
young software engineers by providing value added training in the areas of Software Development & Testing. To
serve the industries by providing trained human resources in the above areas. To provide quality Software Training
and Consulting Services in the areas of J2EE, .NET, ERP, Database Administration, Testing, Content Management with
Live Projects.
</p>
</div>
<h4 style="text-align:center;color:red">Click here to go to <a href="/Home/Index">Home Page.</a></h4>

Now go to “HomeController” class and add a new Action method in the class as below:
public ViewResult Mission()
{
return View("~/Views/Test/Mission.cshtml");
}

What is the default View Engine in an MVC 5 Application?


Ans: The default View Engine in an MVC5 Application is “Web Form Engine”, so if a View page is existing with both
“.aspx” as well as “.cshtml” extensions the first preference goes to “.aspx” only.

To test this, add 2 new Views into the Home folder of Views folder with the name “About.aspx” and
“About.cshtml”.

Note: From MVC5 the support for adding “Web Form Views” is removed in Visual Studio, so we should explicitly add
an “ASP.NET Web Form” and make the necessary changes to it to make it a “Web Form View” and to do that, right
click on the Home folder under Views Folder, select Add => New Item and in the New Item Window select “Web
Form”, name it as “About.aspx” and click on “Add” button to add a “Web Form” and then write the below code in
“About.aspx” file under its “<div>” tag:

<h1 style="text-align: center; color: red; text-decoration: underline">Naresh I Technologies</h1>


<div style="background-color: cyan">

103
<h3 style="text-align: center">About page created using Web Form View Engine.</h3>
<p style="text-align: justify; font-size: 16px; text-indent: 50px; color: coral">Naresh I Technologies (Pronounced:
NareshIT) is a leading software training institute providing Software Training, Project Guidance, IT Consulting and
Technology Workshops. Using our enhanced global software training delivery methodology, innovative software
training approach and industry expertise, we provide high-value corporate training services that enable our clients
to enhance business performance, accelerate time-to-market, increase productivity, and improve customer service.
We serve Global 100 companies and the leading software vendors in Banking & Financial Services, Insurance,
Telecommunications, Technology and Media, Information & Education industries. We design and mentor human
resources for our clients who create competitive advantage. Founded in 2004 and headquartered in Hyderabad,
India, we have offices and training institutes throughout India.
</p>
</div>
<h4 style="text-align: center; color: red">Click here to go to <a href="/Home/Index">Home Page.</a></h4>

Now go to “About.aspx.cs” and to do that, right click on “About.aspx” and select the option “View Code”
which will take us to “About.aspx.cs” and there we will find a class “About” inheriting from “System.Web.UI.Page”,
change that as “System.Web.Mvc.ViewPage”.

Now add another view in home folder naming it as “About.cshtml” and write same code as above View in
the “<div>” tag but change the “Inner Html” of “<h3>” tag in the top as: About page created using Razor View
Engine.

Now go to HomeController class and add a new Action Methods in the class as following:
public ViewResult About()
{
return View();
}
Now launch Index View and click on the “About Page” hyper link and this will launch “About.aspx” page
because by default it will search for “.aspx” pages first, whereas if we want “About.cshtml” page to be launched we
need to pass the path of “About.cshtml” file as parameter to Helper method and to test that re-write code in “About”
action method as following:
return View("~/Views/Home/About.cshtml");

Without passing the address of View Page to Helper Method also, we can launch the “.cshtml” View and to
do that we need to either clear all the “View Engines” and then freshly add “Razor View Engine” or remove the “Web
Form View Engine” to make “Razor View Engine” as default View Engine. To do that go to “Global.asax” file and write
the below code in top of “Application_Start” method:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
Or
ViewEngines.Engines.Remove(ViewEngines.Engines.OfType<WebFormViewEngine>().FirstOrDefault());

Note: Now even if the code under “About” action method is “return View();” also, it will launch “About.cshtml” only
and in this case if we try to launch “About.aspx” View Page by specifying the explicit path also, we get an error
because “WebFormViewEngine” support has been removed by us.

104
Can an Action method return different views based on a condition?
Ans: Yes, it is possible to return different Views by an Action method based on a condition. To test this, add 2 new
Views under Home folder of Views with the names “Show1.cshtml” and “Show2.cshtml”, and write the below code
under their “<div>” tags:

Show1.cshtml:
<h1 style="text-align:center;color:red;text-decoration:underline">Naresh I Technologies</h1>
<div style="background-color: cyan"><h3 style="text-align: center">This is Show1 View Page</h3></div>
<h4>Click here to go to <a href="/Home/Index">Home Page.</a></h4>

Show2.cshtml:
<h1 style="text-align: center; color: red">Naresh I Technologies</h1>
<div style="background-color: cyan"><h3 style="text-align: center">This is Show2 View Page</h3></div>
<h4>Click here to go to <a href="/Home/Index">Home Page.</a></h4>

Now under “HomeController” class add a new Action method as following:


public ViewResult Show(int id) {
if (id == 1)
return View("Show1");
else
return View("Show2");
}

Now go to “Index.cshtml” and add the below links over there:


<a href="/Home/Show/1">Show1 View</a><br />
<a href="/Home/Show/2">Show2 View</a>

MVC Action Selectors: these are attributes that can be applied on an Action method, and they help the View Engine
to select the correct Action Method to handle the request.

We have 3 Action Selectors and those are:


1. ActionName
2. NonAction
3. ActionVerbs

ActionName: this attribute is used to specify a different name to any Action method than its actual name. We use
this attribute when we want an Action method to be called with a different name instead of the actual name of the
method. Generally used in-case we want to overload Action methods. For Example:
[ActionName("Launch")]
public ViewResult LaunchViewPageLoadingDataFromDatabase()

Non-Action: this attribute indicates a public method of the Controller is not an Action method i.e., when we use this
attribute, then the public method in the Controller class will not be treated as an Action method and we can’t call
this method from browsers using a URL. For Example:
[NonAction]
public string SayHello()

105
ActionVerbs: this attribute is used on an Action method when we want to handle different type of HTTP Requests.
MVC framework provides various action verbs like: “HttpGet”, “HttpPost”, “HttpPut”, “HttpDelete”, “HttpOptions”
and “HttpPatch”. You can apply one or more action verbs on an action method to handle different HTTP Requests.
If we don’t apply any action verb on an action method, then by default it handles “HttpGet” requests. In our
application if we have defined 2 Login Action methods and those methods are decorated with [HttpGet] and
[HttpPost] Action Verbs, then whenever we send the first request (get request) to “Login” Action method then it will
invoke the method which is decorated with [HttpGet] Action Verb and launches the corresponding View. When we
fill in the credentials and click on the “Login” button it will send a “Post” or “Postback” request and will then invokes
“Login” Action method which is decorated with [HttpPost] Action Verb. For Exampe:
[HttpGet]
public ViewResult Login() //Responds for Get Request

[HttpPost]
public ViewResult Login(string Name, string Password) //Responds for Post Request

Razor Programming
From MVC 3.0, Microsoft has introduced Razor Engine for creating View without using Web Forms Engine.
Views that are created targeting Razor Engine are saved with “.cshtml” extension whereas Views that are created
targeting Web Form Engine are saved with “.aspx” extension.

Web Forms are provided with Design View, Source View and Code View, where we will be using Design
View for design the UI with a “drag & drop” feature and Source View for implementing HTML, Java Script and CSS,
and Code View for implementing C# Logic whereas Razor View is provided only with Source View and here only we
can implement HTML, Java Script, CSS and C# Logic also, and this is the reason why these Views are saved with
“.cshtml” extension.

Razor Views are light weight when compared to Web Form Views because we don’t use any ASP.NET Server
Controls but will use only Html Controls so doesn’t require maintaining of View State.

Razor View Pages uses “@{ ... }” sign to implement C# code, whereas in Web Form Pages if we want to write
any C# code it should be under “<% ... %>” tags.

Code in Razor View Page can be written in 3 different ways:


1. Single Line Statements.
2. In-Line Statements.
3. Multi Line Statements.

Single Line Statements: these are generally used for declarations and Initializations.
Syntax:
@{ <Stmt>; }

Examples:
@{ int Count = 0; }
@{ Count += 100; }
@{ Object obj = new Object(); }
@ { String str = "Hello World"; }

106
In-Line Statements: these statements are generally used for accessing or printing the values of Members, just by
pre-fixing “@” character before the Member.
<h3>Value of Count is: @Count</h3>
<h3>obj is of type: @obj.GetType() </h3>

Multi Line Statements: we use this for writing multiple lines of code that can be C# or/and HTML also.
Syntax:
@{
<Stmt's>
}

Example:
@{
string Date = DateTime.Now.ToShortDateString();
string Time = DateTime.Now.ToShortTimeString();
<h3>Today's Date is: @Date</h3>
<h3>Current Time is: @Time</h3>
}

Note: in multiline statement block we can write HTML Code directly without enclosing them in double quotes,
whereas if we want to use any static text, we need to either prefix it with “@:” or put it under “<text></text>” tags.
@{
string Date = DateTime.Now.ToShortDateString();
string Time = DateTime.Now.ToShortTimeString();
@:Today's Date is: @Date
<text>Current Time is:</text> @Time
}

Comments in razor programming should be under “@* Comment Text *@” and in a multiline statement
block we can also use our C# style of single line commenting i.e. “//”.

To test the above add, a new Controller in our current project i.e., “MVCActionResults”, name the Controller
as “RazorController”, add a View to the default “Index” Action method, and write the below code in its “<div>” tag:

@* Single Line Statements *@


@{ int Count = 0; }
@{ Count += 100; }
@{ string str = "Hello World"; }
@{ Object Obj = new Object(); }

@* In Line Statements *@
Value of count is: @Count
<br>
Value of str is: @str
<br>
Obj is of type: @Obj.GetType()
<hr>

107
@* Multi Line Statements *@
@{
string Date = DateTime.Now.ToShortDateString();
string Time = DateTime.Now.ToShortTimeString();
<span>Today's Date is: @Date</span> <br>
@:Current Time is: @Time <br>
<text>Current Time is: @Time</text>
}
<hr>

@* If condition in Razor programming *@


@{
int x = 131;
if (x % 2 == 0)
{
<span>@x is an even number.</span>
}
else
{
<span>@x is an odd number.</span>
}
}
<hr>

@{ string[] Colors = { "Red", "Blue", "Green", "Yellow", "Magenta" }; }


@* Loops in Razor programming - For Loop *@
@{
<h4>List of colors printed using for loop:</h4>
<ol>
@for (int i = 0; i < Colors.Length; i++)
{
<li>@Colors[i]</li>
}
</ol>
}
<hr>

<h4>List of colors printed using for loop:</h4>


<ol>
@for (int i = 0; i < Colors.Length; i++)
{
<li>@Colors[i]</li>
}
</ol>
<hr>

108
<h4>List of colors printed using for loop:</h4>
<ol>
@{
for (int i = 0; i < Colors.Length; i++)
{
<li>@Colors[i]</li>
}
}
</ol>
<hr>

@* Loops in Razor programming - ForEach Loop *@


@{
<h4>List of colors printed using foreach loop:</h4>
<ul>
@foreach (string color in Colors)
{
<li>@color</li>
}
</ul>
}
<hr>

<h4>List of colors printed using foreach loop:</h4>


<ul>
@foreach (string color in Colors)
{
<li>@color</li>
}
</ul>
<hr>

<h4>List of colors printed using foreach loop:</h4>


<ol>
@{
foreach (string color in Colors)
{
<li>@color</li>
}
}
</ol>

109
Passing values from Controller - Action Methods to Views
We are already aware that in an MVC Application all requests are handled by a Controller and these
Controllers only will receive the information either from the End User or Model and these values should be sent to
the View for displaying. To pass values from a Controller’s - Action method to a View we are provided with various
options like:
1. ViewData
2. ViewBag
3. TempData
4. Cookies
5. Session
6. Application
7. Anonymous Types
8. Models

To test all the above options, create a new “ASP.Net Web Application” project naming it as
“MVCDataTransfer”, choose “Empty Project Template”, select “MVC Checkbox” and click on the Create button.

Now go to “RouteConfig.cs” file and modify the “url” value as below:


Old URL => url: "{controller}/{action}/{id}" New URL => url: "{controller}/{action}/{id}/{name}/{price}"

Now change the defaults also as following:


defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional, name = UrlParameter.Optional, price = UrlParameter.Optional
}

ViewData: this is a Property defined under the class “ControllerBase” which is a grandparent for all our Controllers,
so we can directly consume “ViewData” property in our Controller classes. ViewData is of type “ViewDataDictionary”
which will internally store the data in the form of “Key-Value” or “Name-Value” combination, so values that are
stored in this “ViewData” will internally be stored in “ViewDataDictionary”.

Storing values into ViewData:


Syntax: ViewData[string Key] = Value (object)
Example: ViewData["Name"] = "Raju";

Accessing values from ViewData:


Syntax: Object obj = ViewData[string Key]
Example: Object obj = ViewData["Name"];
string Name = obj.ToString();
Or
string Name = ViewData["Name"].ToString();

Add a new Controller in our project naming it as “HomeController”, delete the existing “Index” action
method in the class and write the below code in the class:

110
public ViewResult Index1(int? id, string name, double? price)
{
ViewData["Id"] = id;
ViewData["Name"] = name;
ViewData["Price"] = price;
return View();
}

Now add a View to the “Index1” Action method (with-out choosing any layout) and write the following code
inside of the “<div>” tag:

<table border="1" align="center" width="15%">


<caption>Product Details</caption>
<tr>
<td>Id:</td><td>@ViewData["Id"]</td>
</tr>
<tr>
<td>Name:</td><td>@ViewData["Name"]</td>
</tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(ViewData["Price"]);
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Execute the “Index1” Action method as following: http://localhost:port/Home/Index1/101/Shoes/3500,


and in this case all the values that are sent to the Action method thru URL will be captured in Action method
parameters and stored into “ViewData” so that those values can be accessed under the corresponding View of
Index1’s action method.

Drawbacks of ViewData:
 ViewData can transfer data from a Controllers - Action method to its corresponding View only.
 ViewData life lasts only during the current HTTP request i.e., ViewData values will be cleared if redirection
occurs.
 ViewData is resolved dynamically at runtime, as a result, it doesn’t provide any compile-time error checking as
well as we do not get support of Intellisense. For example, if we miss-spell the “Key Names” then we will not
get any compile-time or runtime error also, whereas we come to know about the problem at the runtime
because the value is not displayed.
 ViewData values must be converted into an appropriate type (un-boxing) before using them because they are
present in object format, as we have performed in-case of Price value to calculate 10% Tax.

111
Note: we can store scalar as well as complex types also in ViewData but while accessing them we need to explicitly
convert them into its original type again. To test this, add a new Action method in “HomeController” class as below:

public ViewResult Display1()


{
List<string> Colors = new List<string>() { "Red", "Blue", "Pink", "Black", "White", "Green", "Brown", "Purple" };
ViewData["Colors"] = Colors;
return View();
}

Now add a View to the “Display1” Action method (with-out choosing any layout) and write the following
code inside of the “<div>” tag:

<h3>List of colors: </h3>


<ol>
@foreach (string color in (List<String>)ViewData["Colors"])
{
<li>@color</li>
}
</ol>

Execute “Display1” Action Method as following: http://localhost:port/Home/Display1

ViewBag: this is also a property defined in the class “ControllerBase”, but this of type “dynamic”. Dynamic is a new
type introduced in C# 4.0, capable of storing any type of value and this is type safe because it represents the value
in its exact type in runtime. ViewBag was introduced in MVC 3.0 which was just a wrapper around the ViewData but
was type safe, so it doesn’t require any type-conversions while consuming.

Storing a value into ViewBag:


Syntax: ViewBag.PropertyName = Value;
Example: ViewBag.Name = "Raju";

Accessing a value from ViewBag:


Syntax: <type> var = ViewBag.PropertyName;
Example: string Name = ViewBag.Name;

To test working with ViewBag add 2 new Action methods in the class Home Controller as below:
public ViewResult Index2(int? id, string name, double? price)
{
ViewBag.Id = id;
ViewBag.Name = name;
ViewBag.Price = price;
return View();
}

112
public ViewResult Display2()
{
List<string> Colors = new List<string>() { "Red", "Blue", "Pink", "Black", "White", "Green", "Purple", "Yellow" };
ViewBag.Colors = Colors;
return View();
}

Now add a View to each action method and write the below code under their <div> tag:
Index2.cshtml:
<table border="1" align="center" width="15%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@ViewBag.Id</td></tr>
<tr><td>Name:</td><td>@ViewBag.Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = ViewBag.Price;
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Display2.cshtml:
<h3>List of colors: </h3>
<ol>
@foreach (string color in ViewBag.Colors)
{
<li>@color</li>
}
</ol>

Execute Index2 Action Method as following: http://localhost:port/Home/Index2/105/Shoes/3500


Execute Display2 Action Method as following: http://localhost:port/Home/Display2

As discussed above “ViewBag” is a wrapper around “ViewData” i.e., data that is stored in the “ViewBag”
will be internally stored in “ViewDataDictionary” only, so values that are stored in a “ViewBag” can also be accessed
thru “ViewData” and vice-versa. To test this, go to “Index2.cshtml” and change the statement @ViewBag.Id to
@ViewData["Id"] and execute Index2 action method and still we get the same output as before.

Note: ViewBag is “Type Safe”, i.e., it doesn't require any type conversions while accessing data because we get the
values back in their original types only, whereas ViewData requires type conversion because values are stored as
object. ViewData and ViewBag are accessible only within the request i.e., with-in the corresponding View associated
with Action Methods. In case of both if “Key Names” are misspelled then we don’t get compile-time or runtime error.

113
TempData: this is also a property under the class “ControllerBase”, but this is of type “TempDataDictionary”. Both
“ViewDataDictionary” and “TempDataDictionary” are child classes of “IDictionary” interface which is designed for
storing data in [key-value] or [name-value] combination.

The difference between TempData and ViewData is TempData can maintain the state of values between
multiple requests i.e., it can pass values from 1 action method to another action method which are present in the
same controller or another controller also.

To test this, add 2 new action methods in “HomeController” class as below:


public RedirectToRouteResult Index3(int? id, string name, double? price)
{
ViewData["Id"] = id;
ViewBag.Name = name;
TempData["Price"] = price;
return RedirectToAction("Index4");
}
public ViewResult Index4()
{
return View();
}
In the above case request will first come to “Index3” action method with a set of route values and that
method stores those values into “ViewData”, “ViewBag” and “TempData” respectively, and then redirects to
“Index4” action method which is performed by using “RedirectToAction” helper method and in this case return type
of “Index3” action method should be “RedirectToRouteResult” but not “ViewResult”.

Now add a View to Index4 action method and write the below code in its “<div>” tag:
<table border="1" align="center" width="15%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@ViewData["Id"]</td></tr>
<tr><td>Name:</td><td>@ViewBag.Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(TempData["Price"]);
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Execute Index3 Action Method as following: http://localhost:port/Home/Index3/105/Shoes/3500

When the request is sent to “Index3” action method, it will redirect to “Index4” action method by calling
“RedirectToAction()”, so this method will send a re-direction response (302) to the browser, so that browser will

114
send a new request to “Index4” action method and then “Index4” View gets launched and we can watch that in the
browser’s address bar which will be now shown as: http://localhost:port/Home/Index4. If we watch the output in
the browser, it will not display the values of “Id” and “Name” but will display the value of “Price” because “ViewData”
and “ViewBag” can’t maintain the state of values between multiple requests, but “TempData” can maintain.

If we want to resolve the above problem, go to “Index3” action method and change “ViewData” and
“ViewBag” to “TempData” and change the code in “Index4.cshtml” file and watch the difference.

In the above example by using “RedirectToAction” helper method we are able to transfer the control from
1 action method to another action method that is present in the same controller, whereas we can also transfer to
an action method that is present in another controller also, and to test it, add a new action method in the
“HomeController” class as below:

public RedirectToRouteResult Index5(int? id, string name, double? price)


{
TempData["Id"] = id;
TempData["Name"] = name;
TempData["Price"] = price;
return RedirectToAction("Index1", "Test");
}
In the above code under “RedirectToAction” helper method, “Test” is the controller’s name and “Index1”
is the action method name where it must redirect. RedirectToAction helper method is an overloaded method that
is pre-defined as below:

RedirectToAction(string actionName)
RedirectToAction(string actionName, string controllerName)
RedirectToAction(string actionName, string controllerName, object routevalues)

Now add a new Controller in the project naming it as “TestController”, change the default Action method
name i.e., “Index” to “Index1”, add a View to the method and write the below code in the View under “<div>” tag:

<table border="1" align="center" width="15%">


<caption>Product Details</caption>
<tr><td>Id:</td><td>@TempData["Id"]</td></tr>
<tr><td>Name:</td><td>@TempData["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(TempData["Price"]);
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

115
Execute Index5 Action Method of Home Controller as following:
http://localhost:port/Home/Index5/105/Shoes/3500

After execution of Index5 Action method, the URL in address bar will be as following because it is re-directed:
http://localhost:port/Test/Index1

Flow of control: Request sent to => Index5 action method of HomeController => Redirected to => Index1 action
method of TestController.

Note: “TempData” is also not type safe like “ViewData” so here also we need to perform type conversion while
working with data and the only difference between “ViewData” and “TempData” is “TempData” can maintain the
state of values between multiple requests.

Drawback of TempData: If we access values once from “TempData” immediately all those values get deleted and
can’t be accessed in next requests, to test this add a hyper link below the table in “Index1.cshtml” file of
“TestController” as following:

<center>Click to launch new <a href="/Test/Display1">Page</a>.</center>

So, if we click on the hyper link it must call “Display1” action method of “TestController” class, so add a new
action method in “TestController” class as following:

public ViewResult Display1()


{
return View();
}

Add a View to Display1 action method and write the below code in its “<div>” tag:
<table border="1" align="center" width="15%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@TempData["Id"]</td></tr>
<tr><td>Name:</td><td>@TempData["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(TempData["Price"]);
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Execute Index5 Action Method of HomeController as following:


http://localhost:port/Home/Index5/105/Shoes/3500

116
This will launch “Index1” view of “TestController” displaying the values and now click on the hyper link we
added to launch “Display1” view of “TestController”, but “Display1” view will not display the values because we
accessed values in “Index1” view and immediately those values got deleted, so can’t be accessed in “Display1” view
again.

Flow of control: Request sent to => Index5 action method of HomeController => Redirected to => Index1 action
method of TestController => when the link is clicked redirects to => Display1 Action method of TestController.

To overcome the above problem and access the values in next requests, we need to use the “Peek” method
of “TempData” while accessing values, so that the values will be persisting even after accessing them and can be
accessed again. To do that, change the code of accessing data in “Index1” view as following:
@TempData["Id"] => @TempData.Peek("Id")
@TempData["Name"] => @TempData.Peek("Name")
@TempData["Price"] => @TempData.Peek("Price")

Note: In this case if we want to transfer data from “Display1” view to any other views there also we must change
the code as above.

To retain the values of “TempData” after accessing, we can also call “Keep” method in place of “Peek”, but
the difference is when we use “Keep” it will retain all the values of “TempData” and can be consumed in the next
request, where “Peek” method is used for retaining specific values only. So, without calling the Peek method 3 times
we can simply call the Keep method, and to try this write the below code, above the “<table>” tag in
“Display1.cshtml” file:
@{ TempData.Keep(); }

Note: Call Keep to preserve all the values of TempData and call Peek to preserve specific values of TempData.

Cookie: A Cookie is a small piece of text that is used to store user-specific information and that information can be
read by the Web Application whenever user re-visits the site. When a user requests for a Web Page, Web Server
sends not just a page, but also a cookie containing the date and time. Cookies are stored in browser memory or a
folder on the user’s hard disk and when the user requests for the Web Page again, browser looks for the Cookies
associated with the Web Site or Web Application and sends them to the Server. Browser stores cookies separately
for each different site we visit.

Writing Cookies on client machine: To write a Cookie on Client Machine first we need to create the instance of
HttpCookie class; store values into it treating it like a dictionary and then write that Cookie to Client Machine by
using Response object.
HttpCookie cookie = new HttpCookie("LoginCookie");
cookie["User"] = "Raju"; cookie["Pwd"] = "Admin@123";
Response.Cookies.Add(cookie);

Reading Cookies back on our WebPages: we can read Cookies Present on the Client Machine from a View or Action
Method using Request object.
HttpCookie cookie = Request.Cookies["LoginCookie"];
string User = cookie["User"];
string Pwd = cookie["Pwd"];

117
Cookies are of 2 types:
I. In-Memory Cookies
II. Persistent Cookies

In-Memory cookies are stored in browser's memory so once the browser is closed, immediately all the
cookies that are associated with that browser window will be destroyed, and by default every cookie is In-Memory
only. Persistent Cookies are stored on Hard Disk of the client machines, so even after closing the browser window
also they will be persisting and can be accessed next time we visit the site. To make a cookie as persistent we need
to set “Expires” property of Cookie with a “DateTime” value.

Setting expires property of Cookie:


cookie.Expires = <DateTime>;

To test working with Cookies, add 2 new Action methods in “HomeController” for creating a Cookie with a
set of values and then launching the View to display those values as below:

public ViewResult Index6(int? Id, string Name, double? Price)


{
HttpCookie cookie = new HttpCookie("ProductCookie");
cookie["Id"] = Id.ToString();
cookie["Name"] = Name;
cookie["Price"] = Price.ToString();
cookie.Expires = DateTime.Now.AddDays(3);
Response.Cookies.Add(cookie);
return View();
}
public ViewResult Index7()
{
return View();
}

Now add a View to “Index6” Action method and write the below code under its “<div>” tag:
@{
HttpCookie cookie = Request.Cookies["ProductCookie"];
int Id = int.Parse(cookie["Id"]);
string Name = cookie["Name"];
double Price = double.Parse(cookie["Price"]);
}
<table border="1" align="center" width="20%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@Id</td></tr>
<tr><td>Name:</td><td>@Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{

118
Price = Price + Price * 10 / 100;
@Price
}
</td>
</tr>
</table>
<center>Click to launch new <a href="/Home/Index7">Page</a>.</center>

Execute Index6 Action Method of Home Controller as following:


http://localhost:port/Home/Index6/105/Shoes/3500

In the above case when we call Index6 action method, will launch the associated view and displays the
values that are stored in the cookie and when we click on the Link in the bottom will call Index7 action method of
the same controller which will also display the values that stored in the cookie and to test that add a View for Index7
action method and write the below code in it under the “<div>” tag:

@{
HttpCookie cookie = Request.Cookies["ProductCookie"];
int Id = int.Parse(cookie["Id"]);
string Name = cookie["Name"];
double Price = double.Parse(cookie["Price"]);
}
<table border="1" align="center" width="20%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@Id</td></tr>
<tr><td>Name:</td><td>@Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{
Price = Price + Price * 10 / 100;
@Price
}
</td>
</tr>
</table>
<center>Click to launch new <a href="/Test/Index2">Page</a>.</center>

When we click on the Link in above View will launch Index2 action method of TestController and here also
it displays the values that are stored in Cookie and to test it add a new action method in TestController class as
below:

public ViewResult Index2()


{
return View();
}

119
Add a View to the above Index2 action method and write the below code under it’s “<div>” tag:
@{
HttpCookie cookie = Request.Cookies["ProductCookie"];
int Id = int.Parse(cookie["Id"]);
string Name = cookie["Name"];
double Price = double.Parse(cookie["Price"]);
}
<table border="1" align="center" width="20%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@Id</td></tr>
<tr><td>Name:</td><td>@Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{
Price = Price + Price * 10 / 100;
@Price
}
</td>
</tr>
</table>

Flow of control: Request sent to => “Index6” Action method of “HomeController” => when the hyper link is clicked
on this page, it is redirect to => “Index7” Action method of “HomeController” => when the hyper link is clicked on
this page, it is redirect to => “Index2” Action method of “TestController”.

Drawbacks of Cookies:
1. We can create only 50 cookies for each website, so every new cookie from the site will override the old cookie
once after reaching the limit.
2. A cookie can store only 4 K.B. of data that too of type string only.
3. Cookies are not secured because they are stored on client machines.
4. Because cookies are stored on client machines there is a problem like clients can delete the cookies.

Location of Persistant Cookies:


Microsoft Edge: C:\Users\<User>\AppData\Local\Microsoft\Edge\User Data\Default
Google Chrome: C:\Users\<User>\AppData\Local\Google\Chrome\User Data\Default

Delete Cookies on Browser: To delete cookies on our browser use the command Ctrl + Shift + Delete which will open
“Clear browsing data” window, in that select “Cookies and other site data” Checkbox and click “Clear now”. We can
also delete individual cookies using “Manage and delete cookies and site data” option.

Session: this is also a property, but defined under “Controller” class and this is of type “HttpSessionStateBase. Values
that are stored in a Session are accessible from anywhere to anywhere for a particular User in Session Life-time i.e.,
Action to Action in same Controller or another Controller, Controller to View, View to Controller, View to View etc.

Whenever a user connects to the Web Server, server will create a Session and gives it to the user for storing
any values that are associated with him which are accessible only to him in every page he visits in the site. This

120
happens for every user connecting to the server. So, each user will be having a Session of his own which will not be
shared between other users, in short, a session is a “Single-User Global Data”.

Storing values into a Session:


Syntax: Session[string key] = value (object)
Example: Session["Name"] = "Raju";

Accessing values from a Session:


Syntax: object value = Session[string key]
Example: object value = Session["Name"];
string Name = value.ToString();
Or
string Name = Session["Name"].ToString();

To test Sessions, add 2 new Action methods in “HomeController” as below for transferring session values
from Action method to Action method within a Controller:

public RedirectToRouteResult Index8(int? id, string name, double? price)


{
Session["Id"] = id;
Session["Name"] = name;
Session["Price"] = price;
return RedirectToAction("Index9");
}
public ViewResult Index9()
{
return View();
}
In the above case we are storing the values into a Session in “Index8” action method and then redirecting
to “Index9” action method of same Controller, so the View that is associated with “Index9” can access the values
from the Session and display them. Now add a View to “Index9” Action method and write the below code under its
“<div>” tag:

<table border="1" align="center" width="15%">


<caption>Product Details</caption>
<tr><td>Id: </td><td>@Session["Id"]</td></tr>
<tr><td>Name: </td> <td>@Session["Name"]</td></tr>
<tr>
<td>Price: </td>

121
<td>
@{
double Price = Convert.ToDouble(Session["Price"]);
Price = Price + (Price * 10 / 100);
@Price;
}
</td>
</tr>
</table>

Execute Index8 Action Method of Home Controller as following:


http://localhost:port/Home/Index8/105/Shoes/3500

After execution of Index8 Action Method, the URL in the address bar will be as following because it re-directed:
http://localhost:port/Home/Index9

Flow of control: Request sent to => “Index8” Action method of “HomeController” => Redirected to => “Index9”
Action method of “HomeController”.

Values that are stored in a Session are accessible in Action methods or Views which are defined in same or
different Controller also and for testing this add a new Action method in “HomeController” as below:

public RedirectToRouteResult Index10(int? id, string name, double? price)


{
Session["Id"] = id;
Session["Name"] = name;
Session["Price"] = price;
return RedirectToAction("Index3", "Test");
}

In the above case “Index10” action method of “HomeController” is storing the values into a Session and
then redirecting to “TestController” => “Index3” action method, so the view that is associated with the “Index3”
action method can access the values from Session and from there if we further redirect to any other View also, we
can access the values from the Session and to test that add 2 new Action methods in “TestController” as below:

public ViewResult Index3()


{
return View();
}
public ViewResult Display2()
{
return View();
}

Add a View to “Index3” Action method and write the below code under its “<div>” tag:
<table border="1" align="center" width="15%">

122
<caption>Product Details</caption>
<tr><td>Id:</td><td>@Session["Id"]</td></tr>
<tr><td>Name:</td><td>@Session["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(Session["Price"]);
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>
<center>Click to launch new <a href="/Test/Display2">Page</a>.</center>

Add a View to Display2 Action method and write the below code under its “<div>” tag:
<table border="1" align="center" width="15%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@Session["Id"]</td></tr>
<tr><td>Name:</td><td>@Session["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(Session["Price"]);
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Execute Index10 Action Method of Home Controller as following:


http://localhost:port/Home/Index10/105/Shoes/3500

Flow of control: Request sent to => “Index10” Action method of “HomeController” => Redirected to => “Index3”
Action method of “TestController” => when the hyper link is clicked on this page, it is again redirected to =>
“Display2” Action method of “TestController” and provides access to all the values that are stored in the Session but
for this User only.

How is a session identified to which user it belongs to?


Ans: Whenever a Session is created for a user it is given with a Unique I’d known as “SessionId” and this “SessionId”
is written to client’s browser in the form of a “In-Memory Cookie”, so whenever the client comes back to the server
in the next request, server will read the Cookie, picks the “SessionId” and associates user with his exact Session and
if no SessionId - Cookie is present then it will create a new Session.

123
Note: because SessionId is stored on client’s browser in the form of an “In-Memory Cookie”, other tabs under the
browsers instance can also access that Session, whereas a new instance of a new browser can’t access the Session.

What happens to Sessions associated with clients if the client closes the browser?
Ans: Every Session will be having a “time-out” period of “20 Minutes (default)” from the last request (Sliding
Expiration), so within 20 Minutes if the Session is not used by the User, Server will destroy that, Session.

Note: we can change the default time-out period of “20 Mins” to our required value thru “Web.config” file by setting
“timeout” attribute value of “sessionState” element. To test it write the below code under “<system.web>” tag:
<sessionState timeout="1" />

Can we explicitly destroy a Session associated with a User?


Ans: Yes, this can be performed by calling “Abandon()” method on the Session and this is what we generally do under
“Sign Out” or “Log Out” options in a Web Site or Web Application.
E.g.: Session.Abandon();

Where will Web Server store Session values?


Ans: Web Server can store Session values in 3 different locations:
I. In-Proc [d]
II. State Server
III. SQL Server

In-Proc: this is the default option used for storing Session values and in this case Session values are stored under the
memory of “IIS Worker Process”. To understand about these, first host your application on “Local IIS”.

What is IIS Worker Process?


Ans: Under IIS, Web Application run’s inside of a container known as Application Pool or an Application Pool is a
container of Web Applications that will execute by a single or multiple Worker Process. Application Pool is the Heart
of a Web Application and by default under IIS all Web Applications runs under the same Application Pool which is
created when IIS is installed i.e., “Default App Pool”. To check that open “IIS Manager” and in the LHS under
“Connections Panel” we will find “Applications Pools” and “Sites” options, select “Application Pools” which displays
“DefaultAppPool” on the RHS.

If you notice the above image there are 4 applications on the server running under “DefaultAppPool” and
it is still possible to run each Web Application under a separate Application Pool which enables us to isolate our Web
Application for better Security, Reliability and Availability; therefore, problems in one Application Pool do not affect
Web Sites or Applications in other Application Pools.

124
Note: whenever a new Site is created under IIS, it will also create an Application Pool under which the new Site runs
and name of that Application Pool will be the same name of Site. In the above picture you can see NITSite1 and
NITSite2 Application Pools associated with NITSite1 and NITSite2 Site’s we have created earlier.

We can also create our own Application Pools under IIS and to do that right click on Application Pools node
under Connection Panel and select “Add Application Pool” which opens a window asking for a name, enter name as
“MyPool” and click “Ok”. Currently the new Application Pool i.e., “MyPool” doesn’t have any applications running
under it and if we want our application “MVCDataTransfer” to run under “MyPool”, then right click on our application
under “Default Web Site” and choose Manage Applications => Advanced Settings, which opens a window and in that
select “Application Pool” and click on the button beside it which opens another window listing all the Application
Pools that are available in a DropDownList, select “MyPool” and click Ok and Ok again.

The IIS Worker Process is a Windows Process (w3wp.exe) which runs Web Applications and is responsible
for handling requests sent to a Web Server for a specific Application Pool. Each Application Pool creates at least 1
instance of w3wp.exe and that is responsible for processing ASP.NET application request and sending back response
to the client. All ASP.NET functionalities run within the scope of this Worker Process.

We can view the “IIS Worker Process” that is associated with each Application Pool under “Task Manager”
which displays a separate “IIS Worker Process” for each Application Pool. To get the exact details go to “Details
Section” in the Task Manager and there we find “w3wp.exe” and beside that it will display the Application Pool to
which this Worker Process is associated.

Note: in In-Proc session mode Session values are stored under the Memory that is associated with IIS Worker
Process, who runs our Web Application. So, in this case if we recycle the IIS Worker Process all the Session Values
that are stored under this will be destroyed and to test this, open “Task Manager” identify the “IIS Worker Process”
under which our Web Application is running, select it and click on “End Task” button which will destroy all the session
values associated with that application.

State Server: this is separate software for storing “Session Values” which is installed when we install .NET Runtime
on any machine, and it can be found in the “Services Window”. To see that go to Control Panel => Administrative
Tools => Services and in that we find “ASP.NET State Service”. To use this, first we need to set “mode” attribute of
<sessionState> element in the “Web.config” file and “mode” attribute accepts any of the following values like: Off,
In-Proc [d], SQL Server and State Server.

Note: default is In-Proc i.e., Sessions are stored under IIS Worker Process Memory, if set as off application will not
maintain Sessions at all and if set as State Server then Session values are stored under ASP.NET State Service.

To use State Service for storing Session values we need to do the following:
Step 1: Open Windows Services console, right click on ASP.NET State Service and select Start to start the service.

125
Step 2: Now open Web.config file and write the sessionState tag as following:
<sessionState mode="StateServer" stateConnectionString="tcpip=localhost:42424" />

Note: “localhost” refers to the machine name and if ASP.NET State Service software is running on a remote machine
then write that machine name in place of localhost and 42424 is the Port No. on which ASP.NET State Server software
will be running.

SQL Server: if “Session Mode” is set as SQL Server then Session values are stored under SQL Server Database and to
use that we need to create a Database, a set of Tables and Stored Procedures. Without creating all these objects
manually, we are provided with a command line tool called as “aspnet_regsql” that should be used from “Visual
Studio Developer Command Prompt” as below:

Step 1: run the “aspnet_regsql” tool at “VS Developer Command Prompt”, so that the required Database, Tables
and Stored Procedure for maintaining Sessions will be created under SQL Server.

aspnet_regsql -? => Help


aspnet_regsql -S <Server Name> -U <User Id> -P <Password> -E < In-case of Windows Auth> -ssadd -sstype t|p|c

-S: to specify SQL Server name.


-U: to specify User Id in case of SQL Authentication.
-P: to specify password in case of SQL Authentication.
-E: this must be used in case of Windows Authentication and in such case don’t use -U and -P option again.
-ssadd: is to enable support for SQL Server Session State and this will create a Database on the server.

Note: If we want to remove the support for session state we need to use -ssremove in place -ssadd.

-sstype: is to specify the type of tables we want to use where “t” indicates temporary tables, “p” indicates persisted
tables and “c” indicates custom - but in this case we need to create our own Database to store Session data, and to
specify that Database name we need to use “-d <Database Name>” option in the last.

Testing the processes of using “aspnet_regsql”:


For SQL Server Authentication: aspnet_regsql -S Server -U Sa -P 123 -ssadd -sstype t
For Windows Authentication: aspnet_regsql -S Server -E -ssadd -sstype t

Note: in the above case we are using temporary tables for storing Session State values, so a new Database is created
on the Server with the name “ASPState” and under this Database it creates a set of Stored Procedures for managing
the data and because we have asked for temporary tables, all the required tables gets created on “TempDB - System
Database” and this Database will be re-created every time we re-start SQL - Server, whereas if we ask for persisted
tables then all the required tables also gets created on “ASPState” Database only, so even if we re-start SQL Server,
then also tables and their values will be persisting.

Step 2: Now open Web.config file and re-write the <sessionState> tag as below:
Sql Server Authentication:
<sessionState mode="SQLServer" sqlConnectionString="Data Source=Server;User Id=Sa;Password=123" />
Windows Authentication:
<sessionState mode="SQLServer" sqlConnectionString="Data Source=Server;Integrated Security=SSPI" />

126
Testing the processes of using “aspnet_regsql” with permenant table support:
For SQL Server Authentication: aspnet_regsql -S Server -U Sa -P 123 -ssadd -sstype p
For Windows Authentication: aspnet_regsql -S Server -E -ssadd -sstype p

Testing the processes of using “aspnet_regsql” with custom Database and permenant table support:
For SQL Server Authentication: aspnet_regsql -S Server -U Sa -P 123 -ssadd -sstype c -d MySessions
For Windows Authentication: aspnet_regsql -S Server -E -ssadd -sstype c -d MySessions

In this case we are using Custom Database then we need to specify the Database name in our
sqlConnectionString and also we need to use allowCustomSqlDatabase attribute with the value as true as below:

Sql Server Authentication: <sessionState mode="SQLServer" allowCustomSqlDatabase="true"


sqlConnectionString="Data Source=Server;User Id=Sa;Password=123;Database=MySessions" />
Windows Authentication: <sessionState mode="SQLServer" allowCustomSqlDatabase="true"
sqlConnectionString="Data Source=Server; Integrated Security=SSPI;Database=MySessions" />

Removing support for Sql Server Session State:


For SQL Server Authentication: aspnet_regsql -S Server -U sa -P 123 -ssremove
For Windows Authentication: aspnet_regsql -S Server -E -ssremove

When to use State Server and SQL Server Session Modes over In-Proc Session Mode?
Ans: State Server and SQL Server session mode options are used in scenarios where a Web Application is running in
“Web Farm” or “Web Garden” architectures.

Web Farm: it's an approach of hosting a Web Application on multiple Web Servers for balancing the load, so that
client request first comes to Load Balancer and Load Balancer will in-turn redirect the client to an appropriate Web
Server which is free currently. In case of Web Farm architecture “In-Proc” Session Mode can’t be used because if
each request from the same client is re-directed to a different Web Servers, then Session Data of 1 Web Server is
not accessible to other Web Servers, so to overcome this problem we install “State Server” or “SQL Server” software
on a remote machine and configure all the Web Servers to that machine as following:

State Server or SQL Server

Web Garden: as discussed earlier every Application Pool under which our Web Application executes will be having
1 Worker Process to execute that Application, but we can have more than 1 Worker Process also in an Application
Pool and if we have that, we call it as Web Garden.

127
To add Worker Processes to an Application Pool right click on the Application Pool in “IIS Manager”, select
“Advanced Settings” which opens a window and, in that window, under the “Process Model” settings we find
“Maximum Worker Processes” with the value 1, change it to any value other than 1 and click Ok.

Application: this is a global storage mechanism that is used to store data on the server which is shared between all
users i.e., data stored in Application Memory is accessible to all users and anywhere in the application (Multi-User
Global Data). Application-State is stored in the memory of the Web Server and is faster than storing and retrieving
information from a Database. Application is used in the same way as Session, but Session is specific for a single user,
whereas Application is common for all users of the application.

Application does not have any default expiration period like Session, so when we re-cycle the Worker
Process or re-start the Web Server only the data in application memory will be lost. Data is stored into Application
in the form of name/value pairs only like we store in Session, ViewData or TempData. We store data into Application
by using “Application” property of “HttpContext” class that is defined in “System.Web” namespace.

Note: Application Memory is not Thread-Safe, so to overcome the problem whenever we are dealing with
Application-State data we need to call Lock() and UnLock() methods on Application object.

Storing values into Application:


Syntax: HttpContext.Application[string key] = value (object)
Example: HttpContext.Application["Name"] = "Raju";

Accessing values from Application:


Syntax: object value = HttpContext.Application[string key]
Example: object value = HttpContext.Application["Name"];
string Name = value.ToString();
Or
string Name = HttpContext.Application["Name"].ToString();

public ViewResult Index11(int? id, string name, double? price) {


HttpContext.Application.Lock();
HttpContext.Application["Id"] = id;
HttpContext.Application["Name"] = name;
HttpContext.Application["Price"] = price;
HttpContext.Application.UnLock();
return View();
}
public ViewResult Index12() {
return View();
}

128
Now add a View to “Index11” Action method and write the below code under its “<div>” tag:
<table border="1" align="center" width="20%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@HttpContext.Current.Application["Id"]</td></tr>
<tr><td>Name:</td><td>@HttpContext.Current.Application["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(HttpContext.Current.Application["Price"]);
Price = Price + Price * 10 / 100;
@Price
}
</td>
</tr>
</table>
<center>Click to launch new <a href="/MVCDataTransfer/Home/Index12">Page</a>.</center>

Execute Index11 Action Method of Home Controller as following:


http://localhost/MVCDataTransfer /Home/Index11/105/Shoes/3500

In the above case when we call Index11 action method, will launch the associated View and displays the
values that are stored in the Application Memory and when we click on the Link in the bottom will call Index12 action
method of the same controller which will also display the values that stored in Application Memory and to test that
add a View for Index12 action method and write the below code in it under the “<div>” tag:

<table border="1" align="center" width="20%">


<caption>Product Details</caption>
<tr><td>Id:</td><td>@HttpContext.Current.Application["Id"]</td></tr>
<tr><td>Name:</td><td>@HttpContext.Current.Application["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(HttpContext.Current.Application["Price"]);
Price = Price + Price * 10 / 100;
@Price
}
</td>
</tr>
</table>
<center>Click to launch new <a href="/MVCDataTransfer/Test/Index4">Page</a>.</center>

When we click on the Link in above View, will launch Index4 action method of TestController and here also
it displays the values that are stored in Application and to test it add a new action method in TestController class as
below:

129
public ViewResult Index4()
{
return View();
}

Add a View to the above Index4 action method and write the below code under it’s “<div>” tag:
<table border="1" align="center" width="20%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@HttpContext.Current.Application["Id"]</td></tr>
<tr><td>Name:</td><td>@HttpContext.Current.Application["Name"]</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double Price = Convert.ToDouble(HttpContext.Current.Application["Price"]);
Price = Price + Price * 10 / 100;
@Price
}
</td>
</tr>
</table>

Flow of control: Request sent to => “Index11” Action method of “HomeController” => when the hyper link is clicked
on page, it is redirect to => “Index12” Action method of “HomeController” => when the hyper link is clicked on this
page, it is redirect to => “Index4” Action method of “TestController”.

Anonymous Types: This is another mechanism using which we can transfer values from Action method to View or
Action method to Action method within the same Controller or another Controller also, without using ViewData,
ViewBag, TempData and Session. An anonymous type is a type (class) without a name that contains a set of read
only properties, for which we can directly create the instance by using “new” keyword.

For example if we define a class as below:


public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Job { get; set; }
public double Salary { get; set; }
public bool Status { get; set; }
}

We can create instance of the above class as following:


Employee Emp = new Employee { Id = 1001, Name = "Raju", Job = "Manager", Salary = 50000.00, Status = true };

In the above case we are creating the instance of “Employee” class which is defined first and then initializing
the attributes (Id, Name, Job, Salary, and Status) that are associated with it, so now the instance “Emp” contains all

130
attribute values in it. Without explicitly defining a class/type also, we can create an instance for a type and initialize
it as following:
var Emp = new { Id = 1001, Name = "Raju", Job = "Manager", Salary = 50000.00, Status = true };
dynamic Emp = new { Id = 1001, Name = "Raju", Job = "Manager", Salary = 50000.00, Status = true };

In the above case also instance “Emp” is an instance containing all the attribute values in it same as in the
first scenario, but the difference is in the first case we defined the class first and then created the instance whereas
in the second case we created the instance without defining the class/type and we call this “Anonymous Type”.

Anonymous type (introduced in C# 3.0), as the name suggests, is a type that doesn’t have any name. C#
allows you to create an instance with the new keyword without defining a class. The implicitly typed variable - “var”
or “dynamic” is used to hold the reference of anonymous types. In the above example, “Emp” is an instance of the
anonymous type which is created by using the new keyword and object initializer syntax. It includes 5 properties of
different data types. An anonymous type is a temporary type that is inferred based on the data that you include in
an object initializer. Properties of anonymous types will be read-only properties so you cannot change their values.

Notice that the compiler applies the appropriate type to each property based on the value assigned. For
example, Id is of integer type, Name and Job are of string type, Salary is of double type and Status is of Boolean type.
Internally, the compiler automatically generates the new type for every anonymous type. You can check that by
calling GetType() method on an anonymous type instance which will return the following value:
<>f__AnonymousType0`5[System.Int32,System.String,System.String,System.Double,System.Boolean]

By using these anonymous types also, we can transfer values from an Action method to its corresponding
View or an Action method to another Action method that is present in the same Controller or other Controller.

Define a new Action method in Home Controller as below:


public ViewResult Index13(int? id, string name, double? price)
{
var Product = new { Id = id, Name = name, Price = price };
return View(Product);
}
Add a View to the above Action method and write the below code under its “<div>” tag:
@{
int? Id = Convert.ToInt32(ViewData.Eval("Id"));
string Name = ViewData.Eval("Name").ToString();
double? Price = ViewData.Eval("Price") as double?;
}

<table border="1" align="center" width="15%">


<caption>Product Details</caption>
<tr><td>Id:</td><td>@Id</td></tr>
<tr><td>Name:</td><td>@Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{

131
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

In the above case while accessing values from an anonymous type in the View, we need to first capture
those values from ViewData i.e., even if we did not explicitly store the values in ViewData, they are implicitly stored
into ViewData and accessible under the View.

While accessing the values from ViewData we require calling “Eval” method on ViewData, because the
values are stored in the form of an “instance or object (Complex type)” and under that instance or object we have
all the 3 values which should be separated first and then consumed.

Execute Index13 Action Method of Home Controller as following:


http://localhost/MVCDataTransfer/Home/Index13/105/Shoes/3500

Now define another new Action method in Home Controller as below:


public RedirectToRouteResult Index14(int? id, string name, double? price)
{
var product = new { Id = id, Name = name, Price = price };
return RedirectToAction("Index5", "Test", product);
}

Define a new Action method in “TestController” as below:


public ViewResult Index5(int? id, string name, double? price)
{
var product = new { Id = id, Name = name, Price = price };
return View(product);
}
Add a View to Index5 Action method and write the below code in its “<div>” tag:
@{
int? Id = Convert.ToInt32(ViewData.Eval("Id"));
string Name = ViewData.Eval("Name").ToString();
double? Price = ViewData.Eval("Price") as double?;
}

<table border="1" align="center" width="15%">


<caption>Product Details</caption>
<tr><td>Id:</td><td>@Id</td></tr>
<tr><td>Name:</td><td>@Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{

132
Price = Price + (Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Execute Index14 Action Method of Home Controller as following:


http://localhost/MVCDataTransfer/Home/Index14/105/Shoes/3500

Now URL in the address bar will change as following:


http://localhost/MVCDataTransfer/Test/Index5/105/Shoes/3500

Flow of control: Request sent to => Index14 action method of HomeController => Redirected to => Index5 action
method of TestController and in this process all the 3 values are sent to Index5 action method as Route Parameters,
as shown above.

Model Object: this is another way how we can transfer data from Controller to the View, which provides “type
safety” and “intellisense” support in Views, so by using this also we can transfer values from Action method to
corresponding View or Action method to Action method of same Controller or other Controllers. To test this, first
add a class in the project under “Models” folder naming the class as “Product” and write the below code in it:

public class Product


{
public int? Id { get; set; }
public string Name { get; set; }
public double? Price { get; set; }
}
Now import the namespace “MVCDataTransfer.Models” in “HomeController” class and define a new action
method as below:
public ViewResult Index15(int? id, string name, double? price)
{
Product product = new Product { Id = id, Name = name, Price = price };
return View(product);
}

In the above action method, we can write code in any of these ways:
Product product = new Product { Id = id, Name = name, Price = price };
return View(product);
Or
var product = new Product { Id = id, Name = name, Price = price };
return View(product);
Or
dynamic product = new Product { Id = id, Name = name, Price = price };
return View(product);
Or
return View(new Product { Id = id, Name = name, Price = price });

133
Add a View to “Index15” Action method and write the below code:
@*Write the below statement at top of the View *@
@model MVCDataTransfer.Models.Product

@*Write this code under the <div> tag:*@


<table border="1" align="center" width="15%">
<caption>Product Details</caption>
<tr><td>Id:</td><td>@Model.Id</td></tr>
<tr><td>Name:</td><td>@Model.Name</td></tr>
<tr>
<td>Price:</td>
<td>
@{
double? Price = Model.Price + (Model.Price * 10 / 100);
@Price
}
</td>
</tr>
</table>

Note: in this case on top of the View we need to first import the model object by using “@model” directive, so that
we can access the member of the Product class by using “@Model” Property.

Execute “Index15” Action Method as following:


http://localhost/MVCDataTransfer/Home/Index15/105/Shoes/3500

In the above “Index15” action method without reading each parameter value individually we can directly
read it thru the Model class, by using Model class as method parameter.

To test that let’s now add another Action method in “HomeController” class as following:
public RedirectToRouteResult Index16(Product product)
{
return RedirectToAction("Index6", "Test", product);
}

Add a new Action method in “Test Controller” class as following:


public ViewResult Index6(Product product)
{
return View(product);
}

Note: now add a View to Index6 Action method of Test Controller and write code same as we written in Index15
Action method of Home Controller.

Execute Index16 Action Method as following:


http://localhost:MVCDataTransfer/Home/Index16/105/Shoes/3500

134
Now URL in the address bar will change as following:
http://localhost/MVCDataTransfer/Test/Index6/105/Shoes/3500

Flow of control: Request sent to => Index16 action method of HomeController => Redirected to => Index6 action
method of TestController and in this process all the 3 values are sent to Index6 action method as Route Parameters,
as shown above.

State Management: Web Applications are stateless i.e., we can never access the values of 1 request, in the next
request of the same page or other pages also. But sometimes we may need the values of 1 request, in the next
request to same page or other pages and to overcome this problem and maintain the state of values between
multiple requests to the same page or between different pages we are provided with the concept called as State
Management.

In ASP.NET to maintain the state of values we are provided with various techniques like:
 Query String
 Hidden Fiels
 Anonymous Types
 Model
 TempData
 Cookie
 Session
 Application

135
UI Designing
We design user interfaces in any application for taking input from end users or displaying the results.
Designing of a user interface in Web Applications is performed with HTML, which provides with a set of controls.
Whereas in ASP.NET MVC we call user interface as View, and we design them by using any of the below options:

1. Using Html Controls


2. Using Html Helpers
3. Using Strongly Typed Html Helpers

To test these, create a new “ASP.NET Web Application” project naming it as “MVCUIDesigning”, choose
“Empty Project Template”, check the “MVC” Checkbox and click on “Create” button to create the project.

Designing a View (UI) by using HTML Controls: Add a Controller into the Controllers folder naming it as
“EmpController”, delete all the existing code in the class and write the below code:

[HttpGet]
public ViewResult AddEmp()
{
return View();
}
[HttpPost]
public ViewResult AddEmp(int? id, string name, string job, double? salary)
{
ViewData["Id"] = id;
ViewData["Name"] = name;
ViewData["Job"] = job;
ViewData["Salary"] = salary;
return View("DisplayEmp1");
}

Add a view to “AddEmp” action method and write the below code in its “<div>” tag:
<form method="post">
Enter Employee Id: <br />
<input type="text" name="Id" id="Id" /> <br />
Enter Employee Name: <br />
<input type="text" name="Name" id="Name" /> <br />
Enter Employee Job: <br />
<input type="text" name="Job" id="Job" /> <br />
Enter Employee Salary: <br />
<input type="text" name="Salary" id="Salary" /> <br /><br />
<input type="submit" value="Save" />
<input type="reset" value="Reset" />
</form>

Add another view in “Emp” folder of “Views” folder with the name “DisplayEmp1” and write the below
code in its “<div>” tag:

136
<table border="1" align="center">
<caption>Employee Details</caption>
<tr><td>Employee Id:</td><td>@ViewBag.Id</td></tr>
<tr><td>Employee Name:</td><td>@ViewBag.Name</td></tr>
<tr><td>Employee Job:</td><td>@ViewBag.Job</td></tr>
<tr><td>Employee Salary:</td><td>@ViewBag.Salary</td></tr>
<tr>
<td colspan="2" align="center"><a href="/Emp/AddEmp">Add a new Employee</a></td>
</tr>
</table>

Flow of Control => Call AddEmp => Invokes Get Action method of EmpController which will launch AddEmp View =>
on click of “Save” button it will invoke AddEmp - Post Action method and launches DisplayEmp1 View.

Execute “AddEmp” Action method of “EmpController” as following:


http://localhost:port/Emp/AddEmp

Note: in this example, Action method “Parameter Names” are exactly matching with “Control Names” on the View,
so the values entered in the Controls will directly come into those Parameters. But the drawback in this approach is
when there are multiple Controls on the View, there should also be multiple Parameters defined to the Action
method to read all those Control Values, so the Parameter List will be lengthy and code gets complex, to overcome
this problem of reading each Control Value thru an individual Parameter we can use “FormCollection” class as Action
method parameter, and read values of each Control present on the Form.

To test this, re-write the “AddEmp” Post Action method as below:


[HttpPost]
public ViewResult AddEmp(FormCollection fc)
{
ViewData["Id"] = fc["id"];
ViewData["Name"] = fc["name"];
ViewData["Job"] = fc["job"];
ViewData["Salary"] = fc["salary"];
return View("DisplayEmp1");
}

Execute “AddEmp” Action method of “EmpController” as following:


https://localhost:port/Emp/AddEmp

Note: without reading each controls value thru “FormCollection” we can use “Model Binding” and capture all the
values at a time in the View and pass them to another View for displaying, which provides type safety, name
resolution and intellisense support also.

To test this, add a new class under the Models folder with the name “Employee” and write the below code in it:
public class Employee
{
public int? Id { get; set; }

137
public string Name { get; set; }
public string Job { get; set; }
public double? Salary { get; set; }
}

Now go to “EmpController” class and re-write the “AddEmp – Post Action” method as following by
importing “MVCUIDesigning.Models” namespace.

[HttpPost]
public ViewResult AddEmp(Employee Emp)
{
return View("DisplayEmp2", Emp);
}

Add another view with the name “DisplayEmp2” and write the below code in it:
@*Write the below statement at top of the View *@
@model MVCUIDesigning.Models.Employee

@*Write this code under the <div> tag:*@


<table border="1" align="center">
<caption>Employee Details</caption>
<tr><td>Employee Id:</td><td>@Model.Id</td></tr>
<tr><td>Employee Name:</td><td>@Model.Name</td></tr>
<tr><td>Employee Job:</td><td>@Model.Job</td></tr>
<tr><td>Employee Salary:</td><td>@Model.Salary</td></tr>
<tr><td colspan="2" align="center"><a href="/Emp/AddEmp">Add a new Employee</a></td></tr>
</table>

Run “AddEmp” Action method of “EmpController” with the following URL:


https://localhost:port/Emp/AddEmp

Flow of Control => Call AddEmp => Invokes Get Action method of EmpController which will launch AddEmp View =>
on click of “Save” button it will invoke AddEmp - Post Action method and launches DisplayEmp2 View.

Designing a View (UI) by using HTML Helpers: we are all aware that in Web Applications we design User Interfaces
with the help of HTML Controls, and to simplify UI designing process, MVC provides us “HTML Helper Methods” and
these methods will generate or render required “HTML Code” i.e., the return type of these methods is a string and
that produces required HTML. These helper methods are equivalent to “ASP.NET Server Controls” that we used in
“ASP.NET Web Forms”.

Working with Html Helper Methods:


Syntax: @Html.TextBox(string name) => MvcHtmlString (Return Type)
Example: @Html.TextBox("Id") => <input type="text" id="Id" name="Id" value="" />

In the above case “@Html” is an instance of class “System.Web.Mvc.HtmlHelper” and this class will
generate the required HTML and returns it in the form of a MvcHtmlstring when we call methods of the class, and
these methods are called as “HTML Helper Methods” and all of them are “Extension Methods”.

138
Methods of the “HtmlHelper” class:
 BeginForm
 EndForm
 ActionLink
 CheckBox
 DropDownList
 Hidden
 ListBox
 Password
 RadioButton
 Label
 TextBox
 TextArea
 Display
 Editor

Creating a “Form” using Html Helper Methods:


BeginForm()
BeginForm(string actionname, string controllername)
BeginForm(string actionname, string controllername, object routevalues)
BeginForm(string actionname, string controllername, FormMethod method)
BeginForm(string actionname, string controllername, object routevalues, FormMethod method)

@{
Html.BeginForm();
-Place all controls here
Html.EndForm();
}
Or
@using(Html.BeginForm())
{
-Place all controls here
}

Creating a Label:
@Html.Label(string value)
@Html.Label(string name, string value)
@Html.Label(string name, string value, object HtmlAttributes)

Creating a TextBox:
@Html.TextBox(string name)
@Html.TextBox(string name, object default)
@Html.TextBox(string name, object default, object HtmlAttributes)

Creating a Password:
@Html.Password(string name)

139
@Html.Password(string name, string default)
@Html.Password(string name, string default, object HtmlAttributes)

To work with “Html Helpers” add a new Controller under “MVCUIDesigning” project naming it as
“AccountController”, delete the existing code in the class and write the below code over there:

public ViewResult Login()


{
return View();
}
public ViewResult Validate()
{
string Name = Request["txtName"];
string Password = Request["txtPwd"];
if (Name == "Admin" && Password == "Admin@123")
{
Session["Name"] = Name;
return View("Success");
}
else
{
ViewBag.Name = Name;
return View("Failure");
}
}

Add 3 Views under “Account” folder which is present under “Views” folder naming them as “Login.cshtml”,
“Success.cshtml” and “Failure.cshtml” and write code under them.

Note: if we want to use Bootstrap for styling of HTML in Views, we need to install Bootstrap in our projects, and this
can be done in 2 different ways i.e., either by using “NuGet Package Manager” or “Library Manager”.

What is NuGet?
Ans: NuGet can be used to find and install packages, i.e., software libraries, assemblies, and any other things that
you want to use in your project. NuGet is not a tool that is specific to “ASP.NET MVC” projects. This is a tool that you
can use inside of “Visual Studio” for “Console Applications”, “Windows Applications”, “WPF Applications” and any
other type of Application. NuGet is a Package Manager, and is responsible for downloading, installing, updating, and
configuring software in your project. From the term software we don’t mean end users software like Microsoft Word
or Notepad, etc. but any pieces of software, which you want to use in our project i.e., “Assembly” references.

NuGet Package Manager: this is an option which provides an interface to search for the libraries that can be used in
our project, which also helps in installing those libraries in our projects and consume. To use this, go to Tools Menu
=> Select the Menu Item, “NuGet Package Manager” and under that select the Sub Menu Item, “Manage NuGet
Packages for Solution” and this will launch a new window, choose “Browse” option on the top and search for
“Bootstrap”, which displays various “Bootstrap” libraries that are available, select “bootstrap”, “by The Bootstrap
Authors, Twitter Inc.,” and then in the RHS select the “Checkbox” that displays our “Project Name” and then the

140
“Install” button is enabled, click on it, which will install the required “Bootstrap” files into our application by creating
a set of folders under the project with the name “Content” and “Scripts”.

Library Manager: this option was newly added from “Visual Studio 2017” for managing all the client-side libraries
and to use this open Solution Explorer, right-click on the Project and choose Add => “Client-Side Library” which will
launch “Add Client-Side Library” dialog and in that fill the below details:
 Provider: cdnjs (default)
 Library: [email protected]
 Select Include all library files radio button.
 Target Location: Content/Bootstrap

Click “Install” button and this will install “Bootstrap” in our project under the specified folder, and this action
will add a file in the project with a name “libman.json” and under this file the details of all the libraries installed will
be present as following:

{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "[email protected]",
"destination": "Content/Bootstrap"
}
]
}

Note: same as the above we can also install any other libraries like jQuery, Ajax, etc. into our projects by using the
above 2 tools.

To use bootstrap in “Login.cshtml”, drag and drop “bootstrap.min.css” file from “Content” folder in to the
“<head>” section and then write the below code under the “<div>” tag:

@using (Html.BeginForm("Validate", "Account"))


{
@Html.Label("User Name:", new { @class = "text-info" });<br />
@Html.TextBox("txtName", "", new { placeholder = "Enter Name" });<br /><br />
@Html.Label("Password:", new { @class = "text-info" });<br />
@Html.Password("txtPwd", "", new { placeholder = "Enter Password" });<br /><br />
<input type="submit" value="Login" class="btn btn-success" />
<input type="reset" value="Reset" class="btn btn-success" />
}

Success.cshtml: write the below code under its “<div>” tag.


<h4>Hello @Session["Name"], welcome to the site.</h4>

Failure.cshtml: write the below code under its “<div>” tag.


<h4>Hello @ViewData["Name"], your given credentials are invalid.</h4>

141
Execute Login Action method of “HomeController” using the below URL:
https://localhost:port/Account/Login

This will launch “Login.cshtml” View, to enter user credentials and when we fill the credentials and click on
“Login” button it will launch “Success.cshtml” View, if the credentials are valid or else “Failure.cshtml” View, if the
credentials are invalid.

Designing Views using “Html Helpers” and reading Form values using Models:

Step 1: Add a new class in Models folder of “MVCUIDesigning” project, naming it as “Student” and write the below
code in it:

public class Student


{
public int Sid { get; set; }
public string Name { get; set; }
public int Class { get; set; }
public string Gender { get; set; }
public double Fees { get; set; }
public string Address { get; set; }
}

Step 2: Add a new Controller in the Controllers folder naming it as “StudentController”, delete all the existing content
of the class and write the below code over there by importing “MVCUIDesigning.Models” namespace for working
with “Student” class:

[HttpGet]
public ViewResult AddStudent()
{
return View();
}

[HttpPost]
public ViewResult AddStudent(Student student)
{
return View("DisplayStudent", student);
}

Step 3: Add a View for “AddStudent” action method and write the below code in it:

@*Write this code under the <div> tag:*@


@using (Html.BeginForm())
{
@Html.Label("Student Id: ") <br />
@Html.TextBox("Sid") <br />
@Html.Label("Name: ") <br />

142
@Html.TextBox("Name") <br />
@Html.Label("Class: ")
List<int> li = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
SelectList items = new SelectList(li);
@Html.DropDownList("Class", items, "-Select Class-") <br />
@Html.Label("Gender: ")
@Html.RadioButton("Gender", "Male") @:Male
@Html.RadioButton("Gender", "Female") @:Female <br />
@Html.Label("Fees: ") <br />
@Html.TextBox("Fees") <br />
@Html.Label("Address: ") <br />
@Html.TextArea("Address", "", 3, 21, new { })
<br /><br />
<input type="submit" value="Save" />
<input type="reset" value="Reset" />
}

Step 4: Add a new View with the name “DisplayStudent” under “Student” folder of “Views” folder and write the
below code in it:

@*Write the below statement at top of the View *@


@model MVCUIDesigning.Models.Student
@*Write this code under the <div> tag:*@
<h4>Student Details</h4>
<ul>
<li>Student Id: @Model.Sid</li>
<li>Student Name: @Model.Name</li>
<li>Student Class: @Model.Class</li>
<li>Student Gender: @Model.Gender</li>
<li>Student Fees: @Model.Fees</li>
<li>Student Address: @Model.Address</li>
</ul>

Execute “AddStudent” Action method of “StudentController” using the below URL:


https://localhost:port/Student/AddStudent

This will launch “AddStudent” view to enter details for a new “Student” and when we fill the Form and click
on the “Save” button, will launch “DisplayStudent.cshtml” View to display the details which the user has entered in
the Form.

Strongly Typed Html Helpers: In the above program when we are reading the form values by using Model Object in
“Post” action method we have a problem, i.e., Control Name should exactly be same as the Property Name of Model
class. For example, if the Property Name is “Sid” in Model Class then Control Name also should be “Sid” only and if
we give this as wrong, we don’t get any compile time or run-time errors, but that controls value will not be read into
the Model’s Property, and also intellisense will not help us, to identify the Model Property - Name. To overcome this
problem, in “MVC 2.0” we are provided with “Strongly Typed - Html Helper” and these Helpers purely depends on

143
Model Classes, so while designing the UI’s we don’t require to give any name to Control’s. Strongly Typed - Html
Helpers are also same as Html Helpers we have used till now, but the only difference is, here every Helper method
is suffixed with “For”, for example:

Html Helpers Strongly Typed Html Helpers


Label LabelFor
Hidden HiddenFor
ListBox ListBoxFor
TextBox TextBoxFor
TextArea TextAreaFor
Password PasswordFor
CheckBox CheckBoxFor
RadioButton RadioButtonFor
DropDownList DropDownListFor
Editor EditorFor
Display DisplayFor
DisplayName DisplayNameFor

To work with Strongly Typed Html Helpers add 2 new action methods in the “StudentController” as following:
[HttpGet]
public ViewResult AddStudentST()
{
return View();
}

[HttpPost]
public ViewResult AddStudentST(Student student)
{
return View("DisplayStudentST", student);
}

Add a View to “AddStudentST” Action method and write the below code in its “<div>” tag:
@*Write the below statement at top of the View *@
@model MVCUIDesigning.Models.Student

@*Write this code under the <div> tag:*@


@using (Html.BeginForm())
{
@Html.Label("Student Id: "); <br />
@Html.TextBoxFor(S => S.Sid); <br />
@Html.Label("Student Name: "); <br />
@Html.TextBoxFor(S => S.Name); <br />
@Html.Label("Student Class: ");
List<int> li = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
SelectList items = new SelectList(li);
@Html.DropDownListFor(S => S.Class, items, "-Select Class-"); <br />

144
@Html.Label("Student Gender: ");
@Html.RadioButtonFor(S => S.Gender, "Male")@:Male
@Html.RadioButtonFor(S => S.Gender, "Female")@:Female
@Html.RadioButtonFor(S => S.Gender, "Transgender")@:Transgender <br />
@Html.Label("Annual Fees: "); <br />
@Html.TextBoxFor(S => S.Fees); <br />
@Html.Label("Student Address: "); <br />
@Html.TextAreaFor(S => S.Address, 3, 21, new { });
<br /><br />
<input type="submit" value="Save" />
<input type="reset" value="Reset" />
}

Add a new View with the name “DisplayStudentST” under “Student” folder of “Views” folder and write the
below code in it:

@*Write the below statement at top of the View *@


@model MVCUIDesigning.Models.Student

@*Write this code under the <div> tag:*@


<h4>Student Details</h4>
<ul>
<li>@Html.DisplayNameFor(S => S.Sid): @Html.DisplayFor(S => S.Sid)</li>
<li>@Html.DisplayNameFor(S => S.Name): @Html.DisplayFor(S => S.Name)</li>
<li>@Html.DisplayNameFor(S => S.Class): @Html.DisplayFor(S => S.Class)</li>
<li>@Html.DisplayNameFor(S => S.Gender): @Html.DisplayFor(S => S.Gender)</li>
<li>@Html.DisplayNameFor(S => S.Fees): @Html.DisplayFor(S => S.Fees)</li>
<li>@Html.DisplayNameFor(S => S.Address): @Html.DisplayFor(S => S.Address)</li>
</ul>

Execute “AddStudentST” Action method of “StudentController” using the below URL:


https://localhost:port/Student/AddStudentST

This will launch “AddStudentST” View to enter details for a new “Student”, when we fill the Form and click
on “Save” button, it will launch “DisplayStudentST.cshtml” view to display the details which the user has entered in
the Form.

Note: In “DisplayStudentST.cshtml” we have used DisplayNameFor helper method which will get the
Model Property - Name over there and DisplayFor helper method will get the Model Property - Value over
there.

145
Partial Views
A Partial View is also a View, but this can be used in other Views, i.e., they provide re-usability. Creating a
Partial View is also just like creating a normal View and the extension of the Partial View also will be “.cshtml” only,
but in a Partial View we don’t have any HTML tag’s like “<head>” and “<body>” by default. Partial Views are generally
stored in the “Shared” folder of “Views” folder because they are consumed by multiple Views in the application, and
it is suggested (optional) to prefix Partial View names with “underscore (_)” to differentiate them from other Views.

To work with Partial Views in our existing project i.e., “MVCUIDesigning” add a new folder with the name
“Shared” in the “Views” folder and add another folder under the project with the name “Images”, copy an image
into that folder and rename the image as “Header”.

Now right click on the Shared folder select “Add” => “View”, name it as “_Header” and check the “Create
as a Partial View” Checkbox which will disable all the other Checkbox’s on the window, and then click on “Add”
button. This action will create a blank “.cshtml” file, write the below code in it:

<div style="color:darksalmon;text-align:center;height:150px;background-color:azure;border-style:dotted;
border-color:slateblue;border-width:thick; box-shadow: 0px 0px 50px inset">
<img id="imgNaresh" alt="www.nareshit.com" src="~/Images/Header.png" width="96%" height="80%" />
<marquee style="font-size:x-large;color:crimson;" behavior="alternate">
.NET, Java, Python, Hadoop, Data Science, DevOps, etc.
</marquee>
</div>

Consuming a Partial View: after creating the Partial View, we can consume it in any of our Views by calling the below
3 methods of “HtmlHelper” class:
 @Html.Partial(string PartialViewName) => MvcHtmlString
 @{ Html.RenderPartial(string PartialViewName); } => void
 @{ Html.RenderAction(string ActionMethodName); } => void

The first option of calling the method “Partial” returns an “MVCHtmlString” and we can call this method in
any of our View Pages. Because this method returns an MVCHtmlString back there is a chance to manipulate the
content of the Partial View in the future within our View Pages.

The second option of calling the method “RenderPartial” can also be done in our View Pages, and this is a
preferred option because its return type is void and there is no chance to manipulate the Partial View i.e., it can be
used as is only.

Third option is also non-modifiable, but to use this we again need to define a new Action method under any
Controller class because in this case we call the Action method in our View Page but not Partial View.

Html.Partial: to test this, open “AddStudent.cshtml” View of “StudentController” and write the below code in its
“<body>” section just above the “<div>” tag:
@Html.Partial("_Header")

Note: as said above we can manipulate the content of the Partial View in this case, and to test that go to
“DisplayStudent.cshtml” view of “StudentController” and write the below code in its “<body>” section just above
the “<div>” tag:

146
@{
String strHeader = Html.Partial("_Header").ToString();
strHeader = strHeader.Replace("150", "200");
strHeader = strHeader.Replace("azure", "aquamarine");
MvcHtmlString htmlString = new MvcHtmlString(strHeader);
@htmlString
}

In the above case “width” of “<div>” is increased from 150 pixels to 200 pixels and the “background-color”
of “<div>” is changed from azure to aquamarine, and in the same way we can manipulate anything with-in the
Partial View.

Html.RenderPartial: to test this, open “AddStudentST.cshtml” View of “StudentController” and write the below code
in its “<body>” section just above the “<div>” tag:
@{ Html.RenderPartial("_Header"); }

Html.RenderAction: in this case we can’t directly call the “PartialView”, but what we need to call is Action method
which will in-turn call the “PartialView”. To test this, go to “StudentController” and define a new Action method in
it as below:
public PartialViewResult Header()
{
return PartialView("_Header");
}

Now go to “DisplayStudentST.cshtml” view of “StudentController” and write the below code in the
“<body>” section just above the “<div>” tag:
@{ Html.RenderAction("Header"); }

Creating a Partial View that loads data from Model:


Step 1: add a new class in Models folder of the project naming it as Customer and write the below code in it:
public class Customer
{
public int Custid { get; set; }
public string Name { get; set; }
public string Account { get; set; }
public double Balance { get; set; }
public string City { get; set; }
public bool Status { get; set; }
public string Photo { get; set; }
}

Step 2: under the Images folder of the project add 6 images corresponding to 6 Customers naming them as “Image1”,
“Image2”, “Image3”, “Image4”, “Image5” and “Image6”.

Step 3: add a new Controller under the Controllers folder with the name as “CustomerController”, delete existing
code in the class and write the below code over there, by importing the namespace “MVCUIDesigning.Models”:

147
public ViewResult DisplayCustomers()
{
Customer c1 = new Customer { Custid = 1001, Name = "Peter", Account = "Savings", Balance = 50000.00,
City = "Delhi", Status = true, Photo = "/Images/Image1.jpg" };
Customer c2 = new Customer { Custid = 1002, Name = "Kevin", Account = "Current", Balance = 50000.00,
City = "Kolkata", Status = true, Photo = "/Images/Image2.jpg" };
Customer c3 = new Customer { Custid = 1003, Name = "Sandra", Account = "Demat", Balance = 50000.00,
City = "Mumabi", Status = true, Photo = "/Images/Image3.jpg" };
Customer c4 = new Customer { Custid = 1004, Name = "Williams", Account = "Savings", Balance = 50000.00,
City = "Chennai", Status = true, Photo = "/Images/Image4.jpg" };
Customer c5 = new Customer { Custid = 1005, Name = "John", Account = "Demat", Balance = 50000.00,
City = "Bengaluru", Status = true, Photo = "/Images/Image5.jpg" };
Customer c6 = new Customer { Custid = 1006, Name = "Bill", Account = "Current", Balance = 50000.00,
City = "Hyderabad", Status = true, Photo = "/Images/Image6.jpg" };

List<Customer> customers = new List<Customer> { c1, c2, c3, c4, c5, c6 };

return View(customers);
}

In the above case Display action method is creating instance of 6 Customers, adding them into a List and
then sending that List to its corresponding View to display. To display each Customer’s data in a table format lets
create a Partial View first.

Step 4: add a Partial View in the Shared folder of the Views folder naming it as “_CustomerView”, select the “Create
as a Partial View” CheckBox, click Add button and write the below code in it:

@model MVCUIDesigning.Models.Customer
<table border="1" width="350">
<tr>
<td rowspan="6" style="width:200px;height:200px">
<img style="width:100%;height:100%" src="@Url.Content(Model.Photo)" />
</td>
<td>Custid: @Model.Custid</td>
</tr>
<tr><td>Name: @Model.Name</td></tr>
<tr><td>Account: @Model.Account</td></tr>
<tr><td>Balance: @Model.Balance</td></tr>
<tr><td>City: @Model.City</td></tr>
<tr><td>Status: @Html.CheckBoxFor(C => C.Status)</td></tr>
</table>

Step 5: add a View to “DisplayCustomers” action method of “CustomerController” and write the below code in it.

@*Write the below statement at top of the View *@


@model List<MVCUIDesigning.Models.Customer> Or @model IEnumerable<MVCUIDesigning.Models.Customer>

148
@*Write this code under the <div> tag:*@
<h2>Customer Details</h2>
@foreach (MVCUIDesigning.Models.Customer customer in Model) or @foreach (var customer in Model)
{
Html.RenderPartial("_CustomerView", customer);
}

When we send a request to “DisplayCustomers” action method of “CustomerController”, the method


creates a List of Customers and transfers it to “DisplayCustomers.cshtml” View, and this View will in turn call the
“Partial View” i.e., “_CustomerView” for displaying each Customer data in a table format.

Note: IEnumerable (Interface) is a parent of all the Collection classes, so in place of the List we can also use
IEnumerable, so that going forward this IEnumerable can hold the data that is coming from any Collection object.

Layout Views
These are like “Master Pages” in “ASP.NET Web Forms” and by using these we can design a Layout for the
whole application. Generally, every application will have a common Layout like the Header, Footer, Menu Bar, and
Navigation Bar etc. So, in such scenario without re-designing them for multiple times in each View Page, we will
design it as a Layout View and then use it in the whole Application.

In “ASP.NET Web Forms” the extension of a “Master Page” is “.master” whereas in “ASP.NET MVC” the
extension of “Layout View” is also “.cshtml” only.
ASP.Net Web Forms ASP.NET MVC
Page or View .aspx .cshtml
User Control or Partial View .ascx .cshtml
Master Page or Layout View .master .cshtml

Note: Layout Views are also known as Master Pages and our View Pages are known as Content Pages or Content
Views so these Content Pages or Content Views will merge with the Layout View to display the final output.

To include a Content View into a particular location of a Layout View we need to call a method i.e.,
“RenderBody” so that the Content View will come and sit in that location. A Layout View can contain 1 and only 1
“RenderBody” method call.

To include a “piece of text” into any location of a Layout View we need to call the method “RenderSection”,
so that “text” can be sent into the Layout View from Content View and sending that “text” is not mandatory i.e.,
while calling the “RenderSection” method we can specify a name to the section and a “boolean” value to indicate,
sending a value to that section is mandatory or optional.
RenderSection(string name, bool required)

149
Note: A Layout View can have any no. of “RenderSection” method calls in it, and in this process for every
“RenderSection” we need to give a unique name for identification.

Designing a Layout View:


Step 1: Create a new “ASP.NET Web Application” project naming it as “MVCLayoutViews” choose “Empty Project
Template”, check “MVC” Checkbox and click on the Create button to create the project.
Step 2: Install Bootstrap into the project either by using “NuGet Package Manager” or “Library Manager”, which
installs all the required files by creating required folders under the project.
Step 3: Add a new folder under Views folder naming it as “Shared” because “Partial Views” and “Layout Views” are
generally stored in Shared folder only and the name of these 2 Views will be prefixed with “_ (underscore)” character.
Step 4: add a View into the Shared folder naming it as “_SiteMaster.cshtml”, uncheck the CheckBox “Use a layout
page” and click on the Add button. This action will add a new View and if we observe the code in this View, we find
a statement on the top of the file as following to specify a Layout for this View:
@{
Layout = null;
}

 Right now, what we are designing is a “Layout View” only and we don’t want to apply another layout to the
current View, so delete it.
 Now under the <title> section of the page we find “_SiteMaster”, delete it and write the following there:
“@ViewBag.Title – NIT” so that we can send any value to this “Title” from the “Content Views”.
 Now drag and drop “bootstrap.min.css” file from the content folder into the “<head>” section.
 Add a new folder under the Project with the name Images and add 3 Images into that folder: “Header.png”,
“Footer.png” and “Logo.jpg”.
 Now let’s design the Layout View as below:

150
Write the below code under the “<div>” tag to create the above “Layout View”:
<table style="width:100%">
<tr>
<td align="center" style="background-color:aquamarine">
<img src="~/Images/Logo.jpg" style="height:100px;width:100px" class="rounded-circle" />
</td>
<td>
<img src="~/Images/Header.png" style="height:100px;width:100%" class="rounded" />
</td>
</tr>
<tr>
<td style="vertical-align:top;background-color:burlywood">
<nav class="navbar-dark bg-primary">
<font size="4">
@Html.ActionLink("Home Page", "Home", "NareshIt", new { @class = "navbar-brand" }) <br />
@Html.ActionLink("Registration Page", "Register", "NareshIt", new { @class = "navbar-brand" }) <br />
@Html.ActionLink("Login Page", "Login", "NareshIt", new { @class = "navbar-brand" }) <br />
@Html.ActionLink("Courses Offered", "Courses", "NareshIt", new { @class = "navbar-brand" }) <br />
@Html.ActionLink("About Us", "About", "NareshIt", new { @class = "navbar-brand" }) <br />
</font>
</nav>
</td>
<td>
@RenderBody()
</td>
</tr>
<tr>
<td colspan="2" style="background-color:coral;text-align:center">
@RenderSection("S1", false)
</td>
</tr>
<tr>
<td colspan="2" style="width:100%">
<img src="~/Images/Footer.png" style="width:100%;height:50px" class="rounded" />
</td>
</tr>
</table>

How is a Layout applied to a View (Content View)?


Ans: if we want to apply any Layout to a View, we can do that in 2 different ways.

1. Page Level Binding: we can do this by writing the below code on the top of every View Page:

@{
Layout = "~/Views/Shared/_SiteMaster.cshtml";
}

151
Note: while adding a new View we can select the “Layout View” for the View by selecting the CheckBox, with the
caption “Use a layout page” and when we select the CheckBox, a TextBox and Button with the caption “…” will
enable, and by clicking on that Button we can select our “Layout View” so that it will write the above code
automatically. The drawback in this approach is we need to use this statement on every “Content Page” where we
want to apply the Layout.

2. Application-Level Binding: we do this by writing code in “_ViewStart.cshtml” file because this View will execute
before execution of any other View, and this is called implicitly by MVC Framework. This file should be in the root
folder of “Views” i.e., directly under the “Views” folder. Let’s add this file in the Views folder and to do that right
click on Views folder and select the option => Add => View, name the View as “_ViewStart.cshtml”, choose “Empty
(Without model)” template and make sure all the Checkboxes are un-checked and click on the Add Button. Delete
all the content present in the file and write the below code over there:
@{
Layout = "~/Views/Shared/_SiteMaster.cshtml";
}

Note: if the “_ViewStart.cshtml” file is not added by us and when adding a new View if we check the CheckBox “Use
a layout page”, but did not select any “Layout View” then “MVC Scaffolding” will add a “Layout View” in to the
project with the name “_Layout.cshtml” and also it adds “_ViewStart.cshtml” file under the Views folder with the
below code in it:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

Whereas when we add “_ViewStart.cshtml” explicitly and specified the layout as “_SiteMaster.cshtml”,
then when adding a new View if we check the CheckBox “Use a layout page” but did not select a “Layout View” then
automatically the Layout we specified in “_ViewStart.cshtml” will be applied i.e., “_SiteMaster.cshtml”.

Note: if the “_ViewStart.cshtml” file is present under the Views folder, then all the Views will apply this layout
whereas if it is present under the Views folder corresponding to a Controller then it applies only to the Views in that
folder and if we have this file present in both the places then first preference goes to local.

Step 5: Add a new Controller in Controllers folder naming it as “NareshITController”, delete the existing Action
method in it and write the below code over there:

public ViewResult Home()


{
return View();
}
public ViewResult Register()
{
return View();
}
public ViewResult Login()
{
return View();
}

152
public ViewResult Courses()
{
return View();
}
public ViewResult About()
{
return View();
}

Step 6: Add Views to all the Action methods and while adding them check the CheckBox “Use a layout page”.

Note: as said above, when we perform application level binding of a “Layout View” by entering the details of the
“Layout View” under “_ViewStart.cshtml” file then while adding a View if we select the CheckBox “Use a layout page”
then it will automatically make use of the “Layout View” that is specified in “_ViewStart.cshtml”, whereas if we have
multiple “Layout Views”, we need to click on “…” Button and select the “Layout View” explicitly which will then
perform Page Level Binding.

Code under “Home.cshtml” file:


@{
ViewBag.Title = "Home Page";
}
<p style="text-align: justify; color: palevioletred; font-family: Arial; text-indent: 50px">We have set the pace with
online learning. Learn what you want, when you want, and practice with the instructor-led training sessions, on-
demand video tutorials which you can watch and listen.</p>
<ol style="color:blueviolet; background-color: darkseagreen">
<li>150+ Online Courses</li>
<li>UNLIMITED ACCESS</li>
<li>EXPERT TRAINERS</li>
<li>ON-THE-GO-LEARNING</li>
<li>PASSIONATE TEAM</li>
<li>TRAINING INSTITUTE OF CHOICE</li>
</ol>
<p style="text-align: justify; color: palevioletred; font-family: Arial; text-indent: 50px">Naresh I Technologies is
renowned around the world for classroom training where every aspirant is encouraged to attend technical sessions
discussing every facet of the subject with excruciating detail on varied technologies. Every aspirant in the training
program will be provided with the hands-on experience through several Lab assignments and case studies there by
making them more employable.</p>
@section S1 {
<font size="3" color="blue">Excellence in IT Training since 2003.</font>
}

Code under “Register.cshtml” file:


@{
ViewBag.Title = "Registration Page";
}
<h3 style="text-align:center;text-decoration:underline">Registration Page</h3>
<table align="center" class="table-bordered">

153
<tr>
<td>Name:</td><td><input type="text" id="txtName" /></td>
</tr>
<tr>
<td>User Id:</td><td><input type="text" id="txtUid" /></td>
</tr>
<tr>
<td>Password:</td><td><input type="password" id="txtPwd" /></td>
</tr>
<tr>
<td>Confirm Password:</td><td><input type="password" id="txtCPwd" /></td>
</tr>
<tr>
<td>Mobile:</td><td><input type="tel" id="txtMobile" /></td>
</tr>
<tr>
<td>Email Id:</td><td><input type="email" id="txtEmail" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" id="btnRegister" value="Register" />
<input type="reset" id="btnReset" value="Reset" />
</td>
</tr>
</table>
@section S1 {
<font size="3" color="blue">Join us for best IT Training.</font>
}

Code under “Login.cshtml” file:


@{
ViewBag.Title = "Login Page";
}
<h3 style="text-align:center;text-decoration:underline">Login Page</h3>
<table class="table-bordered" align="center">
<tr><td>User Id:</td><td><input type="text" id="txtUid" /></td></tr>
<tr><td>Password:</td><td><input type="password" id="txtPwd" /></td></tr>
<tr>
<td colspan="2" align="center">
<input type="submit" id="btnLogin" value="Login" />
<input type="reset" id="btnReset" value="Reset" />
</td>
</tr>
</table>
@section S1 {
<font size="3" color="blue">Trained over 10,00,000 IT Professionals.</font> }

154
Code under “Courses.cshtml” file:
@{
ViewBag.Title = "Courses Page";
}
<h2>Courses Offered:</h2>
<ul type="square">
<li>.NET</li>
<li>Java</li>
<li>Python</li>
<li>DevOps</li>
<li>Selenium</li>
<li>Cloud Technologies</li>
<li>Data Science</li>
<li>Automation</li>
<li>Software Testing</li>
<li>Mobile Technologies</li>
<li>Digital Marketing</li>
<li>Spring Boot & Microservices</li>
</ul>
@section S1 {
<font size="3" color="blue">Experienced faculties with excellent training skills.</font>
}

Code under “About.cshtml” file:


@{
ViewBag.Title = "About Page";
}
<p style="text-align: justify; color: green; font-family: 'Agency FB'; text-transform: capitalize; text-indent: 50px;font-
size:15px">NareshIT (Naresh I Technologies) is a leading Software Training Institute and provides Job Guarantee
Program through Nacre in Hyderabad, Chennai, Bangalore, Vijayawada and across the world with Online Training
services. Managed and Lead by IT Professionals with more than a decade experience in leading MNC companies.
We are most popular for our training approach that enables students to gain real-time exposure on cutting-edge
technologies. Naresh I Technologies started satisfying the students who are at remote locations with Online Training
program, with an intention to provide services for all those aspirants who want to be part of the software industry.
The aspirants who due to various reasons cannot travel physically to our location can just keep themselves registered
for this program along with their needs with just a single phone call or a mail provided in our contact’s page. The
Online Training program is conducted over the internet using the latest state of the art software tools and via the
video and desktop sharing facility. The training program is conducted by well experienced training faculty who are
mentored in conducting such sessions as per the convenience of the participant. The Online Training program is
provided with required material for reference and on hands exercises and Lab sessions for practical exposure. The
students are monitored for any clarifications and doubts by the faculty all through the course either by phone or
mail as per the convenience of the participants. Our sole maxim in introducing Online Technical Training Sessions is
to cater to the training requirements of the aspirants who due to various reasons cannot travel physically to our
location. In the online training program, the training sessions are conducted over the internet using the latest state
of the art software tools and the hands-on experience also will be provided at the convenience of the participant.
</p>

155
Action Results in MVC
Action Methods in an “MVC Application” can return different types of results and we call them as Action
Results. In MVC, “ActionResult” is a class, and this class has various child classes under it and an Action method can
return any of those classes as a result i.e., either parent class “ActionResult” or its child classes. Controller class (the
parent class of all the Controllers we define) provides different helper methods to return a Result, where each helper
method returns a different “ActionResult”, for example:
Helper Methods Action Results
File FileResult
Json JsonResult
View ViewResult
--- EmptyResult
Content ContentResult
Redirect RedirectResult
JavaScript JavaScriptResult
PartialView PartialViewResult
HttpNotFound HttpNotFoundResult
HttpStatusCodeResult HttpUnauthorizedResult
RedirectToRoute RedirectToRouteResult
RedirectToAction RedirectToRouteResult

 ViewResult: sends a view as response.


 PartialViewResult: sends a partial view as response.
 RedirectToRouteResult: represents a result that performs a redirection to an action method by using the
specified route values dictionary.
 JsonResult: represents a class that is used to send JSON-Formatted content as response.
 FileResult: represents a class that is used to send file content as response.
 RedirectResult: controls the processing of application’s action method by redirecting to a specified URI.
 ContentResult: represents a user-defined content type, which is sent as a response.
 JavaScriptResult: sends JavaScript content as a response (currently this is not supported by the modern
browsers and removed in MVC Core).
 EmptyResult: represents a result that does nothing, such as controller action method which returns void.
 HttpStatusCodeResult: provides a way to return an action result with a specific HTTP Status Code and
Description.

In the previous programs we have already used “ViewResult”, “PartialViewResult” and


“RedirectToRouteResult” and to test the other Action Results lets create a new “ASP.NET Web Application” project
naming it as “ActionResultsInMVC”, choose “MVC Project Template”, un-check all the other Checkboxes and click on
Create button to create the project.

Note: if we open a project by choosing “MVC Project Template” then, we will find a “Content” folder with
“Bootstrap” installed and we will also find a “Scripts” folder with “JQuery” installed in it. In the “Controllers” folder
we find a Controller with the name “HomeController” with 3 Action methods in it with the name: Index, About and
Contact; and these methods will also have associated Views in the “Home” folder of “Views” folder. We will also
have “Shared” folder with a “Layout View (_Layout.cshtml)” and “Error View (Error.cshtml)”, apart from that we will
also have “_ViewStart.cshtml” in which the Layout is applied.

156
Now do the following under the Project:
Step 1: Add a new folder in the project, naming it as “Downloads”, and add 1 “.pdf” and 1 “.doc” file into the folder.

Step 2: Add a new class in Models folder of the project naming it as “Employee” and write the below code in it:

public class Employee


{
public int Id { get; set; }
public string Name { get; set; }
public string Job { get; set; }
public double Salary { get; set; }
public bool Status { get; set; }
}

Step 3: Add a Controller naming it as “ResultsController” and define the below “Action Methods” in the class.

using System.Text;
using ActionResultsInMVC.Models;
public JsonResult GetEmployees()
{
Employee e1 = new Employee { Id = 101, Name = "Scott", Job = "CEO", Salary = 25000, Status = true };
Employee e2 = new Employee { Id = 102, Name = "Smith", Job = "President", Salary = 22000, Status = true };
Employee e3 = new Employee { Id = 103, Name = "Parker", Job = "Manager", Salary = 18000, Status = true };
Employee e4 = new Employee { Id = 104, Name = "John", Job = "Salesman", Salary = 10000, Status = true };
Employee e5 = new Employee { Id = 105, Name = "David", Job = "Clerk", Salary = 5000, Status = true };
Employee e6 = new Employee { Id = 106, Name = "Maria", Job = "Analyst", Salary = 12000, Status = true };
List<Employee> Emps = new List<Employee> { e1, e2, e3, e4, e5, e6 };
return Json(Emps, JsonRequestBehavior.AllowGet);
}
public FileResult DownloadPdf()
{
return File("~/Downloads/Test.pdf", "application/pdf");
}
public FileResult DownloadWord()
{
return File("~/Downloads/Test.doc", "application/msword");
}
public RedirectResult OpenFaceBook()
{
return Redirect("https://facebook.com");
}
public RedirectResult OpenTwitter()
{
return Redirect("https://twitter.com");
}
public string SendDate1()
{

157
return "Current Date: " + DateTime.Now;
}
public ContentResult SendDate2()
{
return Content("Current Date: " + DateTime.Now.ToString());
}
public string SayHello1()
{
return "नमस्ते आप कैसे हैं ";
}
public ContentResult SayHello2()
{
return Content("नमस्ते आप कैसे हैं ", "text/plain", Encoding.Unicode);
}
public JavaScriptResult AlertUser()
{
return JavaScript("alert('Hello, how are you.');");
}
public void ReturnEmpty1()
{
string str = ("Hello World").ToUpper();
}
public EmptyResult ReturnEmpty2()
{
return new EmptyResult();
}

Add a “View” to “Index Action Method” without choosing a Layout and write the below code in its “<div>” tag:
<h2>MVC Action Results</h2>
<ol>
<li>@Html.ActionLink("Json Result", "GetEmployees")</li>
<li>@Html.ActionLink("Download Pdf", "DownloadPdf", null, new { target = "_blank" })</li>
<li>@Html.ActionLink("Download Word", "DownloadWord")</li>
<li>@Html.ActionLink("Facebook", "OpenFaceBook", null, new { target = "_blank" })</li>
<li>@Html.ActionLink("Twitter", "OpenTwitter", null, new { target = "_blank" })</li>
<li>@Html.ActionLink("Today’s date returned as ContentResult", "SendDate1")</li>
<li>@Html.ActionLink("Today’s date returned as String", "SendDate2")</li>
<li>@Html.ActionLink("नमस्ते बोलो returned as String", "SayHello1")</li>
<li>@Html.ActionLink("नमस्ते बोलो returned as ContentResult", "SayHello2")</li>
<li>@Html.ActionLink("Javascript Alert", "AlertUser")</li>
<li>@Html.ActionLink("Empty Result", "ReturnEmpty1")</li>
<li>@Html.ActionLink("Void Result", "ReturnEmpty2")</li>
</ol>
Run the “Index” action method of “ResultsController” which provides links to execute the other action
methods defined in the class.

158
Minification and Bundling
These are two techniques we use in Web Applications to improve request load time. Bundling and
Minification improves load time by reducing the size of requested assets and reducing the number of requests to
the server for the assets (such as CSS and JS Files.)

Note: most of the current modern browsers limit the number of simultaneous connections per each host to 6. That
means while 6 requests are being processed, additional requests for assets on a host will be queued by the browser.

Minification: this performs a variety of different code optimizations to CSS and Scripts such as removing unnecessary
white spaces, line breaks, comments, and shortening variable names to one character.

For example, consider the below JavaScript function:


function SayHello(name)
{
//This function wishes the user with his given name
var msg = "Hello " + name;
alert(msg);
}

After Minification, the function is reduced as below:


function SayHello(n){var m="Hello "+n;alert(m);}

In the above case “name” parameter is shortened as “n” and “msg” variable is shorted as “m”, removed
comments, line breaks and unnecessary white spaces.

How to perform Minification?


Ans: To perform Minification of assets (CSS and JS files) we need to take the help of some tool and there are various
tools available in the industry to do this. In our code we are going to use “Portable Smalify” tool which can be
download from this location:
https://www.softpedia.com/get/PORTABLE-SOFTWARE/System/File-management/Portable-Smalify.shtml

After downloading, unzip the file into a folder and in that folder, we find “Smalify.exe”. Run it, which will
open a User Interface, drag, and drop the folder in which we have placed the “.css” or “.js” files on the UI, which we
want to minify and click on the “Minify now” button on the UI.

Step 1: Create a new “ASP.NET Web Application” project naming it as “MinificationAndBundling”; choose “Empty
Project Template”, check “MVC” checkbox and click on the “Create” button.

Add a folder under the project with the name “Content” and under this folder add 2 “.css” files with the
name “Header.css” & “Paragraph.css”, and write the below code in those files:

Header.css:
h1 {
color: red;text-align: center;background-color: palegreen;border-style: double;border-bottom-color: bisque;
border-top-color: coral;border-left-color: coral;border-right-color: bisque;text-decoration: underline;
}

159
Paragraph.css:
p
{
text-align: justify;text-justify: inter-word;
color: green;font-family: courier;font-size: 160%;
text-transform: capitalize;text-indent: 50px;line-height: 1.8;border: 2px solid #0066FF;
border-top-width: 2px;border-right-width: 2px;border-bottom-width: 2px;border-left-width: 2px;
border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;
border-top-color: #0066FF;border-right-color: #0066FF;border-bottom-color: #0066FF;
border-left-color: #0066FF;
}

Step 2: Minification of “.css” files and to do that right click on Project in Solution Explorer, select “Open Folder in File
Explorer” which will display the list of folders and files under project folder in Windows Explorer. Run “Smalify.exe”,
drag and drop the “Content” folder on to the UI of the “Smalify.exe” and click on “Minify now” button, which will
generate the minified files “Header.min.css” and “Paragraph.min.css”. To load these files in our project, select
“Content” folder in Solution Explorer and choose the option “Show All Files” in the top of Solution Explorer which
will show the 2 files under Content folder, right click on them and select the option “Include in Project”, which will
load them into the project, and after loading again click on “Show All Files”.

Step 3: Add a new Controller with the name “HomeController” and add a View to the existing Index Action Method
without selecting “Use a layout page” Check Box. Now drag and drop “Header.min.css” and “Paragraph.min.css” files
under the “<head>” tag of the View and write the below code under the “<div>” tag of the View:

<h1>Naresh I Technologies</h1>
<p>Classroom Training schedule is a custom-made training program to suit the aspirants from different educational
backgrounds, the training programs are conducted by well-trained faculties in the corresponding specializations in a
real-time environment. The classroom training is conducted exclusively in the campus of Naresh i Technologies with
well equipped and configured architecture to give students exactly an environment of industrial exposure.</p>
<p>Naresh i Technologies is renowned around the world for classroom training where every aspirant is encouraged
to attend technical sessions discussing every facet of the subject with excruciating detail on varied technologies.
Every aspirant in the training program will be provided with the hands-on experience through a number of Lab
assignments and case studies there by making them more employable.</p>
<p>Digital marketing is an umbrella for an online system. Digital marketing refers to advertising which is delivered
through the digital channel. Few digital marketing is like websites, social media, emails and mobile apps. The product
is being marketed through digital technology. This Digital marketing online training course will help how to use the
Facebook, Twitter, LinkedIn, etc for online advertisement. In simple term, the digital marketing means the promotion
of the products or brands via some electronic media.</p>
<p>Corporate Training program is tailor-made to suit the working professionals in the industry who are expected to
have a shift in their domain or technology as per their career demand. The corporate training courses are customized
to meet the project requirements as expected from the corporate trainees.</p>
<p>The Corporate Training is provided either at the client location or at our Naresh i Technologies campus depending
upon the need of the client. In the global markets of competition training and development of the employees to
keep up their technical expertise has become the most important composition of any I.T. Organization.</p>
<p>The corporate employees require regular enhancements and update of the up-coming technologies in
accordance with the advancements as demanded by the end clients. This requirement of the corporate sector is the

160
key juncture where Naresh iTechnologies started sharing its expertise in reducing the training over-heads of the
corporate sector.</p>
<p>The success of Naresh i Technologies lies in customized course content depending on the project requirements
of the client and the experience level of the participants thereby enhancing the productivity of the overall
industry.</p>
<h1>Excellence In IT Training</h1>

Now run the “Index View” and watch the output, because the page is using 2 CSS Files (Assets) there will
be total 3 requests sent from the browser to server to load the assets as following:
 Index.cshtml
 Header.min.css
 Paragraph.min.css

To watch this hit “F12” in the Browser which will open a window on the “RHS” or “Bottom” of the Browser
called as “Developer Tools”, in that window go to “Network” tab, and click on the refresh button on the Browser
which will show the no. of requests in the bottom on “Developer Tools” window.

Note: To minimize the no. of requests from browser to server, we can take the help of bundling, so that both the
CSS files will be loaded in a single request and the no. of requests can be reduced to 2 from 3 in the current case.

Bundling: this is a new feature introduced in “ASP.NET 4.5”. Bundling makes it easy to combine or bundle multiple
files into a single unit, and by using this we can create CSS, Java Script and other bundles. Fewer files mean fewer
HTTP requests and that can improve page load performance.

To perform Bundling we need to take the help of “Web Optimization Framework” library in our project and
to use it we need to install it thru “NuGet Package Manager”, and to do that, open “NuGet Package Manager”, go to
Browse and search for “Web Optimization Framework” that displays “Microsoft.AspNet.Web.Optimization”, select
it and install it.

Working with Microsoft AspNet Web Optimization Framework: in this library we are provided with a set of classes
under “System.Web.Optimization” namespace:

 StyleBundle: this represents a collection of Style Sheet files.


 ScriptBundle: this represents a collection of Script files.
 BundleCollection: this represents a set of “StyleBundles” and “ScriptBundles”.
 BundleTable: this is a holder class for the “BundleCollection”.
 Scripts: this class is used for rendering the Script Bundles in our Web Pages i.e., “.cshtml” files and to do that
we need to call a static method under the class i.e., Render to render the script files in ScriptBundles.
 Styles: this class is used for rendering the Style Bundles in our Web Pages i.e., “.cshtml” files and to do that we
need to call a static method under the class i.e., Render to render the style files in StyleBundles.

Step 4: To perform bundling, add a “Code File” under “App_Start” folder with the name “BundleConfig.cs” and write
the below code in the file:

161
using System.Web.Optimization;
namespace MinificationAndBundling
{
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
//Create a StyleBundle and include all the CSS files into it
StyleBundle styleBundle = new StyleBundle("~/Content/NITStyleBundle");
styleBundle.Include("~/Content/Header.min.css", "~/Content/Paragraph.min.css");
bundles.Add(styleBundle);

//Create a ScriptBundle and include all the Scripts files into it (Example Code)
//ScriptBundle scriptBundle = new ScriptBundle("~/Scripts/NITScriptBundle");
//scriptBundle.Include("~/Scripts/Test1.min.js", "~/Scripts/Test2.min.js");
//bundles.Add(scriptBundle);
}
}
}

Step 5: Now open the “Global.asax” file and call “RegisterBundles” method of “BundleConfig” class inside of
“Application_Start” method by importing “System.Web.Optimization” namespace:
BundleConfig.RegisterBundles(BundleTable.Bundles);

Step 6: go to “Index.cshtml” file and do the following:


 Import the namespace “System.Web.Optimization” as following on top of the file:
@using System.Web.Optimization

 Delete the 2 <link> tag statements in the head section and write the below code over there:
@Styles.Render("~/Content/NITStyleBundle")
//@Scripts.Render("~/Scripts/NITScriptBundle") //Example Code

 Now run the “Index.cshtml” file again and watch the output, but now also we will have 3 requests only because
bundling is performed only in the “Release or Production” mode but not in “Debug or Development” mode. If
we want to test bundling at the time of “Application Development” we can achieve that in 2 different ways:

 Open “Web.config” file and there under “<system.web>” tag we find “<compilation>” tag with a boolean
attribute “debug” and its value will be “true” by default, change it as “false” and run “Index.cshtml” file
again. The code in “Web.config” should now look as following:
<compilation debug="false" targetFramework="4.8" />

 With-out changing the “debug” attribute value as “false” in “Web.config” file also, we can perform
bundling i.e., in “Debug or Development” mode bundling can be performed and to do that, change the
“false” value as “true” again in “Web.config” file, go to “BundleConfig.cs” and write the below
statement in the end of “RegisterBundles” method and run “Index.cshtml” page again:
BundleTable.EnableOptimizations = true;

162
Areas
It is an approach of dividing a large “MVC Applications into smaller logical units, so that organizing of the
application becomes much simple and easier. Area in an MVC Application is a collection of “Controllers”, “Views”
and “Models” i.e., we can maintain them separately for each module.

For example, in a Hospital Management Application, for better organization of the Application the Project
Manager divided the Application into different modules like Patient Module, Doctor Module, Staff Module,
Insurance Module, Billing Module, Labs Module, Medicine Module and HR Module. Now each Module is given for a
different team to develop, so every Module will be having its own Controllers, Views and Models, for example:
Patients Module => Controllers, Views and Models
Doctors Module => Controllers, Views and Models
Staff Module => Controllers, Views and Models
Insurance Module => Controllers, Views and Models
Billing Module => Controllers, Views and Models
Labs Module => Controllers, Views and Models
Medicines Module => Controllers, Views and Models
HR Module => Controllers, Views and Models

While integrating all these Modules, for a clear separation and management of the Application we use areas
because every area will be having its own Controllers, Views and Models, so under the project we maintain 1 area
for each Module as below:
PatientArea => PatientControllers, PatientViews, PatientModels
DoctorArea => DoctorControllers, DoctorViews, DoctorModels
StaffArea => StaffControllers, StaffViews, StaffModels
InsuranceArea => InsuranceControllers, InsuranceViews, InsuranceModels
BillingArea => BillingControllers, BillingViews, BillingModels
LabArea => LabControllers, LabViews, LabModels
MedicinesArea => MedicineControllers, MedicineViews, MedicineModels
HRArea => HRControllers, HRViews, HRModels

To work with areas, create a new “ASP.NET Web Application” project naming it as “MVCAreas”, choose
“Empty Project Template”, check the “MVC” CheckBox and click on “Create” button to create the project. To add an
Area under the project, right click on the Project and select the option Add => “New Scaffolded Item”, this will open
a new window and in that window on the LHS expand the “MVC Node” and select the option “Area” and then on
the RHS it will display “MVC 5 Area”, select it and click on “Add” button which will ask for a name to the Area, enter
the name as “Patient” and click on the “Add” button which will add “Areas” folder under the Project and under that
“Areas” folder it will add another folder with the name “Patient” and under this it will add “Controllers”, “Views”
and “Data (Models)” folders and also 1 file with name “PatientAreaRegistration.cs” and under this we find a class
“PatientAreaRegistration” inheriting from “AreaRegistration” class and under this class we find a method
“RegisterArea” defining the route to accessing the “Action Methods” in this area as following:

public override void RegisterArea(AreaRegistrationContext context)


{
context.MapRoute(
"Patient_default",
"Patient/{controller}/{action}/{id}",

163
new { action = "Index", id = UrlParameter.Optional }
);
}

Adding multiple areas in the Project: to add more “Areas” in the project, now directly right click on the “Areas” in
Solution Explorer and select “Add” => “Area” and in the window opened select “MVC 5 Area” and give a name to it,
and by following this process add 2 new Areas with the names “Doctor” and “Staff”.

Note: under every Area we have added, we will find “Controllers”, “Views” and “Data” folders as well as
“AreaRegistration” class as following:

Add a Controller in each Controllers folder with-in the “Areas” naming them as “HomeController” and add
a View to each “Index Action Method” by choosing a layout and write the below code in them by deleting the existing
code:

Doctor Home Controller’s - Index.cshtml:


@{
ViewBag.Title = "Doctors - Index Page";
}
<h2>This is Home Page of Doctor's Area.</h2>
@Html.ActionLink("Back to site home page", "Index", "Home", new { area = "" }, null)

Patient Home Controller’s - Index.cshtml:


@{
ViewBag.Title = "Patients - Index Page";
}
<h2>This is Home Page of Patient's Area.</h2>
@Html.ActionLink("Back to site home page", "Index", "Home", new { area = "" }, null)

Staff Home Controller’s - Index.cshtml:


@{
ViewBag.Title = "Staff - Index Page";
}

164
<h2>This is Home Page of Staff Area.</h2>
@Html.ActionLink("Back to site home page", "Index", "Home", new { area = "" }, null)

Add a Controller under the project’s root “Controllers” folder naming it as “HomeController” only, add a
View to existing “Index Action Method”, choosing a layout and write the below code in it by deleting existing code:

@{
ViewBag.Title = "Site - Index";
}
<h2>This is the Home Page of Site.</h2>
@Html.ActionLink("Doctor Home Page", "Index", "Home", new { area = "Doctor" }, null)
<br />
@Html.ActionLink("Patient Home Page", "Index", "Home", new { area = "Patient" }, null)
<br />
@Html.ActionLink("Staff Home Page", "Index", "Home", new { area = "Staff" }, null)

Run the project which must launch the above “Index.cshtml” View of the root “Home Controller” but it will
not launch because there are multiple “Home Controllers” and “Index Action Methods” under the project, so we get
an error. To resolve the problem open “RouteConfig.cs” file present in “App_Start” folder of the project and specify
the namespace of our Root “HomeController” to it in “routes.MapRoute” method, which should now look as below:

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "MVCAreas.Controllers" }
);

This action should now launch the “Site Home Page” i.e., “Index Page” of root “Home Controller” of the
Project and in that “Page” we will find links to launch “Doctor’s Home Page”, “Patient’s Home Page” and “Staff Home
Page”, click on them and test it.

When we enter the below URL in the browser:


http://localhost:port => Launches Site Home Page

Same as above when we enter below URL’s they should launch their corresponding Home Pages, for example:
http://localhost:port/Doctor => should launch Doctor home page
http://localhost:port/Patient => should launch Patient home page
http://localhost:port/Staff => should launch Staff home page

But when to try them, we get “Page Not Found” error and to resolve this problem go to each
“AreaRegistration.cs” file that are present in each “Areas” folder and there we find the method “RegisterArea”, and
in that method with-in the last line specify the default Controller name i.e., “Home”, as following:

Old Code: new { action = "Index", id = UrlParameter.Optional }


New Code: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

165
Data Annotations
These are nothing but validations that we put on our “Models” to validate the input from the user. These
are similar to “Validation Controls” in “ASP.NET Web Forms”. “ASP.NET MVC” provides a unique feature by using
which we can validate the models using the “Data Annotation” attributes importing the namespace
“System.ComponentModel.DataAnnotations”. Data Annotations can be used in our View Pages for validating
Controls as well as they can also be used in “Entity Framework”. Data Annotations allows us to define all the rules a
Model Class and its Properties has to follow, and they are divided into different categories, like:

 Display Attributes
 Validation Attributes
 Modeling Attributes

Every Data Annotation is a class that is defined in the libraries of our language under the namespace
“System.ComponentModel.DataAnnotations” and the parent class for all these classes is “Attribute” and the
hierarchy of these classes is as following:

 Attribute
 DisplayAttribute
 DisplayFormatAttribute
 DisplayColumnAttribute
 ValidationAttribute
RequiredAttribute
DataTypeAttribute
CompareAttribute
RangeAttribute
RegularExpressionAttribute
RemoteAttribute (This class is defined under “System.Web.MVC” namespace)

Note: Data Annotation’s - Validation Attributes, will perform data validations both on Client as well as Server also
i.e., first they will validate the data on Client Machine and if at all those validations fail, page will not be submitted
to the Server, whereas if the Client disables Java Script on his browser, then data is submitted to Server even if the
Validations fail and to overcome this problem, validations are re-performed on Server also.

To perform the Client-Side Validations, Data Annotations uses JQuery Libraries, so our View Pages have to
use the below JQuery Libraries:

 jquery-<version>.min.js
 jquery.validate.min.js
 jquery.validate.unobtrusive.min.js

Display Attribute: by using this attribute we can specify a name that has to be displayed by a Label on the View for
the Model’s Property.
[Display(Name = "First Name:")]
public string FirstName { get; set; }

DisplayFormat Attribute: by using this attribute we can specify how data fields are displayed and formatted, and
with the help of this we can do the following:

166
 Display the text as “[Null]” when a data field is empty.
 Display currency data in locale-specific currency format.
 Display date information in any pre-defined or specified format.

To display numeric data in Currency Format:


[DisplayFormat(DataFormatString = "{0:c}")]
public double Salary { get; set; }

To display data in Date Format (MM/dd/yyyy):


[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime DOB { get; set; }

To display data in specified Date Format:


[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime DOB { get; set; }

To display data in specified Date & Time format (Time in 24 hour format):
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy HH:mm:ss}")]
public DateTime DOB { get; set; }

To display data in specified Date & Time format (Time in 12 hour format with AM/PM):
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy hh:mm:ss tt}")]
public DateTime DOB { get; set; }

To display “Value not specified” when value is null:


[DisplayFormat(NullDisplayText = "Name not specified.")]
public string Name { get; set; }

Validation Attributes:
Required Attribute: this attribute is used to specify that the value is mandatory and cannot be skipped.
[Required(ErrorMessage = "Name field can't be left empty.")]
public string Name { get; set; }

DataType Attribute: this attribute is used to specify the data type for the model’s property.
[DataType(DataType.Password)]
public string Password { get; set; }

Compare Attribute: this attribute is used to compare the value of 1 Model property with other property.
[Compare("Password", ErrorMessage = "Confirm password should match with password.")]
public string ConfirmPassword { get; set; }

Range Attribute: this attribute is used to specify a range for the Model properties value.
[Range(18, 60, ErrorMessage = "Age should be between 18 to 60 years. ")]
public int Age { get; set; }

RegularExpression Attribute: this attribute is used to compare the Model properties value with a
“RegularExpression”.

167
[RegularExpression(@"[6-9]\d{9}")] //Mobile No. should start with 6, 7, 8, and 9 only and can be
having a length of 10 digits (Both Max & Min).
public string Mobile { get; set; }

Remote Attribute: this attribute class is defined in “System.Web.MVC” namespace which is used to make “AJAX”
call to Server and validate data without posting the entire form to the server, whenever a server-side validation is
preferable in any particular scenario and in this case the result is sent back from server to client in JSON format.

To test all the above, create a new “ASP.NET Web Application” project naming it as “MVCDataAnnotations”,
choose “Empty Project Template” and select “MVC” Checkbox to create the project.

Step 1: Add a Model class under the Models folder naming it as “User.cs” and write the below code in it by importing
“System.ComponentModel.DataAnnotations” namespace:

public class User


{
[Display(Name = "User Name")]
[Required(ErrorMessage = "User name field can't be left empty.")]
[RegularExpression(@"[A-Za-z\s]{3,}", ErrorMessage = "Name can have alphabets & spaces with min size of 3.")]
public string Name { get; set; }

[DataType(DataType.Password)]
[Required(ErrorMessage = "Password field can't be left empty.")]
[RegularExpression(@"(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$_-])(?=\S+$).{8,16}", ErrorMessage = "Password
Format: <br />-No spaces.<br />-Minimum 1 numeric.<br />-Minimum 1 upper case & lower case alphabet.
<br />-Minimum 1, any of these Special characters: -, _, @, #, $.<br />-Should be ranging between 8 - 16 chars.")]
public string Password { get; set; }

[DataType(DataType.Password)]
[Display(Name = "Confirm Password")]
[Required(ErrorMessage = "Confirm password field can't be left empty.")]
[Compare("Password", ErrorMessage = "Confirm password should match with password.")]
public string ConfirmPassword { get; set; }

[DataType(DataType.Date)]
[Display(Name = "Date of Birth")]
[Required(ErrorMessage = "Date of birth field can't be left empty.")]
[System.Web.Mvc.Remote("IsValidDate", "User", ErrorMessage = "User should attain 18 years age to register.")]
public DateTime DOB { get; set; }

[Display(Name = "Mobile No")]


[DataType(DataType.PhoneNumber)]
[Required(ErrorMessage = "Mobile No. field can't be left empty.")]
[RegularExpression(@"[6-9]\d{9}", ErrorMessage = "Mobile No. should start with 6, 7, 8, and 9 only and can be
having a length of 10 digits (both Max & Min).")]
public string Mobile { get; set; }

168
[Display(Name = "Email Id")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }

[Display(Name = "User Address")]


[DataType(DataType.MultilineText)]
public string Address { get; set; }
}

Password rules Regular Expression:


(?=.*[0-9]) represents a digit must occur at least once.
(?=.*[a-z]) represents a lower case alphabet must occur at least once.
(?=.*[A-Z]) represents an upper case alphabet that must occur at least once.
(?=.*[@#$_-]) represents a special character that must occur at least once.
(?=\S+$) white spaces are not allowed in the entire string.
{8, 16} represents at least 8 characters and at most 16 characters allowed.

Step 2: Add a Controller class in Controllers folder of the project naming it as “UserController” delete all the content
in the class and write the below code in it by importing “MVCDataAnnotations.Models” namespace:

//Validation code for DOB field which is called using Remote Attribute
public JsonResult IsValidDate(DateTime DOB)
{
bool Status;
if (DOB > DateTime.Now.AddYears(-18))
{
Status = false;
}
else
{
Status = true;
}
return Json(Status, JsonRequestBehavior.AllowGet);
}
public ViewResult AddUser()
{
return View();
}
public ViewResult DisplayUser(User user)
{
return View(user);
}

Step 3: Install latest versions of jQuery, jQuery.Validation, Microsoft.jQuery.Unobtrusive.Validation, and Bootstrap


libraries using “Nuget Package Manager”.

Step 4: Add a view to “AddUser” action method without choosing any “Layout”, and do the following:

169
@* Write the below statement at top of the View. *@
@model MVCDataAnnotations.Models.User

@* Drag and Drop the following files from Scripts folder into the "<head>" section. *@
<script src="~/Scripts/jquery-3.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

@* Drag and Drop the following file from Content folder into the "<head>" section. *@
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />

@* Write the below code under "<div>" tag. *@


@using (Html.BeginForm("DisplayUser", "User"))
{
<div>
@Html.LabelFor(U => U.Name)<br />
@Html.EditorFor(U => U.Name)
@Html.ValidationMessageFor(U => U.Name)
</div>
<div>
@Html.LabelFor(U => U.Password)<br />
@Html.EditorFor(U => U.Password)
@Html.ValidationMessageFor(U => U.Password)
</div>
<div>
@Html.LabelFor(U => U.ConfirmPassword)<br />
@Html.EditorFor(U => U.ConfirmPassword)
@Html.ValidationMessageFor(U => U.ConfirmPassword)
</div>
<div>
@Html.LabelFor(U => U.DOB)<br />
@Html.EditorFor(U => U.DOB)
@Html.ValidationMessageFor(U => U.DOB)
</div>
<div>
@Html.LabelFor(U => U.Mobile)<br />
@Html.EditorFor(U => U.Mobile)
@Html.ValidationMessageFor(U => U.Mobile)
</div>
<div>
@Html.LabelFor(U => U.Email)<br />
@Html.EditorFor(U => U.Email)
@Html.ValidationMessageFor(U => U.Email)
</div>
<div>
@Html.LabelFor(U => U.Address)<br />

170
@Html.EditorFor(U => U.Address)
</div>
<div>
<input type="submit" value="Save User" class="btn btn-primary" />
<input type="reset" value="Reset Data" class="btn btn-danger" />
</div>
}

Note: Data Annotations will perform Data Validations when we bind Views with Model Classes using the “Strongly
Typed Html Helpers” like LabelFor, TextBoxFor, EditorFor, etc.

Step 5: Add a view to “DisplayUser” and while adding choose the Template as: Details, choose the Model class as:
User, uncheck all other CheckBox’s and click on Add button which should be as below:

If we open “DisplayUser.cshtml” file and watch the code, there we find a “<dl> (Description List)” to display
the data and under this “<dt>” tag is used to display “Attribute Name” by calling the helper method
“DisplayNameFor” and “<dd>” tag is used to display “Attribute Value” by calling the helper method “DisplayFor”.

Now run the View, fill in the details and click on “Save User” button to launch “DisplayUser” View but in this
process if we enter any wrong values into the controls or did not enter values into the controls, Validation Attributes
comes into picture, display’s “Error Messages” and will not allow the page to be submitted to the server. By default,
“Validation Error Messages” are displayed by using the “Span” tag and the text will be in black color, whereas if we
want to highlight those messages go to “<head>” section of the “AddUser” View and define a style for “<span>” tag
as following:
<style>span { color: red;background-color: yellow;font-style: oblique }</style>

Validation Attributes will perform Data Validations on the Client Machine and if at all those validations fail,
page will not be submitted to server. Even in case of the “Remote” validation also without submitting the page to
Server it will perform an “AJAX” call to the Server and receives the result as “JSON” which will be “true” if the
validation is successful and “false” if the validation fails. In case, if Java Script is disabled on client’s browser, then
there will be a problem i.e., page gets submitted to Server even if Validations fail, so to overcome the problem, in
our “DisplayUser” action method we need to verify with a condition i.e., “ModelState.IsValid” which returns “true”
if all the data validations are successfully completed or else it returns “false” if any validation fails.

To test this, re-write code of “DisplayUser” Action method as below:


if (ModelState.IsValid)
{
return View(obj);
}

171
else
{
return View("AddUser", obj);
}
All Validation Attributes will perform Validations on client side only and if at all Java Script is disabled on
client’s browser, page will be submitted to the Server, so to overcome this problem, Server will again re-validate all
the input, and if the Validations are successful, it will set the Models “IsValid” property as “true”, or “false” if any of
the Validations fail which we can use in our Server-Side Logic to perform further actions as we have done above.

Validation Summary: by using this we can display all the “Error Messages” at 1 place without displaying them beside
the controls. To display all our “Error Messages” on top of the form, write the below code in “AddUser” View in the
top of “Begin Form” block.

<div>@Html.ValidationSummary("", new { @class = "alert alert-danger" })</div>

Note: After adding this all the “Error Messages” will be displayed by the “Validation Summary” i.e., all at 1 place, but
the “Error Messages” will be displayed beside the controls also and to avoid that, change the style code we have
defined for “<span>” tag that we have added in “<head>” section as below:

Old Code: <style>span { color: red;background-color: yellow;font-style: oblique }</style>


New Code: <style>span { display: none }</style>

ASP.NET MVC Request Life Cycle:

Routing: ASP.NET Routing is the first step in MVC request cycle. Basically, it is a pattern matching system that
matches the request’s URL against the registered URL patterns in the Route Table. When a matching pattern found
in the Route Table, the Routing engine forwards the request to the corresponding “IRouteHandler” for that request
and the default one calls the “MvcHandler”. The routing engine returns a 404 HTTP status code against that request
if the patterns are not found in the Route Table. When application starts at first time, it registers one or more
patterns to the Route Table to tell the routing system what to do with any requests that match these patterns. An
application has only one Route Table and this is setup in the “Global.asax” file of the application.

172
MvcHandler: The “MvcHandler” is responsible for initiating the real processing inside ASP.NET MVC. “MvcHandler”
implements “IHttpHandler” interface and further process the request by using “ProcessRequest” method.

Controller: “MvcHandler” uses the “IControllerFactory” instance and tries to get an “IController” instance. If
successful, then it calls the Execute method.

Action Execution: Once the controller has been instantiated, Controller’s “ActionInvoker” determines which specific
action to invoke on the controller. Action to be executed is chosen based on attributes
“ActionNameSelectorAttribute” (by default method which have the same name as the action is chosen) and
“ActionMethodSelectorAttribute” (If more than one method found, the correct one is chosen with the help of this
attribute).

View Result (Action Result): The action method receives user input, prepares the appropriate response data, and
then executes the result by returning a result type. The result type can be “ViewResult”, “RedirectToRouteResult”,
“PartialViewResult”, “RedirectResult”, “ContentResult”, “JsonResult”, “FileResult”, and “EmptyResult”.

View Engine: The first step in the execution of the View Result involves the selection of the appropriate View Engine
to render the View Result. It is handled by “IViewEngine” interface of the View Engine. By default, ASP.NET MVC
uses “Web Forms” and “Razor” view engines. You can also register your own custom view engine to your MVC
application.

View: Action method may return a text string, a binary file or a JSON formatted data. The most important Action
Result is the View Result, which renders and returns an HTML page to the browser by using the current View Engine.

Differences between ASP.NET Web Forms and ASP.NET MVC


First of all, lets’ be clear that ASP.NET MVC is not a replacement for ASP.NET Web Forms. Both these
development models exist and can be used to develop ASP.NET Web Applications.

ASP.NET Web Forms ASP.NET MVC


Web Forms uses Page Controller Pattern approach for MVC uses Front Controller Pattern approach. That
rendering layout. In this approach, every page has its approach means, a common controller for all pages,
own controller i.e., code-behind file that processes the processing the requests.
request.
Lots of server-side interactions and post backs. Very minimum post backs and interactions.
Web Form has file-based URLs means file name exist in MVC has route-based URLs means URLs are divided into
the URLs which must have it’s physically existence. controllers and actions and moreover it is based on a
controller but not on physical file.
No separation of concerns. As we discussed that every Very clean separation of concerns. View, Model and
page (.aspx) has its own controller i.e., code behind Controller are neatly separated.
“aspx.cs” file), so both are tightly coupled.
Because of this coupled behavior, automated testing is Testability is key feature in MVC. Test driven
difficult. development is quite simple using this approach.
To achieve stateful behavior, ViewState is used. MVC approach is stateless as that of the web. So here
Purpose was to give developers, the same experience there is no concept of ViewState.
of a typical Win Forms application.

173
Statefulness has lot of problems for web environment As controller and view are not dependent and no
i.e., excessively large ViewState. Large ViewState ViewState concept in MVC, so output is very clean.
means increase in page size.
Web Form follows Web Forms syntax. MVC follows customizable syntax both Web Forms as
well as Razor (default).
Web Forms model follows a complex Page Life Cycle. No Page Life Cycle like Web Forms. Request cycle is
simple in ASP.NET MVC model.
In Web Forms we have Server Controls; so minimal In MVC we have html helpers, so detailed knowledge of
knowledge of HTML and CSS is required. HTML and CSS is required.
Provides limited control over HTML, Java Script and CSS Full control over HTML, Java Script, and CSS.
which is necessary in many cases.
With lots of control libraries availability and limited It’s a step back for developers decreasing in the
knowledge of other related technologies, Web Forms is productivity.
RAD (Rapid Application Development) approach.
It’s good for small scale applications with limited team It’s better as well as recommended approach for large-
size. scale applications where different teams are working
together.
Response type can be HTML only and if we want any Response type can either be HTML, XML, JSON, etc.
other response type, we need to write some complex
code.

ASP.Net Web Forms Request Life Cycle:

174
Language Integrated Query
In C# 3.0 .Net has introduced a new language known as “LINQ” much like “SQL (which we use universally
with relational databases to perform queries)”. LINQ allows you to write query expressions like SQL queries that can
retrieve information from a wide variety of Data Sources like Objects, Relational Databases and XML.

Introduction to LINQ: LINQ stands for Language Integrated Query. LINQ is a data querying methodology which
provides querying capabilities to .NET languages with syntax like a SQL Query. LINQ has a great power of querying
from any source of data i.e., the Data Source can be collections of Objects, Relational Databases or XML.

LINQ to Objects: used to perform queries against the in-memory data like an Array or Collection.

LINQ to Databases:
 LINQ to DataSet’s is used to perform queries against ADO.NET Data Table’s.
 LINQ to SQL is used to perform CRUD Operations against Microsoft SQL Server Database.
 LINQ to Entities is used to perform CRUD Operations against any Relation Database like SQL Server, Oracle, etc.

LINQ to XML (XLinq): used to perform queries against the XML Source.

Advantages of LINQ:
 LINQ offers an object-based, language-integrated way to query over data, no matter where that data came from.
So, through LINQ we can query Database, XML as well as Collections and Arrays also.
 Compile time syntax checking.
 It allows us to Query - Collections, Arrays, & Classes etc. in the native language of our application like VB or C#.

LINQ to SQL
Probably the biggest and most exciting addition to the .Net Framework 3.5 is the addition of the .Net
Language Integrated Query Framework (LINQ) into C# 3.0. Basically, what LINQ provides is a lightweight façade over
programmatic data integration. This is such a big deal because data is King. Pretty much every application deal with
data in some manner, whether that data comes from memory, databases, XML files, text files, or something else.
Many developers find it very difficult to move from the strongly typed object-oriented world of C# to the data tier
where objects are second-class citizens. The transition from the one world to the next was a kludge at best and was
full of error-prone actions.

In C#, programming with objects means a wonderful strongly typed ability to work with code. You can
navigate very easily through the namespaces; work with a debugger in the Visual Studio IDE, and more. However,

175
when you must access data, you will notice that things are dramatically different. You end up in a world that is not
strongly typed, where debugging is a pain or even non-existent, and you end up spending most of the time sending
strings to the database as commands. As a developer, you also must be aware of the underlying data and how it is.

Microsoft has provided LINQ as a lightweight façade that provides a strongly typed interface to the
underlying data stores. LINQ provides the means for developers to stay within the coding environment they are used
to and access the underlying data as objects that work with the IDE, Intellisense, and even debugging. With LINQ,
the queries that you create now become first-class citizens within the .NET Framework alongside everything else you
are used to. When you work with queries for the data store you are working with, you will quickly realize that they
now work and behave as if they are types in the system. This means that you can now use any .NET-compliant
language and query the underlying data stores as you never have before.

LINQ to SQL and Visual Studio: LINQ to SQL in particular is a means to have a strongly typed interface against a SQL
Server Database. You will find the approach that LINQ to SQL provides is by far the easiest approach for querying
SQL Server available now. It is important to remember that LINQ to SQL is not only about querying data, but you can
also perform Insert/Update/Delete operations that you need to perform which are known as CRUD operations
(Create/Read/Update/Delete). Visual Studio comes into strong play with LINQ to SQL in that you will find an
extensive user interface that allows you to design the LINQ to SQL classes you will work with.

Adding a LINQ to SQL Class: To work with LINQ first you need to convert Relational Objects of Database into Object
Oriented Types of our language and the process of conversion is known as ORM (Object Relational Mapping) and to
perform this we are provided with a tool under Visual Studio i.e., OR Designer (Object-Relational Designer) which
does an outstanding job of making it as easy as possible.

To work with LINQ to SQL first create a Database in SQL Server with the name “MVCDB” and then create a
table with the name Student using the below SQL Statement:

Create Table Student (Sid Int Primary Key, Name Varchar(50), Class Int, Fees Money, Photo Varchar(100), Status Bit
Not Null Default 1)

Now create a new “ASP.NET Web Application” project, naming it as “MVCWithLinq1”, choose “MVC Project
Template” and click on Create button to create the Project. In the project created open Solution Explorer and under
the Models folder add the “OR Designer” and to do this open “Add New Item” Window, in the LHS of the Window
select “Data” and in the RHS select the option “Linq to SQL Classes” name the item as “MVCDB.dbml” (Database
Markup Language). We can give any name to the “.dbml” file but it is always suggested to use our Database name
as a name to this, because our database name is “MVCDB” we have named it as “MVCDB.dbml”, now click “Add”
button which will do the following:

 Adds a reference to “System.Data.Linq” assembly which is required to work with “LINQ to SQL”.
 Under “Models” folder of Solution Explorer we will find “MVCDB.dbml” and under it we will find 2 sub-items
“MVCDB.dbml.layout” and “MVCDB.Designer.cs” and under this file only “OR-Designer” writes all the “ORM”
code by converting “Relational Objects” into “Object Oriented Types”.
 The item “MVCDB.dbml” is added to the studio which will appear as a tab within the document window, and
this is made up of two parts. The first part on the left is for “Data Classes”, which map to Tables, Views, etc,
dragging such items on this surface will give us a visual representation of those objects. The second part on the
right is for Methods, which map to the Stored Procedures within the Database.

176
Let us have a look into the code of “MVCDB.designer.cs” file and there we will find a class
“MVCDBDataContext” inheriting from “DataContext” class of “System.Data.Linq” namespace. “DataContext” class
works with the “Connection String” and connects to the Database for any required operations when we create
instance of the class. “DataContext” class also contains methods in it like “CreateDatabase”, “DeleteDatabase”,
“GetTable”, “ExecuteQuery”, “SubmitChanges” etc, using which we can perform action directly on the Database.
The “MVCDBDataContext” class which is defined here by default contains 4 parameterized Constructors in it.

Creating the Student Entity: For this example, we want to work with the “Student” (Entity) table from the “MVCDB”
database, which means that you are going to create a “Student” (Entity) class that will use LINQ to SQL map to
Student table. To accomplishing this task simply open the “Server Explorer” within Visual Studio from “View” menu
and configure it with our Database i.e., “MVCDB”.

To configure the Database under “Server Explorer”, right click on “Data Connections” node and select the
option “Add Connection” which opens a window “Choose Data Source” and in that select “Microsoft SQL Server”
and click on “Ok” button, which opens another window “Add Connection”, in the new window under “Server name:”
TextBox enter your “Server Name”, under “Log on to the server” option choose the “Authentication Mode” and
provide the “Credentials”, under Encrypt DropDownList choose “Optional (False)”, and under “Connect to a
database” option choose your “Database” from “Select or enter a database name” DropDownList (Database name
is “MVCDB” in our case) and click on the “OK” button which adds the Database under “Data Connections” node.

Now drag and drop the “Student” table of our “MVCDB” Database onto the design surface of “O/R
Designer” in to LHS and this action will add a bunch of code in to “MVCDB.designer.cs” file on our behalf with a set
of classes in it, and those classes will give you a strongly typed access to the Student (Entity) table.

When we drag & drop the first object (Table or SP) on OR Designer it will perform the following actions:
 Writes Connection String in to “Web.config” file targeting to the Database we have configured in Server
Explorer.
 Defines a new default constructor in “MVCDBDataContext” class and we can use this constructor for creating
the instance of “MVCDBDataContext” class for connecting to the Database and this constructor will read the
Connection String from “Web.config” file whereas in the latest version this default Constructor is not defined,
so we need to use the existing parameterized constructor of “MVCDBDataContext” class that takes string as a
parameter and for that we need to pass the name of Connection String by reading it from “Web.config” file.

When we drag & drop a table on OR Designer the following actions gets performed internally:
 Defines a class representing the Entity (Table) we have dragged & dropped on the OR Designer where the name
of the class will be same as the table name, right now we have dropped “Student” table on OR Designer, so
“Student” class gets defined.
 Defines properties under the entity class (Student), where each property represents each attribute of the entity
(table). So, in the student class we will find the properties Sid, Name, Class, Fees, Photo and Status.
 Defines a property under “MVCDBDataContext” class referring to the table we are working with, and the type
of this property will be “Table<Entity>”, because we are working with “Student Entity” here the name of the
property will be “Students” and type of the property will be “Table<Student>”.

Note: Table<Entity> is a generic class under “System.Data.Linq” namespace which also contains a set of methods
like “DeleteOnSubmit”, “InsertOnSubmit”, “SingleOrDefault”, “FirstOrDefault”, “Single”, “First” etc. for performing
CRUD operations on the Entity.

177
Performing CRUD (Create (Insert), Read (Select), Update and Delete) Opertions: to Perform CRUD operations on
SQL Server Database by using Linq to SQL we need to adopt the below process for Insert, Update and Delete:

Steps for Inserting:


1. Create an instance of Model (Student) class, which is defined representing the Student Entity (Table) because
each instance is a record, and then assign values to properties because those properties represent attributes.
2. Call InsertOnSubmit method on the table (Students) which adds the record into the table in a pending state.
3. Call SubmitChanges method on DataContext object for saving the changes to Database server.

Steps for Updating:


1. Create a reference of Model (Student) class that has to be updated by calling First or FirstOrDefault or
SingleOrDefault or Single method on the table (Students).
2. Re-assign values to properties of reference so that old values get changed to new values.
3. Call SubmitChanges method on DataContext object for saving the changes to Database server.

Steps for Deleting:


1. Create a reference of Model (Student) class that must be deleted by calling First or FirstOrDefault or
SingleOrDefault or Single method on the table (Students).
2. Call DeleteOnSubmit method on the table (Students) that deletes the record from table in a pending state.
3. Call SubmitChanges method on DataContext object for saving the changes to Database server.

Add a class under Models folder with the name StudentDAL.cs and write the below code in it:
using System.Configuration;
public class StudentDAL
{
MVCDBDataContext context = new MVCDBDataContext(); //Old Version (If default constructor is defined)
Or
MVCDBDataContext context = new MVCDBDataContext(
ConfigurationManager.ConnectionStrings["MVCDBConnectionString"].ConnectionString); //New Version

public List<Student> GetStudents(bool? Status)


{
List<Student> students;
try
{
if(Status != null)
students = (from s in context.Students where s.Status == Status select s).ToList();
else
students = context.Students.ToList(); Or students = (from s in context.Students select s).ToList();
return students;
}
catch(Exception ex)
{
throw ex;
}
}

178
public Student GetStudent(int Sid, bool? Status)
{
Student student;
try
{
if (Status == null)
student = (from s in context.Students where s.Sid == Sid select s).Single();
else
student = (from s in context.Students where s.Sid == Sid && s.Status == Status select s).Single();
return student;
}
catch(Exception ex)
{
throw ex;
}
}
public void AddStudent(Student student)
{
try
{
context.Students.InsertOnSubmit(student);
context.SubmitChanges();
}
catch(Exception ex)
{
throw ex;
}
}
public void UpdateStudent(Student newValues)
{
try
{
Student oldValues = context.Students.Single(S => S.Sid == newValues.Sid);
oldValues.Name = newValues.Name;
oldValues.Class = newValues.Class;
oldValues.Fees = newValues.Fees;
oldValues.Photo = newValues.Photo;
context.SubmitChanges();
}
catch(Exception ex)
{
throw ex;
}
}
public void DeleteStudent(int Sid)
{

179
try
{
Student oldValues = context.Students.First(S => S.Sid == Sid);
//dc.Students.DeleteOnSubmit(oldValues); //Permenant Deletion
oldValues.Status = false; //Updates the status with-out deleting the record
context.SubmitChanges();
}
catch (Exception ex)
{
throw ex;
}
}
}

Add a Controller under the Controllers folder with the name StudentController and write the below code in it:
using System.IO;
using MVCWithLinq1.Models;
public class StudentController : Controller
{
StudentDAL obj = new StudentDAL();
public ViewResult DisplayStudents()
{
return View(obj.GetStudents(true));
}
public ViewResult DisplayStudent(int Sid)
{
return View(obj.GetStudent(Sid, true));
}
[HttpGet]
public ViewResult AddStudent()
{
return View();
}
[HttpPost]
public RedirectToRouteResult AddStudent(Student student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
//Checking whether the folder "Uploads" is exists or not and creating it if not exists
string PhysicalPath = Server.MapPath("~/Uploads/");
if(!Directory.Exists(PhysicalPath))
{
Directory.CreateDirectory(PhysicalPath);
}
selectedFile.SaveAs(PhysicalPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;

180
}
student.Status = true;
obj.AddStudent(student);
return RedirectToAction("DisplayStudents");
}
public ViewResult EditStudent(int Sid)
{
Student student = obj.GetStudent(Sid, true);
TempData["Photo"] = student.Photo;
return View(student);
}
public RedirectToRouteResult UpdateStudent(Student student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
string PhysicalPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(PhysicalPath))
{
Directory.CreateDirectory(PhysicalPath);
}
selectedFile.SaveAs(PhysicalPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
else if(TempData["Photo"] != null)
{
student.Photo = TempData["Photo"].ToString();
}
obj.UpdateStudent(student);
return RedirectToAction("DisplayStudents");
}
public RedirectToRouteResult DeleteStudent(int Sid)
{
obj.DeleteStudent(Sid);
return RedirectToAction("DisplayStudents");
}
}

Add a view with the name DisplayStudents.cshtml, selecting layout Checkbox and write the below code in it:
@model IEnumerable<MVCWithLinq1.Models.Student>
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>
<table border="1" align="center" class="table-condensed">
<tr>
<th>@Html.DisplayNameFor(S => S.Sid)</th>
<th>@Html.DisplayNameFor(S => S.Name)</th>
<th>@Html.DisplayNameFor(S => S.Class)</th>
<th>@Html.DisplayNameFor(S => S.Fees)</th>

181
<th>@Html.DisplayNameFor(S => S.Photo)</th>
<th>Actions</th>
</tr>
@foreach (MVCWithLinq1.Models.Student student in Model)
{
<tr>
<td>@Html.DisplayFor(S => student.Sid)</td>
<td>@Html.DisplayFor(S => student.Name)</td>
<td>@Html.DisplayFor(S => student.Class)</td>
<td>@Html.DisplayFor(S => student.Fees)</td>
<td><img src='/Uploads/@student.Photo' width="40" height="25" alt="No Image" /></td>
<td>
@Html.ActionLink("View", "DisplayStudent", new { Sid = student.Sid })
@Html.ActionLink("Edit", "EditStudent", new { Sid = student.Sid })
@Html.ActionLink("Delete", "DeleteStudent", new { Sid = student.Sid },
new { onclick = "return confirm('Are you sure of deleting the record?')" })
</td>
</tr>
}
<tr><td colspan="6" align="center">@Html.ActionLink("Add New Student", "AddStudent")</td></tr>
</table>

Add a view with the name DisplayStudent.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq1.Models.Student
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>
<table border="1" align="center">
<tr>
<td rowspan="4"><img src='~/Uploads/@Model.Photo' width="200" height="200" alt="No Image" /></td>
<td>Sid: @Model.Sid</td>
</tr>
<tr><td>Name: @Model.Name</td></tr>
<tr><td>Class: @Model.Class</td></tr>
<tr><td>Fees: @Model.Fees</td></tr>
<tr>
<td colspan="2" align="center">@Html.ActionLink("Back to Student Details", "DisplayStudents")</td>
</tr>
</table>

Add a view with the name AddStudent.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq1.Models.Student
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>
@using (Html.BeginForm("AddStudent", "Student", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid)</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>

182
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>@Html.LabelFor(S => S.Photo)<br /><input type="file" name="selectedFile" /></div>
<div>
<input type="submit" value="Save" />
<input type="reset" value="Reset" />
</div>
}
@Html.ActionLink("Back to Student Details", "DisplayStudents")

Add a view with the name EditStudent.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq1.Models.Student
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Student</h2>
@using (Html.BeginForm("UpdateStudent","Student",FormMethod.Post,new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid)</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>
@Html.LabelFor(S => S.Photo)<br />
<img src='~/Uploads/@Model.Photo' height="50" width="50" alt="No Image" style="border:dashed 2px red" />
<input type="file" name="selectedFile" />
</div>
<div>
<input type="submit" value="Update" />
@Html.ActionLink("Cancel", "DisplayStudents")
</div>
}

Calling Stored Procedures using LINQ


If we want to call Stored Procedures of SQL Server Database by using LINQ we need to first drag & drop
those Procedures on to the RHS panel of OR-Designer from Server Explorer, so that they get converted into methods
under our “DataContext” class i.e., “MVCDBDataContext” with the same name of Procedures. In this process if the
Stored Procedure has any parameters, then those parameters will be defined for Method also, i.e., “input”
parameters of Procedure will become “input” parameters of the Method and “output” parameters of the Procedure
will become “ref” parameters of the Method.

For example, if the below SP was dropped on RHS panel of OR-designer:


Create Procedure Add(@x int, @y int, @z int output)

A method gets defined under MVCDBDataContext class as following:


public int Add(int? x, int? y, ref int? z)

If the Procedure is defined to perform any Non-Query operations then return type of the method will be
integer, whereas if the Procedure is defined to perform Query operations then return type of the method will be
“ISingleResult<T>”, where “T” represents a class that is newly defined when we drag & drop the Query Procedure

183
and the name of the new class will be “SP Name” suffixed with “Result” i.e., for example if the Procedure name is
“Student_Select” then the class name will be “Student_SelectResult”.

To test calling Stored Procedures, create a new “ASP.NET Web Application” project, naming it as
“MVCWithLinq2” choose “MVC Project Template” and click on “Create” button. Now open “Solution Explorer” and
under the Models folder add “OR Designer” and to do that open “Add New Item” window, select the option “Linq
to SQL Classes”, name it as “MVCDB.dbml” and click on the Add button. Now open “Server Explorer” and configure
our “MVCDB” Database under it and create the below 4 Stored Procedure’s in the Database to perform CRUD
Operations on “Student” table.

To create a Procedure right click on the “Stored Procedures” node under the Database and select the option
“Add New Stored Procedure” which opens a window, write the Procedure code over there and after implementing
the code write click on the document window and select “Execute” which will create the Procedure in the Database.

CREATE Procedure Student_Select(@Sid Int=Null, @Status Bit=Null)


As
Begin
If @Sid Is Null And @Status Is Null --Fetches all the records of table
Select Sid, Name, Class, Fees, Photo From Student Order By Sid;
Else If @Sid Is Null And @Status Is Not Null --Fetches records based on Status
Select Sid, Name, Class, Fees, Photo From Student Where Status=@Status Order By Sid;
Else If @Sid Is Not Null And @Status Is Null --Fetches a single record based on Sid
Select Sid, Name, Class, Fees, Photo From Student Where Sid=@Sid;
Else If @Sid Is Not Null And @Status Is Not Null --Fetches a single record based on Sid & Status
Select Sid, Name, Class, Fees, Photo From Student Where Sid=@Sid And Status=@Status;
End;
Create Procedure Student_Insert(@Sid int, @Name varchar(50), @Class int, @Fees money, @Photo varchar(100)=null)
As
Insert Into Student (Sid, Name, Class, Fees,Photo) Values (@Sid, @Name, @Class, @Fees, @Photo)
Create Procedure Student_Update(@Sid int, @Name varchar(50), @Class int, @Fees money, @Photo varchar(100)=Null)
As
Update Student Set Name=@Name, Class=@Class, Fees=@Fees, Photo=@Photo Where Sid=@Sid;
Create Procedure Student_Delete(@Sid Int)
As
Update Student Set Status=0 Where Sid=@Sid;

Now drag and drop the 4 Stored Procedures we have defined above on to the RHS Panel of “OR Designer”,
which will generate the required methods in “MVCDBDataContext” class. It also generates a class with the name
“Student_SelectResult” mapping with the results retrieved by “Student_Select” Stored Procedure.

Note: In this case we don’t have “Student (Model)” class generated because we did not drag and drop “Student”
table on to the “OR-Designer”, so use “Student_SelectResult” class as your Model to perform Model Binding with
the Views.

Add a controller in Controllers folder naming it as StudentController.cs and write the below code in it:
using System.IO;

184
using System.Configuration;
using MVCWithLinq2.Models;
public class StudentController : Controller
{
MVCDBDataContext context = new MVCDBDataContext(); //Old Version (If default constructor is defined)
Or
MVCDBDataContext context = new MVCDBDataContext(
ConfigurationManager.ConnectionStrings["MVCDBConnectionString"].ConnectionString); //New Version
public ViewResult DisplayStudents()
{
List<Student_SelectResult> students = dc.Student_Select(null, true).ToList();
return View(students);
}
public ViewResult DisplayStudent(int Sid)
{
Student_SelectResult student = dc.Student_Select(Sid, true).ToList()[0];
return View(student);
}
[HttpGet]
public ViewResult AddStudent()
{
Student_SelectResult student = new Student_SelectResult();
return View(student);
}
[HttpPost]
public RedirectToRouteResult AddStudent(Student_SelectResult student, HttpPostedFileBase selectedFile)
{
if(selectedFile != null)
{
string folderPath = Server.MapPath("~/Uploads/");
if(!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
selectedFile.SaveAs(folderPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
dc.Student_Insert(student.Sid, student.Name, student.Class, student.Fees, student.Photo);
return RedirectToAction("DisplayStudents");
}
public ViewResult EditStudent(int Sid)
{
Student_SelectResult student = dc.Student_Select(Sid, true).ToList()[0];
TempData["Photo"] = student.Photo;
return View(student);
}

185
public RedirectToRouteResult UpdateStudent(Student_SelectResult student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
string folderPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
selectedFile.SaveAs(folderPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
else if(TempData["Photo"] != null) {
student.Photo = TempData["Photo"].ToString();
}
dc.Student_Update(student.Sid, student.Name, student.Class, student.Fees, student.Photo);
return RedirectToAction("DisplayStudents");
}
public RedirectToRouteResult DeleteStudent(int Sid)
{
dc.Student_Delete(Sid);
return RedirectToAction("DisplayStudents");
}
}

Add a view with the name DisplayStudents.cshtml, selecting layout Checkbox and write the below code in it:
@model IEnumerable<MVCWithLinq2.Models.Student_SelectResult>
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Students Details</h2>
<table border="1" align="center" class="table-condensed">
<tr>
<th>@Html.DisplayNameFor(S => S.Sid)</th>
<th>@Html.DisplayNameFor(S => S.Name)</th>
<th>@Html.DisplayNameFor(S => S.Class)</th>
<th>@Html.DisplayNameFor(S => S.Fees)</th>
<th>@Html.DisplayNameFor(S => S.Photo)</th>
<th>Actions</th>
</tr>
@foreach (MVCWithLinq2.Models.Student_SelectResult student in Model)
{
<tr>
<td>@Html.DisplayFor(S => student.Sid)</td>
<td>@Html.DisplayFor(S => student.Name)</td>
<td>@Html.DisplayFor(S => student.Class)</td>
<td>@Html.DisplayFor(S => student.Fees)</td>
<td><img src='/Uploads/@student.Photo' width="40" height="25" alt="No Image" /></td>
<td>

186
@Html.ActionLink("View", "DisplayStudent", new { Sid = student.Sid })
@Html.ActionLink("Edit", "EditStudent", new { Sid = student.Sid })
@Html.ActionLink("Delete", "DeleteStudent", new { Sid = student.Sid },
new { onclick = "return confirm('Are you sure of deleting the record?')" })
</td>
</tr>
}
<tr><td colspan="6" align="center">@Html.ActionLink("Add New Student", "AddStudent")</td></tr>
</table>

Add a view with the name DisplayStudent.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq2.Models.Student_SelectResult
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>
<table border="1" align="center">
<tr>
<td rowspan=4><img src='~/Uploads/@Model.Photo' width="200" height="200" alt="No Image" /></td>
<td>Sid: @Model.Sid</td>
</tr>
<tr><td>Name: @Model.Name</td></tr>
<tr><td>Class: @Model.Class</td></tr>
<tr><td>Fees: @Model.Fees</td></tr>
<tr><td colspan="2" align="center">@Html.ActionLink("Back to Student Details", "DisplayStudents")</td></tr>
</table>

Add a view with the name AddStudent.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq2.Models.Student_SelectResult
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>
@using (Html.BeginForm("AddStudent", "Student", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid)</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>@Html.LabelFor(S => S.Photo)<br /><input type="file" name="selectedFile" /></div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" name="btnReset" />
</div>
}
@Html.ActionLink("Back to Student Details", "DisplayStudents")

Add a view with the name EditStudent.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq2.Models.Student_SelectResult
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Student Details</h2>
@using (Html.BeginForm("UpdateStudent","Student", FormMethod.Post, new { enctype="multipart/form-data" }))

187
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid, new { @readonly = "true" })</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>
@Html.LabelFor(S => S.Photo)
<br />
<img src='~/Uploads/@Model.Photo' width="50" height="50" alt="No Image" style="border:dashed 2px red" />
<input type="file" name="selectedFile" />
</div>
<div>
<input type="submit" value="Update" name="btnUpdate" />
@Html.ActionLink("Cancel", "DisplayStudents")
</div>
}

Working with multiple tables using Linq to SQL


We can work with multiple tables that are present under Database which have a relationship with each
other by using LINQ, but to do that we need to define a model class that contains attributes of both the Entities. To
test this, create 2 new tables under our “MVCDB” Database with the name “Department” and “Employee”, and
insert few records into “Department” table as following:

Create Table Department(Did Int Constraint Did_PK Primary Key Identity(10, 10), Dname Varchar(50), Location
Varchar(50));
Insert Into Department Values ('Marketing ', 'Mumbai ');
Insert Into Department Values ('Sales ', 'Chennai ');
Insert Into Department Values ('Accounting ', 'Hyderabad ');
Insert Into Department Values ('Finance ', 'Delhi ');
Create Table Employee(Eid Int Constraint Eid_PK Primary Key Identity(1001, 1), Ename Varchar(50), Job Varchar(50),
Salary Money, Did Int Constraint Did_FK References Department(Did), Status Bit Not Null default 1);

To test working with multiple tables, create a new “ASP.NET Web Application” project, naming it as
“MVCWithLinq3”, choose “MVC Project Template” and click on the “Create” button. Now under the Models folder
add “OR Designer” naming it as “MVCDB.dbml”. Configure our “MVCDB” Database under “Server Explorer” and then
drag & drop “Department” and “Employee” Tables on the LHS Panel of OR Designer. Now under Models folder add
a Class with the name “EmpDept.cs” that combines the properties of Employee & Department model classes, and
write the below code in it:

using System.Web.Mvc;
public class EmpDept
{
public int Eid { get; set; }
public string Ename { get; set; }
public string Job { get; set; }
public decimal? Salary { get; set; }

188
public int Did { get; set; }
public string Dname { get; set; }
public string Location { get; set; }
public List<SelectListItem> Departments { get; set; }
}

Add another class under Models folder with the name EmployeeDAL.cs and write the below code in it:
using System.Web.Mvc;
public class EmployeeDAL
{
MVCDBDataContext context = new MVCDBDataContext(); //Old Version (If default constructor is defined)
Or
MVCDBDataContext context = new MVCDBDataContext(
ConfigurationManager.ConnectionStrings["MVCDBConnectionString"].ConnectionString); //New Version
public List<SelectListItem> GetDepartments()
{
List<SelectListItem> Depts = new List<SelectListItem>();
foreach (var Item in dc.Departments)
{
SelectListItem li = new SelectListItem { Text = Item.Dname, Value = Item.Did.ToString() };
Depts.Add(li);
}
return Depts;
}
public EmpDept GetEmployee(int Eid, bool? Status)
{
dynamic Record;
if (Status == null)
{
Record = (from E in dc.Employees join D in dc.Departments on E.Did equals D.Did where E.Eid == Eid select
new { E.Eid, E.Ename, E.Job, E.Salary, D.Did, D.Dname, D.Location }).Single();
}
else
{
Record = (from E in dc.Employees join D in dc.Departments on E.Did equals D.Did where E.Eid == Eid &&
E.Status == Status select new { E.Eid, E.Ename, E.Job, E.Salary, D.Did, D.Dname, D.Location }).Single();
}
EmpDept Emp = new EmpDept { Eid = Record.Eid, Ename = Record.Ename, Job = Record.Job,
Salary = Record.Salary, Did = Record.Did, Dname = Record.Dname, Location = Record.Location };
return Emp;
}
public List<EmpDept> GetEmployees(bool? Status)
{
dynamic Records;
if (Status != null)
{

189
Records = from E in dc.Employees join D in dc.Departments on E.Did equals D.Did where E.Status == Status
select new { E.Eid, E.Ename, E.Job, E.Salary, D.Did, D.Dname, D.Location };
}
else
{
Records = from E in dc.Employees join D in dc.Departments on E.Did equals D.Did select new { E.Eid, E.Ename,
E.Job, E.Salary, D.Did, D.Dname, D.Location };
}
List<EmpDept> Emps = new List<EmpDept>();
foreach (var Record in Records) {
EmpDept Emp = new EmpDept { Eid = Record.Eid, Ename = Record.Ename, Job = Record.Job,
Salary = Record.Salary, Did = Record.Did, Dname = Record.Dname, Location = Record.Location };
Emps.Add(Emp);
}
return Emps;
}
public void Employee_Insert(EmpDept obj)
{
Employee Emp = new Employee { Ename = obj.Ename, Job = obj.Job, Salary = obj.Salary, Did = obj.Did,
Status = true };
dc.Employees.InsertOnSubmit(Emp);
dc.SubmitChanges();
}
public void Employee_Update(EmpDept NewValues)
{
Employee OldValues = dc.Employees.Single(E => E.Eid == NewValues.Eid);
OldValues.Ename = NewValues.Ename;
OldValues.Job = NewValues.Job;
OldValues.Salary = NewValues.Salary;
OldValues.Did = NewValues.Did;
dc.SubmitChanges();
}
public void Employee_Delete(int Eid)
{
Employee OldValues = dc.Employees.Single(E => E.Eid == Eid);
OldValues.Status = false;
dc.SubmitChanges();
}
}

Add a Controller under Controllers folder with the name EmployeeController.cs and write the below code in it:
using MVCWithLinq3.Models;
public class EmployeeController : Controller
{
EmployeeDAL obj = new EmployeeDAL();
public ViewResult DisplayEmployees()

190
{
return View(obj.GetEmployees(true));
}
public ViewResult DisplayEmployee(int eid)
{
return View(obj.GetEmployee(eid, true));
}
[HttpGet]
public ViewResult AddEmployee()
{
EmpDept emp = new EmpDept();
emp.Departments = obj.GetDepartments();
return View(emp);
}
[HttpPost]
public RedirectToRouteResult AddEmployee(EmpDept emp)
{
obj.Employee_Insert(emp);
return RedirectToAction("DisplayEmployees");
}
public ViewResult EditEmployee(int eid)
{
EmpDept Emp = obj.GetEmployee(eid, true);
Emp.Departments = obj.GetDepartments();
return View(Emp);
}
public RedirectToRouteResult UpdateEmployee(EmpDept emp)
{
obj.Employee_Update(emp);
return RedirectToAction("DisplayEmployees");
}
public RedirectToRouteResult DeleteEmployee(int eid)
{
obj.Employee_Delete(eid);
return RedirectToAction("DisplayEmployee");
}
}

Add a view with the name DisplayEmployees.cshtml, selecting layout Checkbox and write the below code in it:
@model IEnumerable<MVCWithLinq3.Models.EmpDept>
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Employee Details</h2>
<table border="1" align="center">
<tr>
<th>@Html.DisplayNameFor(E => E.Eid)</th>
<th>@Html.DisplayNameFor(E => E.Ename)</th>
<th>@Html.DisplayNameFor(E => E.Job)</th>

191
<th>@Html.DisplayNameFor(E => E.Salary)</th>
<th>@Html.DisplayNameFor(E => E.Did)</th>
<th>@Html.DisplayNameFor(E => E.Dname)</th>
<th>@Html.DisplayNameFor(E => E.Location)</th>
<th>Actions</th>
</tr>
@foreach (var Employee in Model)
{
<tr>
<td>@Html.DisplayFor(E => Employee.Eid)</td>
<td>@Html.DisplayFor(E => Employee.Ename)</td>
<td>@Html.DisplayFor(E => Employee.Job)</td>
<td>@Html.DisplayFor(E => Employee.Salary)</td>
<td>@Html.DisplayFor(E => Employee.Did)</td>
<td>@Html.DisplayFor(E => Employee.Dname)</td>
<td>@Html.DisplayFor(E => Employee.Location)</td>
<td>
@Html.ActionLink("View", "DisplayEmployee", new { Eid = Employee.Eid })
@Html.ActionLink("Edit", "EditEmployee", new { Eid = Employee.Eid })
@Html.ActionLink("Delete", "DeleteEmployee", new { Eid = Employee.Eid },
new { onclick = "return confirm('Are you sure of deleting the record?')" })
</td>
</tr>
}
<tr><td colspan="8" align="center">@Html.ActionLink("Add New Employee", "AddEmployee")</td></tr>
</table>

Add a view with the name DisplayEmployee.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq3.Models.EmpDept
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Employee Details</h2>
<table border="1" align="center">
<tr> <td>Eid:</td> <td>@Model.Eid</td> </tr>
<tr> <td>Ename:</td> <td>@Model.Ename</td> </tr>
<tr> <td>Job:</td> <td>@Model.Job</td> </tr>
<tr> <td>Salary:</td> <td>@Model.Salary</td> </tr>
<tr> <td>Did:</td> <td>@Model.Did</td> </tr>
<tr> <td>Dname:</td> <td>@Model.Dname</td> </tr>
<tr> <td>Location:</td> <td>@Model.Location</td> </tr>
<tr>
<td colspan="2" align="center">@Html.ActionLink("Back to Employee Details", "DisplayEmployees")</td>
</tr>
</table>

Add a view with the name AddEmployee.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq3.Models.EmpDept
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Employee</h2>

192
@using (Html.BeginForm("AddEmployee", "Employee"))
{
<div>@Html.LabelFor(E => E.Ename)<br />@Html.TextBoxFor(E => E.Ename)</div>
<div>@Html.LabelFor(E => E.Job)<br />@Html.TextBoxFor(E => E.Job)</div>
<div>@Html.LabelFor(E => E.Salary)<br />@Html.TextBoxFor(E => E.Salary)</div>
<div>
@Html.LabelFor(E => E.Dname)<br />
@Html.DropDownListFor(E => E.Did, Model.Departments, "-Select Dept-")
</div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" name="btnReset" />
</div>
}
@Html.ActionLink("Back to Display Employees", "DisplayEmployees")

Add a view with the name EditEmployee.cshtml, selecting layout Checkbox and write the below code in it:
@model MVCWithLinq3.Models.EmpDept
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Employee Details</h2>
@using (Html.BeginForm("UpdateEmployee", "Employee"))
{
<div>@Html.LabelFor(E => E.Eid)<br />@Html.TextBoxFor(E => E.Eid, new { @readonly = "true" })</div>
<div>@Html.LabelFor(E => E.Ename)<br />@Html.TextBoxFor(E => E.Ename)</div>
<div>@Html.LabelFor(E => E.Job)<br />@Html.TextBoxFor(E => E.Job)</div>
<div>@Html.LabelFor(E => E.Salary)<br />@Html.TextBoxFor(E => E.Salary)</div>
<div>@Html.LabelFor(E => E.Dname)<br />@Html.DropDownListFor(E => E.Did, Model.Departments)</div>
<div>
<input type="submit" value="Update" name="btnUpdate" />
@Html.ActionLink("Cancel", "DisplayEmployees")
</div>
}

Note: while working with multiple tables, model binding is done with the class we have defined representing the 2
tables i.e., “EmpDept”, whereas while performing CRUD operations we will be working with the original Model class
only i.e., “Employee” or “Department”.

193
Entity Framework
Prior to .NET 3.5, we (developers) often used to write “ADO.NET” code to save or retrieve application data
from the underlying Database. We used to open a connection to the Database, create a “DataSet” or “DataReader”
to fetch or submit the data to the Database and in this process, we convert data present in the “DataSet” or
“DataReader” to .NET objects or vice-versa to apply business rules. This was a cumbersome and error prone process.
Microsoft has provided a framework called “Entity Framework” to automate all these Database related activities for
your application.

Entity Framework is an open source “ORM Framework” for .NET Applications supported by Microsoft. It
enables developers to work with data using objects of domain specific classes without focusing on the underlying
Database or Tables and Columns where this data is stored. With Entity Framework, developers can work at a higher
level of abstraction when they deal with data and can create and maintain data-oriented applications with less code
compared with traditional applications. “Entity Framework is an Object-Relational Mapper (O/RM) that enables .NET
developers to work with a Database using .NET Objects. It eliminates the need for most of the data-access code that
developers usually need to write.”

As per the above figure, Entity Framework fits between the business entities (domain classes) and the
Database. It saves data stored in the properties of business entities and retrieves data from the Database and
converts it to business entity objects automatically.

Entity Framework Versions: Microsoft introduced Entity Framework in 2008 with .NET Framework 3.5 SP1. Since
then, it released many versions of Entity Framework. Currently, there are two latest versions of Entity Framework:
“EF 6” and “EF Core”. The following table lists important difference between EF 6 and EF Core.

EF 6 Version History:
EF 3.5,
EF 4.0, EF 4.1, EF 4.1.1, EF 4.2, EF 4.3, EF 4.3.1,
EF 5.0,
EF 6.0, EF 6.0.1, EF 6.0.2, EF 6.1.0, EF 6.1.1, EF 6.1.2, EF 6.1.3, EF 6.2.0, EF 6.3.0, EF 6.4.0, EF 6.4.4, EF 6.5.1 (Current
Latest Version)

194
EF Core Version History:
EF Core 1.0, EF Core 1.1
EF Core 2.0, EF Core 2.1, EF Core 2.2
EF Core 3.0, EF Core 3.1
EF Core 5.0, EF Core 6.0, EF Core 7.0, EF Core 8.0, EF Core 9.0 (Current Latest Version)

Entity Framework Features:


 Cross-platform: EF Core is a cross-platform framework which can run on Windows, Linux, and Mac.
 Modelling: EF (Entity Framework) creates an EDM (Entity Data Model) based on POCO (Plain Old CLR Object)
entities with get/set properties of different data types. It uses this model when querying or saving entity data
to the underlying Database.
 Querying: EF allows us to use LINQ queries to retrieve data from the underlying database. The database provider
will translate this LINQ queries to the database-specific query language (e.g., SQL for a relational database). EF
also allows us to execute raw SQL queries directly to the database.
 Change Tracking: EF keeps track of changes occurred to instances of your entities (Property values) which need
to be submitted to the Database.
 Saving: EF executes INSERT, UPDATE, and DELETE commands to the database based on the changes occurred
to your entities when you call the SaveChanges() method.
 Concurrency: EF uses Optimistic Concurrency by default to protect overwriting changes made by another user
since data was fetched from the database.
 Transactions: EF performs automatic transaction management while querying or saving data. It also provides
options to customize transaction management.
 Caching: EF includes first level of caching out of the box. So, repeated querying will return data from the cache
instead of hitting the Database.
 Built-in Conventions: EF follows conventions over the configuration programming pattern and includes a set of
default rules which automatically configure the EF model.
 Configurations: EF allows us to configure the EF model by using Data Annotation attributes or Fluent API to
override default conventions.
 Migrations: EF provides a set of migration commands that can be executed on the NuGet Package Manager
Console or the Command Line Interface to create or manage underlying database Schema.

Development Approaches with Entity Framework: There are 3 different approaches you can use while developing
your application using Entity Framework:
 Database-First
 Code-First
 Model-First

Database-First Approach: in this approach we generate the context and entity classes (model classes) for an existing
Database using EDM Wizard which is integrated into Visual Studio or executing EF commands.

Note: EF 6 supports the database-first approach extensively whereas EF Core includes limited support for this.

195
Code-First Approach: in this approach we don’t have any existing Database for our application and in such case, we
start writing our entities (model) and context classes first, and then generate the Database from these classes using
migration commands. Developers who follow the “Domain-Driven Design (DDD)” principles, prefer to begin with
coding their domain classes first and then generate the Database required to persist their data.

Model-First Approach: In this approach, you create entities, relationships, and inheritance hierarchies directly on
the visual designer integrated in Visual Studio and then generate entities, context class, and the Database script from
your visual model.

Note: EF 6 includes limited support for this, and EF Core does not support this approach.

Choosing a Development Approach for our Application: use the following flow chart to decide which will be the
right approach to develop an application using Entity Framework:

Database First Approach


To work with Entity Framework, create a new “ASP.NET Web Application” project naming it as
“MVCWithEFDBF1”, choose “MVC Project Template” and click on “Create” button. Now open Solution Explorer, right
click on the Models folder and choose “Add => New Item” option and in the window opened select the item
“ADO.NET Entity Data Model”, name it as “TestEF.edmx”, click “Ok” which opens a wizard and in that select the
option “EF Designer from database” => click “Next” and in the window opened click on “New Connection” button
and enter the connection details for our “MVCDB” Database and click “Ok” button which will close the “New
Connection” window, now select the radio button “Yes, include the sensitive data in the connection string.” => click
“Next” button, choose the radio button “Entity Framework 6.x” => click “Next” button which will connect to Data
Source and loads all the objects from there. Under tables select our “Department” and “Employee” tables and click
“Finish”, which generates all the classes that are necessary for working with tables.

196
Under solution explorer if we expand “TestEF.edmx” item we find “TestEF.Context.tt” and if we expand this
we find “TestEF.context.cs” and if we expand this we find “MVCDBEntities” item and if we double click on it, it opens
“TestEF.context.cs” file and there we find a class with the name “MVCDBEntities” (DataContext class) inheriting from
“DbContext”. DbContext is the main class that is responsible for interacting with the Database and it can perform
the following activities:

 Querying: Converts “LINQ-to-Entities” Queries to SQL Queries and sends them to the Database.
 Change Tracking: Keeps track of changes that occurred on the entities after Querying from the Database.
 Persisting Data: Performs the Insert, Update and Delete operations to the Database, based on entity states.
 Caching: Provides first level caching by default. It stores the entities which have been retrieved during the life
time of a context class.
 Manage Relationship: Manages relationships using CSDL, MSL and SSDL in Db-First or Model-First approach,
and using fluent API configurations in Code-First approach.
 Object Materialization: Converts raw data from the Database into Entity Objects.

Under MVCDBEntities class the code will be as following:


public partial class MVCDBEntities : DbContext
{
public MVCDBEntities() : base("name=MVCDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Department> Departments { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
}

Note: Departments and Employees properties of the above class provide a collection of Department and Employee
entities as “DbSet<TEntity>” type using which we can access all the data from corresponding tables and perform
CRUD Operations.

Now expand “TestEF.tt” and there we find “Department.cs” file which contains the Entity i.e., Department
class (representing Department table) with all of its attributes (properties or columns), and also “Employee.cs” file
which contains the Entity i.e., Employee class (representing Employee table) with all of its attributes (properties or
columns) and in this class we also find a property “Department” (Navigation Property) which refers to the
“Department” (1 to 1 relationship) entity which is the parent table for “Employee”. Same as the above under
“Department” class we find a property “Employees” (Navigation Property) referring to “Employees” (1 to many
relationship) corresponding to each Department.

197
Under “Department” & “Employee” classes the code will be as following:
public partial class Department
{
public Department() {
this.Employees = new HashSet<Employee>();
}
public int Did { get; set; }
public string Dname { get; set; }
public string Location { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}

public partial class Employee


{
public int Eid { get; set; }
public string Ename { get; set; }
public string Job { get; set; }
public Nullable<decimal> Salary { get; set; }
public Nullable<int> Did { get; set; }
public bool Status { get; set; }
public virtual Department Department { get; set; }
}

Generating Controllers and Views using Scaffolding: we are provided with an option of generating the required
Controllers, Action Methods and Views by using Scaffolding and to do that first build the project, and then right click
on the Controllers folder and select “Add” => “Controller” which opens “Add New Scaffolded Item” window, in that
window choose “MVC5 Controller with views, using EntityFramework” and click on “Add” button which opens “Add
Controller” window , now in that window select “Model class” as “Employee”, “Data context class” as
“MVCDBEntities”, and in the bottom it will display a name to the controller i.e., “EmployeesController” (either leave
the same or change to EmployeeController) and click on “Add” button which will generate a Controller with all the
required “Action Methods” and corresponding views to perform CRUD Operations. Run the project and watch the
behaviour of the whole application by performing CRUD Operations.

Performing CRUD operations manually without using Scaffolding: Open a new “ASP.NET Web Application” project
naming it as “MVCWithEFDBF2”, choose “MVC Project Template” and click on “Create” button. Now open the
solution explorer right click on the Models folder and open the “Add New Item” window and select the item
“ADO.NET Entity Data Model” and name it as “TestEF.edmx” and click “Ok” which opens a wizard and in that select
the option “EF Designer from database” and click “Next” and in the window opened click on “New Connection”
button and enter the connection details for our “MVCDB” database and then select the radio button “Yes, include
the sensitive data in the connection string.”, click “Next” button, choose the radio button “Entity Framework 6.x”,
click “Next” button which will connect to data sources and load all the object from it, now under tables select our
“Department” and “Employee” tables we have and click Finish, which generates all the classes that are necessary
for working with database. Now add a controller under Controller’s folder naming it as “EmployeeController.cs” and
write the below code:

using System.Data.Entity;
using MVCWithEFDBF2.Models;

198
public class EmployeeController : Controller
{
MVCDBEntities dc = new MVCDBEntities();
public ViewResult DisplayEmployees()
{
var Emps = dc.Employees.Where(E => E.Status == true);
return View(Emps);
}
public ViewResult DisplayEmployee(int Eid)
{
var Emp = dc.Employees.Find(Eid);
return View(Emp);
}
public ViewResult AddEmployee()
{
ViewBag.Did = new SelectList(dc.Departments, "Did", "Dname");
return View();
}
[HttpPost]
public RedirectToRouteResult AddEmployee(Employee Emp)
{
Emp.Status = true;
dc.Employees.Add(Emp);
dc.SaveChanges();
return RedirectToAction("DisplayEmployees");
}
public ViewResult EditEmployee(int Eid)
{
Employee Emp = dc.Employees.Find(Eid);
ViewBag.Did = new SelectList(dc.Departments, "Did", "Dname", Emp.Did);
return View(Emp);
}
public RedirectToRouteResult UpdateEmployee(Employee Emp)
{
Emp.Status = true;
dc.Entry(Emp).State = EntityState.Modified;
dc.SaveChanges();
return RedirectToAction("DisplayEmployees");
}
public ViewResult DeleteEmployee(int Eid)
{
Employee Emp = dc.Employees.Find(Eid);
return View(Emp);
}
[HttpPost]
public RedirectToRouteResult DeleteEmployee(Employee Emp)

199
{
//If we want to update the status of employee use the below code:
dc.Entry(Emp).State = EntityState.Modified;
//If we want to delete the record permanently comment the above statement and un-comment the below:
//dc.Entry(Emp).State = EntityState.Deleted;
dc.SaveChanges();
return RedirectToAction("DisplayEmployees");
}
}
Add a view with the name DisplayEmployees.cshtml, selecting layout Checkbox and write the below code
in it by deleting the whole content in the View:

@model IEnumerable<MVCWithEFDBF2.Models.Employee>
@{
ViewBag.Title = "Display Employees";
}
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Employee Details</h2>
<table border="1" align="center">
<tr>
<th>@Html.DisplayNameFor(E => E.Eid)</th>
<th>@Html.DisplayNameFor(E => E.Ename)</th>
<th>@Html.DisplayNameFor(E => E.Job)</th>
<th>@Html.DisplayNameFor(E => E.Salary)</th>
<th>@Html.DisplayNameFor(E => E.Status)</th>
<th>@Html.DisplayNameFor(E => E.Did)</th>
<th>@Html.DisplayNameFor(E => E.Department.Dname)</th>
<th>@Html.DisplayNameFor(E => E.Department.Location)</th>
<th>Actions</th>
</tr>
@foreach (var Employee in Model)
{
<tr>
<td>@Html.DisplayFor(E => Employee.Eid)</td>
<td>@Html.DisplayFor(E => Employee.Ename)</td>
<td>@Html.DisplayFor(E => Employee.Job)</td>
<td align="right">@Html.DisplayFor(E => Employee.Salary)</td>
<td align="center">@Html.DisplayFor(E => Employee.Status)</td>
<td align="center">@Html.DisplayFor(E => Employee.Did)</td>
<td>@Html.DisplayFor(E => Employee.Department.Dname)</td>
<td>@Html.DisplayFor(E => Employee.Department.Location)</td>
<td>
@Html.ActionLink("View", "DisplayEmployee", new { Eid = Employee.Eid })
@Html.ActionLink("Edit", "EditEmployee", new { Eid = Employee.Eid })
@Html.ActionLink("Delete", "DeleteEmployee", new { Eid = Employee.Eid })
</td>
</tr>

200
}
<tr><td colspan="9" align="center">@Html.ActionLink("Add New Employee", "AddEmployee")</td></tr>
</table>
Generate a view for DisplayEmployee action method and while adding the View, choose the Template as
Empty, Model Class as Employee, choose “Use a layout page” CheckBox in the “Add View” window and write the
below code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Employee Details</h2>


<table border="1" align="center">
<tr><td>Eid:</td><td>@Model.Eid</td></tr>
<tr><td>Ename:</td><td>@Model.Ename</td></tr>
<tr><td>Job:</td><td>@Model.Job</td></tr>
<tr><td>Salary:</td><td>@Model.Salary</td></tr>
<tr><td>Status:</td><td>@Html.DisplayFor(E => E.Status)</td></tr>
<tr><td>Did:</td><td>@Model.Did</td></tr>
<tr><td>Dname:</td><td>@Model.Department.Dname</td></tr>
<tr><td>Location:</td><td>@Model.Department.Location</td></tr>
<tr>
<td colspan="2" align="center">@Html.ActionLink("Back to Employee Details", "DisplayEmployees")</td>
</tr>
</table>
Generate a view for AddEmployee action method and while adding the View, choose the Template as
Empty, Model Class as Employee, choose “Use a layout page” CheckBox in the “Add View” window and write the
below code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Employee</h2>


@using (Html.BeginForm("AddEmployee", "Employee"))
{
<div>@Html.LabelFor(E => E.Ename)<br />@Html.TextBoxFor(E => E.Ename)</div>
<div>@Html.LabelFor(E => E.Job)<br />@Html.TextBoxFor(E => E.Job)</div>
<div>@Html.LabelFor(E => E.Salary)<br />@Html.TextBoxFor(E => E.Salary)</div>
<div><label>Department</label><br />@Html.DropDownList("Did", "-Select Department-")</div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" name="btnReset" />
</div>
}
@Html.ActionLink("Back to Employee Details", "DisplayEmployees")
Generate a view for EditEmployee action method and while adding the View, choose the Template as
Empty, Model Class as Employee, choose “Use a layout page” CheckBox in the “Add View” window and write the
below code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Employee</h2>


@using (Html.BeginForm("UpdateEmployee", "Employee"))
{
@Html.HiddenFor(E => E.Eid)

201
<div>@Html.LabelFor(E => E.Ename)<br />@Html.TextBoxFor(E => E.Ename)</div>
<div>@Html.LabelFor(E => E.Job)<br />@Html.TextBoxFor(E => E.Job)</div>
<div>@Html.LabelFor(E => E.Salary)<br />@Html.TextBoxFor(E => E.Salary)</div>
<div><label>Department</label><br />@Html.DropDownList("Did")</div>
<div>
<input type="submit" value="Update" name="btnUpdate" />
@Html.ActionLink("Cancel", "DisplayEmployees")
</div>
}

Generate a view for DeleteEmployee action method and while adding the View, choose the Template as
Empty, Model Class as Employee, choose “Use a layout page” CheckBox in the “Add View” window and write the
below code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Delete Employee</h2>


@using (Html.BeginForm("DeleteEmployee", "Employee"))
{
<table border="1">
<tr><td>Eid:</td><td>@Html.TextBoxFor(E => E.Eid, new { @readonly = "true" })</td></tr>
<tr><td>Ename:</td><td>@Html.TextBoxFor(E => E.Ename, new { @readonly = "true" })</td></tr>
<tr><td>Job:</td><td>@Html.TextBoxFor(E => E.Job, new { @readonly = "true" })</td></tr>
<tr><td>Salary:</td><td>@Html.TextBoxFor(E => E.Salary, new { @readonly = "true" })</td></tr>
<tr><td>Did:</td><td>@Html.TextBoxFor(E => E.Did, new { @readonly = "true" })</td></tr>
</table>
<font color="red">Are you sure of deleting the current record?</font>
<input type="submit" value="Yes" /><br />
@Html.ActionLink("Cancel", "DisplayEmployees")
}

Eager Loading Vs Lazy Loading in Entity Framework: eager loading is the process whereby a query for one type of
entity also loads related entities as part of the query, so that we don’t need to execute a separate query for related
entities. Eager loading is achieved using Include() method.

In our above project under the “DisplayEmployees” action method we have accessed data of Employee
entity as following:

var Emps = dc.Employees.Where(E => E.Status == true);

Default loading is lazy loading only and if we want to use eager loading then we need to first set
“<DbContextClass>.Configuration.LazyLoadingEnabled = false”, and the above code should be replaced as below:

dc.Configuration.LazyLoadingEnabled = false;
var Emps = dc.Employees.Where(E => E.Status == true).Include(E => E.Department);

To enable eager loading in “DisplayEmployees” and “DisplayEmployee” methods re-write the code under
both the methods as below:

202
public ViewResult DisplayEmployees()
{
dc.Configuration.LazyLoadingEnabled = false;
var Emps = dc.Employees.Where(E => E.Status == true).Include(E => E.Department);
return View(Emps);
}
public ViewResult DisplayEmployee(int Eid)
{
dc.Configuration.LazyLoadingEnabled = false;
var Emp = dc.Employees.Where(E => E.Eid == Eid).Include(E => E.Department).Single();
return View(Emp);
}

Lazy loading is delaying the loading of related data, until you specifically request for it. It is the opposite of
eager loading. For example, the Employee entity contains the Department entity. In the lazy loading, the context
first loads the Employee entity data from the Database, and then it will load the Department entity when we access
the Department property.
MVCDBEntities dc = new MVCDBEntities();
List<Employee> Emps = dc.Employees.ToList(); //Loads Employees details only
Department Dept = Emps[0].Department; //Loads Department for particular Employee only

To convert the above code to eager loading, re-write it as below:


MVCDBEntities dc = new MVCDBEntities();
dc.Configuration.LazyLoadingEnabled = false;
List<Employee> Emps = dc.Employees.Include(E => E.Department).ToList();
Department Dept = Emps[0].Department;

Calling Stored Procedures and performing CRUD Operations


Create a new “ASP.NET Web Application” project naming it as “MVCWithEFDBF3”, choose “MVC Project
Template” and click on “Create” button. Now open Solution Explorer, right click on the Models folder, open the “Add
New Item” window and select the item “ADO.NET Entity Data Model” naming it as “TestEF.edmx” and click “Ok”,
this opens a wizard and in that select the option “EF Designer from database” and click “Next”, in the window opened
click on “New Connection” button and enter the connection details for our “MVCDB” database and then select the
radio button “Yes, include the sensitive data in the connection string.” and click “Next” button, in the new window
choose the radio button “Entity Framework 6.x” and click “Next” button which will connect to data sources and load
all the object from it, now under Stored Procedures node select our Student_Select, Student_Insert, Student_Update
and Student_Delete Stored Procedures we have created earlier and click Finish, which generates Methods mapping
with Stored Procedures under MVCDBEntities class and the Method names will be same as Procedure names.

In our Procedures, we have a Select Procedure which is fetching 5 columns out of the 6 columns present in
our table so mapping to the results of this Stored Procedure, Entity Framework defines a new class whose name will
be <ProcedureName>_Result, because the procedure name is Student_Select, the class name will be
“Student_Select_Result” and this class will contain 5 properties representing the 5 columns we are fetching. To view
that class, open Solution Explorer and under Models folder expand TestEF.edmx, under that expand TestEF.tt, under
that we find a file Student_Select_Result.cs which contains the class Student_Select_Result and this class is what we
will be using for model binding the views, which will be as following:

203
public partial class Student_Select_Result {
public int Sid { get; set; }
public string Name { get; set; }
public Nullable<int> Class { get; set; }
public Nullable<decimal> Fees { get; set; }
public string Photo { get; set; }
}
Note: even if we are fetching all 6 columns of the table also, still it creates this class and in such cases we can delete
this class and map the results with original Student class.
Add a folder under the project naming it as “Uploads” and then add a new Controller class in Controllers
folder naming it as StudentController.cs and write the below code in it by importing the Model namespace:

public class StudentController : Controller


{
MVCDBEntities dc = new MVCDBEntities();
public ViewResult DisplayStudents()
{
return View(dc.Student_Select(null, true));
}
public ViewResult DisplayStudent(int sid)
{
return View(dc.Student_Select(sid, true).Single());
}
public ViewResult AddStudent()
{
Student_Select_Result student = new Student_Select_Result();
return View(student);
}
[HttpPost]
public RedirectToRouteResult AddStudent(Student_Select_Result student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
string PhysicalPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(PhysicalPath))
Directory.CreateDirectory(PhysicalPath);
selectedFile.SaveAs(PhysicalPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
dc.Student_Insert(student.Sid, student.Name, student.Class, student.Fees, student.Photo);
return RedirectToAction("DisplayStudents");
}
public ViewResult EditStudent(int sid)
{
var student = dc.Student_Select(sid, true).Single();
TempData["Photo"] = student.Photo;

204
return View(student);
}
public RedirectToRouteResult UpdateStudent(Student_Select_Result student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
string PhysicalPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(PhysicalPath))
Directory.CreateDirectory(PhysicalPath);
selectedFile.SaveAs(PhysicalPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
else if (TempData["Photo"] != null)
student.Photo = TempData["Photo"].ToString();
dc.Student_Update(student.Sid, student.Name, student.Class, student.Fees, student.Photo);
return RedirectToAction("DisplayStudents");
}
public ViewResult DeleteStudent(int sid)
{
return View(dc.Student_Select(sid, true).Single());
}
[HttpPost]
public RedirectToRouteResult DeleteStudent(Student_Select_Result student)
{
dc.Student_Delete(student.Sid);
return RedirectToAction("DisplayStudents");
}
}
Add a view with the name DisplayStudent.cshtml, selecting layout Checkbox and write the below code in it
by deleting the whole content in the View:

@model IEnumerable<MVCWithEFDBF3.Models.Student_Select_Result>
@{
ViewBag.Title = "Display Students";
}
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>
<table border="1" align="center">
<tr>
<th>@Html.DisplayNameFor(S => S.Sid)</th>
<th>@Html.DisplayNameFor(S => S.Name)</th>
<th>@Html.DisplayNameFor(S => S.Class)</th>
<th>@Html.DisplayNameFor(S => S.Fees)</th>
<th>@Html.DisplayNameFor(S => S.Photo)</th>
<th>Actions</th>
</tr>
@foreach (var Student in Model)

205
{
<tr>
<td>@Html.DisplayFor(S => Student.Sid)</td>
<td>@Html.DisplayFor(S => Student.Name)</td>
<td>@Html.DisplayFor(S => Student.Class)</td>
<td>@Html.DisplayFor(S => Student.Fees)</td>
<td><img src='/Uploads/@Student.Photo' width="85" height="30" alt="No Image"/></td>
<td>
@Html.ActionLink("View", "DisplayStudent", new { Sid = Student.Sid })
@Html.ActionLink("Edit", "EditStudent", new { Sid = Student.Sid })
@Html.ActionLink("Delete", "DeleteStudent", new { Sid = Student.Sid })
</td>
</tr>
}
<tr><td colspan="6" align="center">@Html.ActionLink("Add New Student", "AddStudent")</td></tr>
</table>
Generate a view for DisplayStudent action method and while adding the View, choose the Template as
Empty, Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below
code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>


<table border="1" align="center">
<tr>
<td rowspan="4"><img src='/Uploads/@Model.Photo' width="200" height="200" alt="No Image" /></td>
<td>Sid: @Model.Sid</td>
</tr>
<tr><td>Name: @Model.Name</td></tr>
<tr><td>Class: @Model.Class</td></tr>
<tr><td>Fees: @Model.Fees</td></tr>
<tr><td colspan="2" align="center">@Html.ActionLink("Back to Student Details", "DisplayStudents")</td></tr>
</table>
Generate a view for AddStudent action method and while adding the View, choose the Template as Empty,
Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>


@using (Html.BeginForm("AddStudent", "Student", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid)</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>@Html.LabelFor(S => S.Photo)<br /><input type="file" name="selectedFile" /></div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" />

206
</div>
@Html.ActionLink("Back to Student Details", "DisplayStudents")
}
Generate a view for EditStudent action method and while adding the View, choose the Template as Empty,
Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Student</h2>


@using (Html.BeginForm("UpdateStudent","Student",FormMethod.Post, new { enctype = "multipart/form-data"}))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid, new { @readonly = true }) )</div>
<div>@Html.LabelFor(S => S.Name)<br>@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>
@Html.LabelFor(S => S.Photo)<br />
<img src='/Uploads/@Model.Photo' width="100" height="100" />
<input type="file" name="selectedFile" />
</div>
<div>
<input type="submit" value="Update" name="btnUpdate" />
@Html.ActionLink("Cancel", "DisplayStudents")
</div>
}
Generate a view for DeleteStudent action method and while adding the View, choose the Template as
Empty, Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below
code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Delete Student</h2>


@using (Html.BeginForm("DeleteStudent", "Student")) {
<table border="1">
<caption>Student Details</caption>
<tr>
<td rowspan="4"><img src='/Uploads/@Model.Photo' width="200" height="200" /></td>
<td>Sid: @Model.Sid @Html.HiddenFor(S => S.Sid)</td>
</tr>
<tr><td>Name: @Model.Name</td></tr>
<tr><td>Class: @Model.Class</td></tr>
<tr><td>Fees: @Model.Fees</td></tr>
</table>
<font color="red">Are you sure of deleting the current record?</font>
<input type="submit" value="Yes" />
}
@using (Html.BeginForm("DisplayStudents", "Student")) {
<text>Click</text> <input type="submit" value="No" /> @:for going back to Student Details.
}

207
Code-First Approach
Entity Framework introduced the Code-First approach with Entity Framework 4.1. Code-First is mainly
useful in Domain Driven Design. In the Code-First approach, we focus on the domain of your application and start
creating classes for our domain entity, rather than design our Database first, and then create the classes which match
your Database design. The following figure illustrates the code-first approach.

As you can see in the above figure, EF API will create the database based on your domain classes and
configurations. This means you need to start coding first in C# or VB.NET languages and then EF will create the
Database from your code.

Code-First Workflow: The below figure illustrates the code-first development workflow:

To work with Code First Approach, create a new “ASP.NET Web Application” project naming it as
“MVCWithEFCF1”, choose “MVC Project Template” and click on the “Create” button. Now do the following actions:

Step 1: Install Entity Framework in our project and to do that open “Nuget Package Manager”, go to Browse tab,
search for “Entity Framework” and install “Entity Framework by Microsoft”. This will add all the references that are
required to work with Entity Framework in our project.

Step 2: Add 3 Classes into the Models folder naming them as “Category.cs”, “Product.cs” and “StoreDbContext.cs”,
and we call them as Domain Classes and then write the below code under them:

public class Category


{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
public ICollection<Product> Products { get; set; }
}

public class Product


{
public int Id { get; set; }
public string ProductName { get; set; }
public int CategoryId { get; set; }
public decimal UnitPrice { get; set; }

208
public byte[] ProductImage { get; set; }
public string ProductImageName { get; set; }
public bool Discontinued { get; set; }
public Category Category { get; set; }
}

using System.Data.Entity;
public class StoreDbContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}

Step 3: Go to “Web.config” file and write the below code inside of <configuration></configuration> tag:

<connectionStrings>
<add name="StoreDbContext" connectionString="Data Source=Server;User Id=Sa;Password=123;
Database=StoreDB" providerName="System.Data.SqlClient" />
</connectionStrings>

Step 4: Go to “_Layout.cshtml” and add 2 menus to work with Categories and Products. To do this, add 2 ActionLinks
below the following statement:
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>

Write the below code, under the above statement:


<li>@Html.ActionLink("Categories", "DisplayCategories", "Category")</li>
<li>@Html.ActionLink("Products", "DisplayProducts", "Product")</li>

Step 5: Add a controller in Controllers folder naming it as “CategoryController.cs”, define all the required Action
methods and create Views that are necessary to perform CRUD operations on “Categories” table.

using System.Data.Entity;
using MVCWithEFCF1.Models;
public class CategoryController : Controller
{
StoreDbContext dc = new StoreDbContext();
public ViewResult DisplayCategories()
{
var categories = dc.Categories;
return View(categories);
}
public ViewResult AddCategory()
{
return View();
}

209
[HttpPost]
public RedirectToRouteResult AddCategory(Category category)
{
dc.Categories.Add(category);
dc.SaveChanges();
return RedirectToAction("DisplayCategories");
}
public ViewResult EditCategory(int CategoryId)
{
Category category = dc.Categories.Find(CategoryId);
return View(category);
}
public RedirectToRouteResult UpdateCategory(Category category)
{
dc.Entry(category).State = EntityState.Modified;
dc.SaveChanges();
return RedirectToAction("DisplayCategories");
}
public RedirectToRouteResult DeleteCategory(int CategoryId)
{
Category category = dc.Categories.Find(CategoryId);
dc.Categories.Remove(category);
dc.SaveChanges();
return RedirectToAction("DisplayCategories");
}
}

Add a View with the name DisplayCategories.cshtml, selecting layout Checkbox and write the below code
in it by deleting the whole content in the View:

@model IEnumerable<MVCWithEFCF1.Models.Category>
@{
ViewBag.Title = "Display Categories";
}
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Categories List</h2>
<table border="1" align="center">
<tr>
<th>@Html.DisplayNameFor(C => C.CategoryId)</th>
<th>@Html.DisplayNameFor(C => C.CategoryName)</th>
<th>@Html.DisplayNameFor(C => C.Description)</th>
<th>Actions</th>
</tr>
@foreach (var Category in Model)
{
<tr>
<td>@Html.DisplayFor(C => Category.CategoryId)</td>

210
<td>@Html.DisplayFor(C => Category.CategoryName)</td>
<td>@Html.DisplayFor(C => Category.Description)</td>
<td>
@Html.ActionLink("Edit", "EditCategory", new { CategoryId =Category.CategoryId })
@Html.ActionLink("Delete", "DeleteCategory", new { CategoryId = Category.CategoryId },
new { onclick = "return confirm('Are you sure of deleting the record?')" })
</td>
</tr>
}
<tr><td colspan="4" align="center">@Html.ActionLink("Add New Category", "AddCategory")</td></tr>
</table>

Generate a view for AddCategory action method and while adding the View, choose the Template as Empty,
Model Class as Category, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Category</h2>


@using (Html.BeginForm("AddCategory", "Category"))
{
<div>@Html.LabelFor(C => C.CategoryName)<br />@Html.TextBoxFor(C => C.CategoryName)</div>
<div>@Html.LabelFor(C => C.Description)<br />@Html.TextAreaFor(C => C.Description)</div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" name="btnReset" />
</div>
}
@Html.ActionLink("Back to Category Details", "DisplayCategories")

Generate a view for EditCategory action method and while adding the View, choose the Template as Empty,
Model Class as Category, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Update Category</h2>


@using (Html.BeginForm("UpdateCategory", "Category"))
{
<div>
@Html.LabelFor(C => C.CategoryId)<br />@Html.TextBoxFor(C => C.CategoryId, new { @readonly = "true" })
</div>
<div>@Html.LabelFor(C => C.CategoryName)<br />@Html.TextBoxFor(C => C.CategoryName)</div>
<div>@Html.LabelFor(C => C.Description)<br />@Html.TextAreaFor(C => C.Description)</div>
<div>
<input type="submit" value="Save" name="btnSave" />
@Html.ActionLink("Cancel", "DisplayCategories")
</div>
}

211
Step 6: Add another controller in Controllers folder naming it as “ProductController.cs”, define all the required
Action methods and also create Views that are necessary to perform CRUD operations on “Products” table.

using System.IO;
using System.Data.Entity;
using MVCWithEFCF1.Models;
public class ProductController : Controller
{
StoreDbContext dc = new StoreDbContext();
public ViewResult DisplayProducts()
{
dc.Configuration.LazyLoadingEnabled = false;
var products = dc.Products.Include(P => P.Category).Where(P => P.Discontinued == false);
return View(products);
}
public ViewResult DisplayProduct(int Id)
{
dc.Configuration.LazyLoadingEnabled = false;
Product product = (dc.Products.Include(P => P.Category).Where(
P => P.Id == Id && P.Discontinued == false)).Single();
return View(product);
}
public ViewResult AddProduct()
{
ViewBag.CategoryId = new SelectList(dc.Categories, "CategoryId", "CategoryName");
return View();
}
[HttpPost]
public RedirectToRouteResult AddProduct(Product product, HttpPostedFileBase selectedFile)
{
if(selectedFile != null)
{
string DirectoryPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(DirectoryPath))
{
Directory.CreateDirectory(DirectoryPath);
}
selectedFile.SaveAs(DirectoryPath + selectedFile.FileName);
BinaryReader br = new BinaryReader(selectedFile.InputStream);
product.ProductImage = br.ReadBytes(selectedFile.ContentLength);
product.ProductImageName = selectedFile.FileName;
}
dc.Products.Add(product);
dc.SaveChanges();
return RedirectToAction("DisplayProducts");
}

212
public ViewResult EditProduct(int Id)
{
Product product = dc.Products.Find(Id);
TempData["ProductImage"] = product.ProductImage;
TempData["ProductImageName"] = product.ProductImageName;
ViewBag.CategoryId = new SelectList(dc.Categories, "CategoryId", "CategoryName", product.CategoryId);
return View(product);
}
public RedirectToRouteResult UpdateProduct(Product product, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
string DirectoryPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(DirectoryPath))
{
Directory.CreateDirectory(DirectoryPath);
}
selectedFile.SaveAs(DirectoryPath + selectedFile.FileName);
BinaryReader br = new BinaryReader(selectedFile.InputStream);
product.ProductImage = br.ReadBytes(selectedFile.ContentLength);
product.ProductImageName = selectedFile.FileName;
}
else if(TempData["ProductImage"] != null && TempData["ProductImageName"] != null) {
product.ProductImage = (byte[])TempData["ProductImage"];
product.ProductImageName = (string)TempData["ProductImageName"];
}
dc.Entry(product).State = EntityState.Modified;
dc.SaveChanges();
return RedirectToAction("DisplayProducts");
}
public RedirectToRouteResult DeleteProduct(int Id)
{
Product product = dc.Products.Find(Id);
product.Discontinued = true;
dc.Entry(product).State = EntityState.Modified;
dc.SaveChanges();
return RedirectToAction("DisplayProducts");
}
}
Add a View with the name DisplayProducts.cshtml, selecting layout Checkbox and write the below code in
it by deleting the whole content in the View:

@model IEnumerable <MVCWithEFCF1.Models.Product>


@{
ViewBag.Title = "Display Products";
}

213
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Display Products</h2>
<table border="1" align="center">
<tr>
<th>@Html.DisplayNameFor(P => P.Id)</th>
<th>@Html.DisplayNameFor(P => P.ProductName)</th>
<th>@Html.DisplayNameFor(P => P.UnitPrice)</th>
<th>@Html.DisplayNameFor(P => P.ProductImage)</th>
<th>@Html.DisplayNameFor(P => P.CategoryId)</th>
<th>@Html.DisplayNameFor(P => P.Category.CategoryName)</th>
<th>@Html.DisplayNameFor(P => P.Category.Description)</th>
<th>Actions</th>
</tr>
@foreach (var Product in Model)
{
<tr>
<td>@Html.DisplayFor(P => Product.Id)</td>
<td>@Html.DisplayFor(P => Product.ProductName)</td>
<td>@Html.DisplayFor(P => Product.UnitPrice)</td>
<td><img src='/Uploads/@Product.ProductImageName' width="40" height="25" alt="No Image" /></td>
<td>@Html.DisplayFor(P => Product.CategoryId)</td>
<td>@Html.DisplayFor(P => Product.Category.CategoryName)</td>
<td>@Html.DisplayFor(P => Product.Category.Description)</td>
<td>
@Html.ActionLink("View", "DisplayProduct", new { Id = Product.Id })
@Html.ActionLink("Edit", "EditProduct", new { Id = Product.Id })
@Html.ActionLink("Delete", "DeleteProduct", new { Id = Product.Id },
new { onclick = "return confirm('Are you sure of deleting the record?')" })</td>
</tr>
}
<tr><td colspan="9" align="center">@Html.ActionLink("Add New Product", "AddProduct")</td></tr>
</table>

Generate a view for DisplayProduct action method and while adding the View, choose the Template as
Empty, Model Class as Product, choose “Use a layout page” CheckBox in the “Add View” window and write the below
code over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Display Product</h2>


<table border="1" align="center">
<tr>
<td rowspan=7>
<img src='~/Uploads/@Model.ProductImageName' width="200" height="200" alt="No Image" />
</td>
<td>ProductId: @Model.Id</td>
</tr>
<tr><td>ProductName: @Model.ProductName</td></tr>
<tr><td>UnitPrice: @Model.UnitPrice</td></tr>

214
<tr><td>CategoryId: @Model.CategoryId</td></tr>
<tr><td>CategoryName: @Model.Category.CategoryName</td></tr>
<tr><td>Description: @Model.Category.Description</td></tr>
<tr><td colspan="2" align="center">@Html.ActionLink("Back to Product Details", "DisplayProducts")</td></tr>
</table>

Generate a view for AddProduct action method and while adding the View, choose the Template as Empty,
Model Class as Product, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Product</h2>


@using (Html.BeginForm("AddProduct", "Product", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(P => P.ProductName)<br />@Html.TextBoxFor(P => P.ProductName)</div>
<div>@Html.LabelFor(P => P.UnitPrice)<br />@Html.TextBoxFor(P => P.UnitPrice)</div>
<div>@Html.LabelFor(P => P.ProductImage)<br /><input type="file" name="selectedFile" /></div>
<div>@Html.Label("Category Name")<br />@Html.DropDownList("CategoryId", "-Select Category-")</div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" />
</div>
}
@Html.ActionLink("Back to Product Details", "DisplayProducts")

Generate a view for EditProduct action method and while adding the View, choose the Template as Empty,
Model Class as Product, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Update Product</h2>


@using (Html.BeginForm("UpdateProduct", "Product", FormMethod.Post, new {enctype="multipart/form-data" }))
{
<div>@Html.LabelFor(P => P.Id)<br />@Html.TextBoxFor(P => P.Id, new { @readonly = "true" })</div>
<div>@Html.LabelFor(P => P.ProductName)<br />@Html.TextBoxFor(P => P.ProductName)</div>
<div>@Html.LabelFor(P => P.UnitPrice)<br />@Html.TextBoxFor(P => P.UnitPrice)</div>
<div>
@Html.LabelFor(P => P.ProductImage)<br />
<img src='/Uploads/@Model.ProductImageName' width="100" height="100" /><br />
<input type="file" name="selectedFile" />
</div>
<div>@Html.LabelFor(P => P.CategoryId)<br />@Html.DropDownList("CategoryId")</div>

<div>
<input type="submit" value="Update" name="btnUpdate" />
@Html.ActionLink("Cancel", "DisplayProducts")
</div>
}

215
Step 7: Now if we want the Database and Tables to be created on the Database Server, we need to perform
Migrations. Migration is a feature “Entity Framework Code First” provides which is used to keep the “Domain
Classes” and “Database” in sync with each other.

Now when we run the application it launches the “HomeController’s”, “Index View” and the Menu in Layout
will display “Categories” and “Products” links on top of the Page and when we click on the “Categories” link it will
immediately create the Database on the server with the name “StoreDB”.

To test this, run the project, click on “Categories” link on the top and then it will display the View “Category
List” providing options for adding a new category. Now go to SQL Server Database and watch, we will find a new
Database with the name “StoreDB” (we specified this in Web.config file) and under the Database we will find
Categories and Products tables (names of tables are taken based on DbSet properties in DbContext class).

Note: in our “Web.config” file we specified the name of “Connection String” as “StoreDbContext” and this name is
the same name of our “DbContext” class, so we don’t require writing any code to read the “ConnectionString” into
our application. If we want to give our own name for Connection String in “Web.config” without using the name
“StoreDbContext”, we need to explicitly specify that name by defining a default constructor in “StoreDbContext”
class and call its base class constructor using “base” keyword and pass the “Connection String” name as a parameter
to it. For example, in “Web.config”, if we give the name of “Connection String” as “ConStr” but not “StoreDbContext”,
then we need to define a constructor in our Context class as below:

public StoreDbContext() : base("ConStr")


{
}

Database Initialization Strategies: right now, when we run the project for first time it will create the “Database and
Tables” and from next time on wards it will use the same “Database and Tables” when we run the application. There
are various options to decide for us whether we want to use the existing Database next time or re-create it every
time, and that is based on Database Initialization Strategies. To handle this, we have to use one of the Database
Initialization Strategies which should be specified in our Context class constructor as following:
Database.SetInitializer(new CreateDatabaseIfNotExists<ContextClassName>());

Entity Framework Supports 3 different initialization strategies like:


CreateDatabaseIfNotExists: This is the default initializer. As the name suggests, it will create the Database if none
exists as per the configuration. However, if you change the model class and then run the application with this
initializer, then it will throw an Exception.

DropCreateDatabaseIfModelChanges: This initializer drops an existing Database and creates a new if your model
classes (entity classes) have been changed. So, you don’t have to worry about maintaining your Database schema
when your model classes change.

DropCreateDatabaseAlways: As the name suggests, this initializer drops an existing Database every time you run
the application, irrespective of whether your model classes have changed or not.

To try them go to constructor of our Context class i.e., “StoreDbContext” and use any one of the following:
Database.SetInitializer(new CreateDatabaseIfNotExists<StoreDbContext>()); //Default Strategy
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<StoreDbContext>());
Database.SetInitializer(new DropCreateDatabaseAlways<StoreDbContext>());

216
Turn off the DB Initializer: you can even turn off the Database initializer for your application if you don’t want to
lose existing data in production environment, then you can turn off initializer, as shown below:
Database.SetInitializer<StoreDbContext>(null);

EF 6 Code-First Conventions: Conventions are a set of default rules which automatically configure a conceptual
model based on our domain classes when working with the Code-First approach. As you have seen in the previous
example, EF API configured Primary Keys, Foreign Keys, Relationships, and Column Data Types etc. from the domain
classes without any additional configurations. This is because of the EF Code-First Conventions. If they are followed
in domain classes, then the Database schema will be configured based on the Conventions. These EF 6.x Code-First
Conventions are defined in the “System.Data.Entity.ModelConfiguration.Conventions” namespace.

The following table lists default Code-First Conventions


Default Convention For Description
Schema By default, EF creates all the Database objects into the dbo schema.
Table Name <Entity Class Name> + 's'
EF will create a Database table with the entity class name suffixed by ‘s’ for
example “Student” domain class (entity) would map to “Students” table.
Mostly it uses the names of the properties we define to refer the tables in
Context class.
Primary Key Name 1) A property with the name “Id”.
2) <Entity Class Name> + “Id” (case in-sensitive)
EF will create a primary key column for the property named Id or <Entity Class
Name> + “Id” (case in-sensitive).
Foreign Key Property Name By default, EF will look for the foreign key property with the same name as the
principal entity primary key name. If the foreign key property does not exist,
then EF creates an FK Column in the table with <Dependent Navigation
Property Name> + "_" + <Principal Entity Primary Key Property Name>, for
example EF will create “Category_CategoryId” foreign key column in
Products table if the Product entity does not contain a foreign key property.

Null Column EF creates a null column for all reference type properties and nullable value
properties e.g., string, Nullable<int> or int?, etc.
Not Null Column EF creates Not Null columns for Primary Key properties and non-nullable value
type properties e.g., int, float, bool, decimal, DateTime etc.
DB Columns Order EF will create DB columns in the same order as the properties in an entity class.
However, primary key columns would be moved first.
Properties Mapping to DB By default, all properties will map to the Database. Use
the [NotMapped] attribute to exclude property or class from DB mapping.
Cascade Delete & Update Enabled by default for all types of relationships.

217
The following table list C# data types mapped with SQL Server data types
C# Data Type Mapping to SQL Server Data Type
int Int
string nvarchar(Max)
decimal decimal(18,2)
float Real
byte[] varbinary(Max)
datetime Datetime
bool Bit
byte Tinyint
short Smallint
long Bigint
double float
char No Mapping (Throws Exception)
sbyte No Mapping (Throws Exception)
object No Mapping (Throws Exception)

Data Annotations: Data Annotations are .NET attributes which can be applied on an entity class or properties to
override default conventions in EF 6 and EF Core. Data Annotations are provided in EF 6 and EF Core under the
namespaces System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema.
These attributes can be used in Entity Framework as well as with ASP.NET MVC Data Controls.

System.ComponentModel.DataAnnotations Attributes:
Attribute Description
Key Can be applied to a property to specify a key property in an entity and make the
corresponding column a “Primary Key” column in the Database.
Timestamp Can be applied to a property to specify the data type of a corresponding column in the
Database as “Row Version”.
Required Can be applied to a property to specify that the corresponding column is a “Not Null”
column in the Database.
MinLength Can be applied to a property to specify the minimum string length allowed in the
corresponding column in the Database.
MaxLength Can be applied to a property to specify the maximum string length allowed in the
corresponding column in the Database.
StringLength Can be applied to a property to specify the maximum string length allowed in the
corresponding column in the Database.

218
System.ComponentModel.DataAnnotations.Schema Attributes:
Attribute Description
Table Can be applied to an entity class to configure the corresponding table name and schema in
the Database.
Column Can be applied to a property to configure the corresponding column name, order and data
type in the Database.
Index Can be applied to a property to configure that the corresponding column should have an
Index in the Database. (EF 6.1 onwards only)
ForeignKey Can be applied to a property to mark it as a foreign key property.
NotMapped Can be applied to a property or entity class which should be excluded from the model and
should not generate a corresponding column or table in the database.
DatabaseGenerated Can be applied to a property to configure how the underlying database should generate the
value for the corresponding column e.g., identity, computed or none.
InverseProperty Can be applied to a property to specify the inverse of a navigation property that represents
the other end of the same relationship.
ComplexType Marks the class as complex type in EF 6. EF Core 2.0 does not support this attribute.

To test overriding the default Code First Conventions with Data Annotations create a new “ASP.Net Web
Application” project naming it as “MVCWithEFCF2”, choose MVC Project Template and click on “Create” button.
Install Entity Framework in the project and then add 3 new classes into the Models folder naming them as
“Supplier.cs”, “Customer.cs” and “CompanyDbContext.cs”, and write the below code under them:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("Supplier")] //Specifying Name for the table being created in database.
public class Supplier
{
[Key] //Setting this column as Primary Key column.
[DatabaseGenerated(DatabaseGeneratedOption.None)] //Setting identity off, so will not autogenerate values.
public int Sid { get; set; }

[MaxLength(100)] //Setting MaxLength as 100 for this column.


[Column("Sname", TypeName = "Varchar")] //Setting column name and data type of the column.
public string SupplierName { get; set; }

public ICollection<Customer> Customers { get; set; }


}
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("Customer")]
public class Customer

219
{
[Column(TypeName = "Money")]
public decimal? Balance { get; set; }

[Index] //Setting Index attribute for this column in database.


[Required] //Setting not null constraint for this column in database.
[MaxLength(50)]
[Column("Cname", TypeName = "Varchar")]
public string CustomerName { get; set; }

[StringLength(1000)]
[Column(TypeName = "Varchar")]
public string Address { get; set; }

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Custid { get; set; }

public int SupplierId { get; set; }

[ForeignKey("SupplierId")] //Setting the foreign key column for the table.


public Supplier Supplier { get; set; }
}

using System.Data.Entity;
public class CompanyDbContext : DbContext
{
public CompanyDbContext() : base("ConStr")
{
Database.SetInitializer(new DropCreateDatabaseAlways<CompanyDbContext>());
}
public DbSet<Supplier> Suppliers { get; set; }
public DbSet<Customer> Customers { get; set; }
}

Now open Web.config file and write the following code between <configuration></configuration> tag:
<connectionStrings>
<add name="ConStr"
connectionString="Data Source=Server;Database=CompanyDB;User Id=Sa;Password=123"
providerName="System.Data.SqlClient" />
</connectionStrings>

Add a controller naming it as SupplierController and write the below code under it by deleting existing code:
using MVCWithEFCF2.Models;
public class SupplierController : Controller
{

220
CompanyDbContext dc = new CompanyDbContext();
public ActionResult Index()
{
Supplier s1 = new Supplier { Sid = 101, SupplierName = "Ashok Distributors." };
Supplier s2 = new Supplier { Sid = 102, SupplierName = "Meghna Distributors." };
Supplier s3 = new Supplier { Sid = 103, SupplierName = "Diamond Distributors." };
Supplier s4 = new Supplier { Sid = 104, SupplierName = "Prasad Distributors." };
dc.Suppliers.Add(s1); dc.Suppliers.Add(s2);
dc.Suppliers.Add(s3); dc.Suppliers.Add(s4);
dc.SaveChanges();
return View(dc.Suppliers);
}
}

Add a view to the Index action method and while adding the View, in “Add View” window choose
“Template:” as “List”, “Model class:” as “Supplier (MVCWithEFCF2.Models)”, “Data context class:” as
“CompanyDbContext (MVCWithEFCF2.Models)” and click on “Add” button. Run the view we have created which will
create the Database and Tables under SQL Server.

Seed Data in Entity Framework Code-First: We can insert data into our Database tables during the Database
initialization process. This will be important when we want to provide some “default - master data” for any table in
the application, for example in our previous application if we want to insert default data into “Supplier” table then
we need to use the concept of “Seed” and insert default data into the table. To seed data into any table, we need to
implement the logic in “Seed” method of any 3 DBInitializer classes (“CreateDatabaseIfNotExists”,
“DropCreateDatabaseAlways”, “DropCreateDatabaseIfModelChanges”) and to do that we have to define a custom
“DBInitializer” class inheriting from any of the above 3 “DBInitializer” classes and then override the “Seed” method.
To test this process, add a new class in Models folder of our previous project with the name
“CompanyDBInitializer.cs” and write the below code in it:

using System.Data.Entity;
public class CompanyDBInitializer : DropCreateDatabaseIfModelChanges<CompanyDbContext>
{
protected override void Seed(CompanyDbContext context)
{
Supplier s1 = new Supplier { Sid = 101, SupplierName = "Ashok Distributors." };
Supplier s2 = new Supplier { Sid = 102, SupplierName = "Meghna Distributors." };
Supplier s3 = new Supplier { Sid = 103, SupplierName = "Diamond Distributors." };
Supplier s4 = new Supplier { Sid = 104, SupplierName = "Prasad Distributors." };
context.Suppliers.Add(s1); context.Suppliers.Add(s2);
context.Suppliers.Add(s3); context.Suppliers.Add(s4);
context.SaveChanges();
}
}

Go to “CompanyDbContext” class and re-write the constructor of the class as below:


public CompanyDbContext() : base("ConStr")

221
{
Database.SetInitializer(new CompanyDBInitializer());
}

Go to “SupplierController” class and delete the below code, because we have implemented the Seed
method in “CompanyDBInitializer” class and it will insert data into Supplier table during the Database initialization
process, so this code is no more required in the “SupplierController” class.

Supplier s1 = new Supplier { Sid = 101, SupplierName = "Ashok Distributors." };


Supplier s2 = new Supplier { Sid = 102, SupplierName = "Meghna Distributors." };
Supplier s3 = new Supplier { Sid = 103, SupplierName = "Diamond Distributors." };
Supplier s4 = new Supplier { Sid = 104, SupplierName = "Prasad Distributors." };
dc.Suppliers.Add(s1); dc.Suppliers.Add(s2);
dc.Suppliers.Add(s3); dc.Suppliers.Add(s4);

Entity Framework Code First Migrations: Entity Framework Code-First has different Database initialization strategies
like “CreateDatabaseIfNotExists”, “DropCreateDatabaseIfModelChanges”, “DropCreateDatabaseAlways” however,
there are problems with these strategies. In the first case Model changes will not be updated to the Database and
also throws an error when we run the project, whereas in the second and third cases Model changes will be updated
to the Database but if we already have data (other than seed data) or we created our own Stored Procedures,
Triggers, Views etc. in our Database then these strategies will drop the entire Database and recreates it, so we will
lose the Data and Database Objects also.

To overcome the above problems “Entity Framework” introduced “Migrations” that automatically updates
the Database schema whenever our model changes without losing any existing Data or other Database Objects. To
do that we need to use a new Database Initializer called “MigrateDatabaseToLatestVersion”.

There are 2 kinds of Migration available like:


 Automated Migration
 Code-based Migration

Automated Migration: Entity Framework provides automated migration option so that you don’t have to process
Database migration manually for each change you make in your domain classes. The automated migrations can be
implemented by executing the “enable-migrations” command in the Package Manager Console.

To test “Automated Migrations”, create a new “ASP.NET Web Application” project naming it as
“MVCWithEFCF3”, choose “MVC Project Template” and click on “Create” button. Install Entity Framework, add 2
classes under Models folder with names “Student” and “SchoolDbContext” and write the below code under them:

public class Student


{
public int StudentId { get; set; }
public string Name { get; set; }
}

using System.Data.Entity;
public class SchoolDbContext : DbContext

222
{
public SchoolDbContext() : base("ConStr")
{
}
public DbSet<Student> Students { get; set; }
}

Go to Web.config file and write the below code between <configuration></configuration> tag:
<connectionStrings>
<add name="ConStr" providerName="System.Data.SQLClient"
connectionString="Data Source=Server;Database=SchoolDB;User Id=Sa;Password=123" />
</connectionStrings>

Add a controller under the Controllers folder naming it as “SchoolController” and write the below code in it:
using MVCWithEFCF3.Models;
public class StudentController : Controller
{
SchoolDbContext dc = new SchoolDbContext();
public ActionResult Index()
{
Student s = new Student { Name = "Raju" };
dc.Students.Add(s);
dc.SaveChanges();
return View();
}
}

Add a view to “Index” action method; run the project which will create “SchoolDB” Database under SQL
Server and in that “Student” Table is created with 2 Columns and 1 record is inserted into the Table.

Now if we make any changes to the Model class like adding new attributes (properties) or modifying existing
attributes and run the project we get an error because by default the Database Initialization Strategy is
“CreateDatabaseIfNotExists” and if we try to change the Database Initialization Strategy to
“DropCreateDatabaseIfModelChanges” or “DropCreateDatabaseAlways” we will be losing the existing data in the
table and to overcome this problem let’s use “Migrations”.

Automatic Migrations: to use Automatic Migrations we need to enable migrations in our project and to do that go
to “Package Manager Console” window from “Tools Menu” => “Nuget Package Manager” => “Package Manager
Console” and run the below command there:
PM> Enable-Migrations -EnableAutomaticMigration:$true

The above command will add a “Migrations” folder in our project and under that folder we find a file
“Configuration.cs” which contains a class called “Configuaration” with the below code in it:

internal sealed class Configuration : DbMigrationsConfiguration<MVCWithEFCF3.Models.SchoolDbContext>


{

223
public Configuration()
{
AutomaticMigrationsEnabled = true;
ContextKey = "MVCWithEFCF3.Models.SchoolDbContext";
}
protected override void Seed(MVCWithEFCF3.Models.SchoolDbContext context) {
//This method will be called after migrating to the latest version.
//You can use the DbSet<T>.AddOrUpdate() helper extension method to avoid creating duplicate seed data.
}
}

Now go to our “SchoolDbContext” class and write the below statement in its constructor by importing the
namespace “MVCWithEFCF3.Migrations”.

Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolDbContext, Configuration>());

With this action everything is set ready for Automatic Migrations, and to test this either add new properties
to Student class or add new Model classes in the project and the next time when we run the project, we see all the
changes reflecting under the Database. However, sometimes when you modify or remove existing properties in
domain classes we get “System.Data.Entity.Migrations.Infrastructure.AutomaticDataLossException”, and this is
because we may loose data in corresponding column of the Table. So, to handle this kind of scenario, we have to set
“AutomaticMigrationDataLossAllowed = true” in the “Configuration” class Constructor. To do that go to
“Configuration” class in “Migrations” folder and add the above statement which should now look as following:

public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true; //New Statement to be added
ContextKey = "MVCWithEFCF3.Models.SchoolDbContext";
}

Code Based Migrations: code-based migration provides more control on the migration and allows you to configure
additional things such as setting a default value to a column, change data type of a column, add not null constraints
on a column, configure a computed column etc.

To use code-based migration we need to execute the following commands in “Package Manager Console”
window under Visual Studio:

 Enable-Migrations: enables the migration in your project by creating a Configuration class.


 Add-Migration: creates a new migration class as per specified name with the Up() and Down() methods.
 Update-Database: executes the last migration file created by the Add-Migration command and applies changes
to the database schema.

To test Code Based Migrations create a new “ASP.NET Web Application” project naming it as
“MVCWithEFCF4”, choose “MVC Project Template” and click on “Create” button. Install Entity Framework in the
project, add 2 new classes in to Models folder naming them as “Student” and “SchoolDbContext”, and write the
below code under them:

224
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public int Class { get; set; }

[MaxLength(1)]
[Column(TypeName = "Varchar")]
public string Section { get; set; }
}

using System.Data.Entity;
public class SchoolDbContext : DbContext
{
public SchoolDbContext() : base("ConStr")
{
}
public DbSet<Student> Students { get; set; }
}

Go to Web.config file and write the below code between <configuration></configuration> tag:
<connectionStrings>
<add name="ConStr" providerName="System.Data.SQLClient"
connectionString="Data Source=Server;Database=SchoolDB;User Id=Sa;Password=123" />
</connectionStrings>

Add a controller under the Controllers folder naming it as “SchoolController” and write the below code in it:
using MVCWithEFCF4.Models;
public class StudentController : Controller
{
SchoolDbContext dc = new SchoolDbContext();
public ActionResult Index()
{
Student s1 = new Student { Name = "Raju", Class = 10, Section = "A" };
Student s2 = new Student { Name = "Venkat", Class = 10, Section = "B" };
Student s3 = new Student { Name = "Srinivas", Class = 10, Section = "C" };
dc.Students.Add(s1); dc.Students.Add(s2); dc.Students.Add(s3);
dc.SaveChanges();
return View();
}
}

Add a View to Index action method and run the project which will create “SchoolDB” Database on SQL
Server and under that Database, “Student” Table is created with 4 columns in it.

225
Working with Code Based Migrations: To work with code-based migrations, first execute the “enable-migrations”
command in the “Package Manager Console” and to do that go to Tools menu => Nuget Package Manager => Package
Manager Console and run the below command over there:
PM>Enable-Migrations

This command will create the Configuration class same as we saw in case of “Automated Migrations” but
in this case Configuration class Constructor will have “AutomaticMigrationsEnabled = false” because we are using
Code Based Migrations now, and this command also creates a “<timestamp>_InitialCreate.cs” file containing a class
“InitialCreate” with “Up() and Down()” methods as following:

public partial class InitialCreate : DbMigration


{
public override void Up()
{
CreateTable("dbo.Students", c => new
{
StudentId = c.Int(nullable: false, identity: true),
Name = c.String(),
Class = c.Int(nullable: false),
Section = c.String(maxLength: 1, unicode: false),
}).PrimaryKey(t => t.StudentId);
}
public override void Down()
{
DropTable("dbo.Students");
}
}

As we can see the “Up()” method contains code for creating Database objects and the “Down()” method
contains code for dropping or deleting Database objects. You may also write your own custom code for additional
configurations and that is the advantage of Code Based Migrations over Automated Migrations.

Now go to “SchoolDbContext” class and write the below code in its constructor by importing the namespace
“MVCWithEFCF4.Migrations”:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolDbContext, Configuration>());

From now whenever we make changes to existing Model classes or add new Model classes, we need to
create a new Migration class by using the “Add-Migration” command in the “Package Manager Console” with a name
to the class (any name) as following:
Syntax => PM> Add-Migration <Some Name>

To test this, go to Student class and add a new property into the class as following:
public float? Fees { get; set; }

Open Package Manager Console (PMC) and create a new migration file by executing the following statement:
PM> Add-Migration SchoolDB-V1

226
The above action will create a new migration file with the name “<timestamp>_SchoolDB-v1.cs” and in the
same way we can create any no. of migration files as above whenever we make changes to the Model classes and
to discriminate between each file give a different name every time, for example:
PM>Add-Migration SchoolDB-v2
PM>Add-Migration SchoolDB-v3
PM>Add-Migration SchoolDB-v4

After creating a migration file as above, we must execute the “Update-Database” command in the “Package
Manager Console” and update the Database as below:
PM>Update-Database

Note: to view the SQL statements being applied to the target Database use “-Verbose” option as below:
PM>Update-Database -Verbose

The above statement when executed will run the last or latest migration file and alters the Database based
on the changes, we have made to domain classes.

Let’s now add another 2 properties in the “Student” class and to do that go to “Student.cs” file and write
the below code in the class:
public float Marks { get; set; }
public string Address { get; set; }

Create another migration file at the Package Manager Console as following:


PM> Add-Migration SchoolDB-V2

Note: the above action will create a new migration file with the name “<timestamp>_SchoolDB-v2.cs”.

Get Migrations: right now, we have 3 migrations files that are created but what we have applied on the Database is
only 2 and to check what migration are applied on the Database use the “Get-Migrations” command at Package
Manager Console as below:
PM>Get-Migrations

Now let’s apply the 3rd migration file also to the Database i.e. “SchoolDB-V2” and to do that run the
following statement at Package Manager Console:
PM>Update-Database -Verbose

Rollback Migration: suppose if we want to roll back the Database schema to any of the previous migrations, then
you can execute the “Update-Database” command with the “-TargetMigration” parameter to the point which you
want to roll back to. For example, suppose there are many migrations applied to the above “SchoolDB” Database,
but you want to roll back to “SchoolDB-V1” migration then execute the below command:
PM>Update-Database -TargetMigration:SchoolDB-V1 -Verbose

Note: this statement will execute the “Down” method in the migration file and drops the 2 columns from the
Database table, which are added in “SchoolDB-V2” migration. This action will not delete the migration file under
“Migrations” folder, so if we don’t want it, we need to explicitly delete the file on our own and also we need to
delete the properties we added manually in the Model classes.

227
Model-First Approach
In Model-First approach, we create entities, relationships, and inheritance hierarchies directly on Visual
Designer integrated in Visual Studio, which will then generate Model Classes, Context Class, and also the Database
Script from your Visual Model.

Note: EF 6 includes limited support for this, and EF Core does not support this approach at all.

To work with Entity Framework Model First Approach, create a new “ASP.NET Web Application” project
naming it as “MVCWithEFMF”, choose “MVC Project Template” and click on “Create” button. Open Solution
Explorer, right click on the Models folder and choose “Add => New Item” option and in the window opened select
the item “ADO.NET Entity Data Model” name it as “TestEF” and click on the “Add” button and in the window opened
select “Empty EF Designer Model” and click on “Finish” button. This will add “TestEF.edmx” item under Models folder
and under this item we will find 2 items with the names “TestEF.Designer.cs” and “TestEF.edmx.diagram”. We also
see “TestEF.edmx [Diagram1]” displayed in document window and by using this we can design Model classes.

Creating a Department Entity: now right click on the “TestEF.edmx [Diagram1]”, in the document window and select
the option “Add New” => “Entity”, which will open “Add Entity” window => enter the “Entity name” as “Department”
and this will automatically fill the other details in the window, watch them and click on “Ok” button which will add
the “Department” entity with “Id” attribute.

Adding new Properties to Department Entity: right click on the Department Entity and select “Add New” => “Scalar
Property” which will add a new property name it as “Dname”, right click on “Dname” property and select the option
“Properties” which opens “Property Window” and in that window we can set various attributes like Type, Nullable,
Length etc, and by default the Type will be “String” which is ok for “Dname” so leave it and set the “Max Length”
property value as “50”, “Unicode” property value as “false” and “Nullable” property value as “false”. Repeat the
same process again and add another property with the name “Location” and set the “Max Length” property value
as “50”, “Unicode” property value as “false” and “Nullable” property value as “true”.

228
Creating an Employee Entity: right click on the document window and select the option “Add New” => “Entity”,
which will open “Add Entity” window => enter the “Entity name” as “Employee” which will automatically fill the
other details, watch them, and click on the “Ok” button which will add the “Employee” entity with “Id” attribute.

Adding new Properties to Employee Entity: now add all the other required properties to “Employee” Entity with
the following names and attribute values:
Ename: Type: String, Max Length: 50, Unicode: False, Nullable: False
Job: Type: String, Max Length: 50, Unicode: False, Nullable: True
Salary: Type: Decimal, Precision: 9, Scale: 2, Nullable: True
Status: Type: Boolean, Default Value: True, Nullable: False

Adding a relationship between the tables: to add a relationship between the 2 tables right click, on the
document window and select the option “Add New” => “Association” and in the window opened it will display the
following details, verify them, change if anything is not as per our requirements (as of now everything is perfectly
set, so no need to make any changes) and click on the “Ok” button.

This will add a “DepartmentId” column to the “Employee” entity, also adds navigation properties in both
the entities and this will also create a relationship between the tables as following:

Generating Model Classes and Database with Tables, using the Visual Model: right click on the document window
and select the option “Generate Database from Model” which will open a window and in that click on “New
Connection” button and enter the connection details like “Server Name”, “Authentication Details” and in “Select or
enter a database name:” TextBox enter Database Name as “CompanyDB” (make sure this Database is not existing
under SQL Server) and when we click on the “Ok” button it will ask for creating the Database because it is not existing,

229
click on the “Yes” button which will create the Database and launches a new window, here select the radio button
“Yes, include the sensitive data in the connection string.” => Click “Next” and select the Entity Framework version
i.e., “6.x” => Click “Next” which displays the required “SQL Script” code that is generated for creating Tables and this
code will be saved into our “Models” folder with the name “TestEF.edmx.sql” and click on the “Finish” button to
complete the configuration which will also install “Entity Framework” in our project.

Creating Tables on Database Server: after all the above actions i.e., Entity Framework generating required Context
and Model Classes, now we need to create the tables under our Database i.e., “CompanyDB” and to create the
tables, inside of the Model’s folder we find a SQL Script file with name “TestEF.edmx.sql” which is generated by
“Entity Framework Code First” which we need to execute and to do that, open the script file, right click on it in
document window and select the option “Execute” which will open “Connect” window, in that expand the node
“Local” and under that we find our “Server Name” (Server in my case) select it, and in the below specify the
Authentication Details and choose the Database as “CompanyDB” under “Database Name” DropDownList and click
connect which will create the tables on Database.

Now open “Solution Explorer” and watch the “TestEF.edmx” item under “Models” folder there we find new
items added with the names “TestEF.Context.tt” and “TestEF.tt”. We find a “Context” class with the name
“TestEFContainer” under the file “TestEF.Context.cs” which is present under “TestEF.Context.tt” item, and we also
find Model classes under “TestEF.tt” item, which when expanded will show “Department.cs” and “Employee.cs” files
containing “Department” and “Employee” classes.

Note: In the Context class i.e., “TestEFContainer” Constructor, we find a call to its base or parent class Constructor
and under that we find the name of “Connection String” which is nothing but “TestEFContainer”, so in the
“Web.config” file we will find the “Connection String” with this name. Even if it is not required to specify
the name and call base class constructor because we have already learnt that if the “Context” class name
and “Connection String” name are same no need to specify that explicitly, but “Entity Framework Model
First” will include that code in Constructor.

Now we can start working with those Tables and Domain Classes by creating the required Controllers,
Action Methods, and Views.

230
ADO.NET
Create a new ASP.NET Web Application project naming it as “MVCWithADO”, choose “MVC Project
Template” and click on the “Create” button. Under the Model’s folder add a class with the name “Student.cs” to
represent our Student Entity and write the below code in it:

using System.ComponentModel.DataAnnotations;
public class Student
{
[Display(Name = "Student Id")]
public int Sid { get; set; }
public string Name { get; set; }
public int? Class { get; set; }
public decimal? Fees { get; set; }
public string Photo { get; set; }
}

Open Web.config file and add Connection String for connecting to DB under <configuration> tag as following:
<connectionStrings>
<add name="ConStr"
connectionString="Data Source=Server;Database=MVCDB;User Id=Sa; Password=123"
providerName="System.Data.SqlClient" />
</connectionStrings>

Now add another class in Model’s folder with the name “StudentDAL.cs” and write the following code in it:
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
public class StudentDAL
{
SqlCommand cmd;
SqlConnection con;
public StudentDAL()
{
string ConStr = ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString;
con = new SqlConnection(ConStr);
cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
}
public List<Student> SelectStudent(int? Sid, bool? Status)
{
List<Student> students = new List<Student>();
try
{
cmd.Parameters.Clear();
cmd.CommandText = "Student_Select";

231
if (Sid != null && Status != null) {
cmd.Parameters.AddWithValue("@Sid", Sid);
cmd.Parameters.AddWithValue("@Status", Status);
}
else if (Sid != null && Status == null)
cmd.Parameters.AddWithValue("@Sid", Sid);
else if (Sid == null && Status != null)
cmd.Parameters.AddWithValue("@Status", Status);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Student student = new Student {
Sid = (int)dr["Sid"],
Name = (string)dr["Name"],
Class = (int)dr["Class"],
Fees = (decimal)dr["Fees"],
Photo = (string)dr["Photo"]
};
students.Add(student);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
return students;
}
public int InsertStudent(Student student)
{
int Count = 0;
try
{
cmd.CommandText = "Student_Insert";
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("@Sid", student.Sid);
cmd.Parameters.AddWithValue("@Name", student.Name);
cmd.Parameters.AddWithValue("@Class", student.Class);
cmd.Parameters.AddWithValue("@Fees", student.Fees);
if (student.Photo != null && student.Photo.Length != 0) {
cmd.Parameters.AddWithValue("@Photo", student.Photo);
}

232
else {
cmd.Parameters.AddWithValue("@Photo", DBNull.Value);
cmd.Parameters["@Photo"].SqlDbType = SqlDbType.VarChar;
}
con.Open();
Count = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
return Count;
}
public int UpdateStudent(Student student)
{
int Count = 0;
try
{
cmd.CommandText = "Student_Update";
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("@Sid", student.Sid);
cmd.Parameters.AddWithValue("@Name", student.Name);
cmd.Parameters.AddWithValue("@Class", student.Class);
cmd.Parameters.AddWithValue("@Fees", student.Fees);
if (student.Photo != null && student.Photo.Length != 0) {
cmd.Parameters.AddWithValue("@Photo", student.Photo);
}
else {
cmd.Parameters.AddWithValue("@Photo", DBNull.Value);
cmd.Parameters["@Photo"].SqlDbType = SqlDbType.VarChar;
}
con.Open();
Count = cmd.ExecuteNonQuery();
}
catch (Exception ex) {
throw ex;
}
finally {
con.Close();
}
return Count;
}

233
public int DeleteStudent(int Sid)
{
int Count = 0;
try
{
cmd.CommandText = "Student_Delete";
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("@Sid", Sid);
con.Open();
Count = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
return Count;
}
}

Add a Controller under Controllers folder with the name “StudentController” and write the following code in it:
using System.IO;
using MVCWithADO.Models;
public class StudentController : Controller
{
StudentDAL obj = new StudentDAL();
public ViewResult DisplayStudents()
{
return View(obj.SelectStudent(null, true));
}
public ViewResult DisplayStudent(int Sid)
{
return View(obj.SelectStudent(Sid, true)[0]);
}
public ViewResult AddStudent()
{
return View();
}
[HttpPost]
public RedirectToRouteResult AddStudent(Student student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{

234
string PhysicalPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(PhysicalPath)) {
Directory.CreateDirectory(PhysicalPath);
}
selectedFile.SaveAs(PhysicalPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
obj.InsertStudent(student);
return RedirectToAction("DisplayStudents");
}
public ViewResult EditStudent(int Sid)
{
Student student = obj.GetStudents(Sid, true).Single();
TempData["Photo"] = student.Photo;
return View(s);
}
public RedirectToRouteResult UpdateStudent(Student student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
string PhysicalPath = Server.MapPath("~/Uploads/");
if (!Directory.Exists(PhysicalPath)) {
Directory.CreateDirectory(PhysicalPath);
}
selectedFile.SaveAs(PhysicalPath + selectedFile.FileName);
student.Photo = selectedFile.FileName;
}
else
{
student.Photo = TempData["Photo"].ToString();
}
obj.UpdateStudent(student);
return RedirectToAction("DisplayStudents");
}
public RedirectToRouteResult DeleteStudent(int Sid)
{
obj.DeleteStudent(Sid);
return RedirectToAction("DisplayStudents");
}
}

Add a view with the name DisplayStudents.cshtml, selecting layout Checkbox and write the below code in
it by deleting the whole content in the View:

@model IEnumerable<MVCWithADO.Models.Student>
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>

235
<table border="1" align="center" class="table-condensed">
<tr>
<th>@Html.DisplayNameFor(S => S.Sid)</th>
<th>@Html.DisplayNameFor(S => S.Name)</th>
<th>@Html.DisplayNameFor(S => S.Class)</th>
<th>@Html.DisplayNameFor(S => S.Fees)</th>
<th>@Html.DisplayNameFor(S => S.Photo)</th>
<th align="center">Actions</th>
</tr>
@foreach (MVCWithADO.Models.Student student in Model)
{
<tr>
<td>@Html.DisplayFor(S => student.Sid)</td>
<td>@Html.DisplayFor(S => student.Name)</td>
<td>@Html.DisplayFor(S => student.Class)</td>
<td>@Html.DisplayFor(S => student.Fees)</td>
<td><img src='/Uploads/@student.Photo' width="40" height="25" alt="No Image" />
</td>
<td>
@Html.ActionLink("View", "DisplayStudent", new { Sid = student.Sid })
@Html.ActionLink("Edit", "EditStudent", new { Sid = student.Sid })
@Html.ActionLink("Delete", "DeleteStudent", new { Sid = student.Sid },
new { onclick = "return confirm('Are you sure of deleting the record?')" })
</td>
</tr>
}
<tr>
<td colspan="6" align="center">@Html.ActionLink("Add New Student", "AddStudent")</td>
</tr>
</table>

Generate a view for DisplayStudent action method and while adding the View, choose the Template as
Empty, Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below
code over there by deleting the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Student Details</h2>


<table border="1" align="center">
<tr>
<td rowspan=4><img src='~/Uploads/@Model.Photo' width="200" height="200" alt="No Image" /> </td>
<td>Sid: @Model.Sid</td>
</tr>
<tr><td>Name: @Model.Name</td></tr>
<tr><td>Class: @Model.Class</td></tr>
<tr><td>Fees: @Model.Fees</td></tr>
<tr>
<td colspan="2" align="center">@Html.ActionLink("Back to Student Details", "DisplayStudents")</td>

236
</tr>
</table>
Generate a view for AddStudent action method and while adding the View, choose the Template as Empty,
Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>


@using (Html.BeginForm("AddStudent", "Student", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid)</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>@Html.LabelFor(S => S.Photo)<br /><input type="file" name="selectedFile" /></div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" name="btnReset" />
</div>
}
@Html.ActionLink("Back to Student Details", "DisplayStudents")

Generate a view for EditStudent action method and while adding the View, choose the Template as Empty,
Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Student Details</h2>


@using (Html.BeginForm("UpdateStudent", "Student", FormMethod.Post, new {enctype="multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Sid)<br />@Html.TextBoxFor(S => S.Sid, new { @readonly = "true" })</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Class)<br />@Html.TextBoxFor(S => S.Class)</div>
<div>@Html.LabelFor(S => S.Fees)<br />@Html.TextBoxFor(S => S.Fees)</div>
<div>
@Html.LabelFor(S => S.Photo)<br />
<img src='~/Uploads/@Model.Photo' width="100" height="100" alt="No Image" style="border:dashed red" />
<input type="file" name="selectedFile" />
</div>
<div>
<input type="submit" value="Update" name="btnUpdate" />
@Html.ActionLink("Cancel", "DisplayStudents")
</div>
}

237
MVC Filters
In ASP.NET MVC, a user request is routed to an appropriate Controller and Action Method. However, there
may be circumstances where you want to execute some logic before or after an Action Method executes or before
or after an ActionResult is processed, and to achieve this ASP.NET MVC provides Filters.

Filters are used to inject extra logic at different levels of MVC Framework’s request processing pipeline
which provide a way for cross cutting concerns like logging, authentication, authorization, and caching.

Initially ASP.NET MVC Framework supported 4 different types of filters like Authorization Filters, Action
Filters, Result Filters, and Exception Filters whereas Authentication Filters are introduced with ASP.NET MVC 5 and
each Filter allows us to introduce logic at different points during the request processing pipeline.

In MVC, filters are classes, and all these classes inherits from a pre-defined class FilterAttribute and
implements some interface. The following table lists filter types and the interface which they implemented:

Filter Types Interface Description


Authentication IAuthenticationFilter These filters run before any other filters run or action method executes.
Authorization IAuthorizationFilter These filters run next of Authentication Filters and before any other
filters run or action method executes.
Action IActionFilter These filters run before and after an action method executes.
Result IResultFilter These filters run before and after the action result is processed.
Exception IExceptionFilter These filters run only if any filter or action method or action result
throws an exception.

Authentication Filters: Authentication filter runs before any other filter or action method executes. Authentication
confirms that you are a valid or invalid user, and these filters must implement the IAuthenticationFilter interface.

Authorization Filters: Authorization Filters are responsible for checking User Access and these filters must
implement the IAuthorizationFilter interface. These filters are used to implement authorization for controllers and
action methods. The Authorize - Attribute is the example of Authorization Filters.

Action Filters: Action Filters can be applied to a controller’s action method or an entire controller. These filters will
be called before the action method starts executing and after the action method has executed. Action filters
implement the IActionFilter interface that has 2 methods OnActionExecuting and OnActionExecuted.
OnActionExecuting method executes before an action method and gives an opportunity to cancel the Action call and
OnActionExecuted method executes after an action method and gives an opportunity to modify the view data that
a controller action method returns.

Result Filters: These filters contain logic that is executed before and after a view result is processed like if we want
to modify a view result right before the view is rendered to browser. OutputCacheAttribute is an example of Result
Filter, and these filters implement IResultFilter interface which contains OnResultExecuting and OnResultExecuted
methods.

ExceptionFilters: These filters can be used to handle errors raised by either a controller’s action methods or action
results i.e., they execute if there are any unhandled exceptions thrown during the execution pipeline. The
HandleErrorAttribute is an example of ExceptionFilters, and they implement IExceptionFilter interface.

238
List of pre-defined filters provided by ASP.NET MVC:
ChildActionOnly: This filter ensures that an action method can be called only as a child method from a view of
another action method. We tend to use this filter to prevent action methods from being invoked directly and if we
try to do that it will throw an error.

OutputCache: One of the best ways to improve the performance of an ASP.NET Application is by caching. With the
help of caching, we can reduce hosting server and database Server round trips. We can apply OutputCache Action
Filter to achieve caching either on an Action Method or on the whole Controller. OutputCache filter has several
properties like CacheProfile, Duration, Location, VaryByParam, VaryByHeader, VaryByCustom etc.

 Duration: Gets or sets the cache duration in seconds.


 VaryByParam: Gets or sets the vary-by-param value and if not specified default value is none.
 VaryByCustom: Gets or sets the vary-by-custom value.
 Location: Gets or sets the location value which is to specify where the output must be cached, it takes an Enum
value which can be Server, Client, Downstream (Proxy Server), ServerAndClient, Any and None, default is Any.
 CacheProfile: Gets or Sets the cache profile value from Web.config file.

ValidateInput: Cross Site Scripting (CSS/XSS) attack is very common and is a well-known attack for web applications,
for example a CSS/XSS attack is basically the result of poor form validation. How CSS/XSS attacks work is at first the
hacker does inject some HTML code into a HTML input field and the data along with the HTML tag is saved to the
database. Now, when there is a need to display the data in a user interface then we will get it from the Database
and a legitimate browser will parse it as HTML code. If the hacker then injects a normal HTML string, then there is
no problem at all but if they inject harmful Java Script code from an input field that might steal valuable information
from the user’s computer, but we are very sure that we never want to allow a user to inject a HTML element through
a form. In traditional Web Forms applications, we use a form validation script (in Java Script very often) to validate
user’s input whereas in MVC the library has done all the job for us, so we need not validate or write lengthy code
externally. In MVC by default it prevents the HTML element as form data, anyway we can use the ValidateInput
attribute to prevent HTML explicitly in this way: [ValidateInput (true)] which can be used either on controller or
action method.

ValidateAntiForgeryToken: This is a built-in functionality provided by Microsoft which developers often use in their
applications for security purposes i.e., to stop CSRF (Cross Site Request Forgery) from hackers. Cross Site Request
Forgery can be defined as, a forgery request, i.e., a fraud or fake request, which comes on an authenticated site from
a cross site and is treated as an authenticated request. For avoiding this situation, Microsoft provides
ValidateAntiForgeryToken functionality which we can use in our application so that no one can hack our site or
invade some critical information.

HandleError: This is an Exception Filter to handle errors in ASP.NET MVC which can be applied over the Action
Method as well as Controller or at the Global Level. The HandleError Error filter has a set of properties that are very
useful in handling the exception.

Authorize: specifies that access to a controller or action method is restricted to users who meet the authorization
requirement. You can apply the Authorize attribute to individual methods as well as the controller class. If you add
the Authorize attribute to the controller class, then any action methods on the controller will be available only to
authenticated users. The Authorize attribute is inheritable which means that you can add it to a base controller class
of yours and thereby ensure that any methods of the derived controllers are also subject to authentication.

239
AllowAnonymous: when applied to a method, the AllowAnonymous attribute instructs the ASP.MVC runtime to
accept and process the call even if the caller is not authenticated. The scenario when the AllowAnonymous comes
handy is when you apply Authorize at the class level and then need to enable free access to some methods like login
action method, registration action methods etc.

To test filters, create a new Table in our “MVCDB” Database with the name Customer using the below code,
and insert some records into the table:

Create Table Customer (Custid Int Primary Key, Name Varchar(50), Balance Money, City Varchar(50), Status Bit
Default 1 Not Null)

Create a new “ASP.NET Web Application” project naming it as “MVCFilters”; choose “Empty Project
Template”, select “MVC” CheckBox and click on “Create” button. First host the Web Application on IIS and then
under Model’s folder add “ADO.NET Entity Data Model” naming it as “TestEF”, choose “EF Designer from database”
(DB First), provide the connection details for our “MVCDB” Database and choose “Department”, “Employee” and
“Customer” tables. Add a controller under Controller’s folder naming it as “HomeController”, delete existing content
under the class and write the code:

using System.Web.UI;
using MVCFilters.Models;
public class HomeController : Controller
{
MVCDBEntities dc = new MVCDBEntities();

#region ChildActionOnly Filter


public ViewResult DisplayDepts()
{
return View(dc.Departments);
}
public ViewResult DisplayEmpsByDept(int Did)
{
var Emps = from E in dc.Employees where E.Did == Did select E;
return View(Emps);
}
#endregion

#region OutputCache Filter


public ViewResult DisplayCustomers1()
{
return View(dc.Customers);
}
[OutputCache(Duration = 45, Location = OutputCacheLocation.Server)]
public ViewResult DisplayCustomers2()
{
return View(dc.Customers);
}

240
[OutputCache(Duration = 45, Location = OutputCacheLocation.Server, VaryByParam = "City")]
public ViewResult DisplayCustomers3(string City)
{
return View(from C in dc.Customers where C.City == City select C);
}
[OutputCache(Duration = 45, Location = OutputCacheLocation.Server, VaryByCustom = "browser")]
public ViewResult DisplayCustomers4()
{
return View(dc.Customers);
}
public ViewResult DisplayCustomers5()
{
return View(dc.Customers);
}
#endregion

#region ValidateInput Filter


public ViewResult GetComments()
{
return View();
}
[HttpPost]
public string GetComments(string txtComments)
{
return txtComments;
}
#endregion

#region ValidateAntiForgeryToken Filter


public ViewResult AddEmployee()
{
return View();
}
[HttpPost]
public string AddEmployee(Employee Emp)
{
Emp.Status = true;
dc.Employees.Add(Emp);
dc.SaveChanges();
return "Record Inserted";
}
#endregion

#region HandleError Filter


public ViewResult DivideNums()
{

241
return View();
}
[HttpPost]
public string DivideNums(int num1, int num2)
{
int result = num1 / num2;
return "Result is: " + result;
}
#endregion
}

Add a view with the name “DisplayEmpsByDept.cshtml”, selecting layout Checkbox and write the below
code in it by deleting the existing code in the file:

@model IEnumerable<MVCFilters.Models.Employee>
@{
Layout = null;
}
<table align="center">
<tr>
<th>@Html.DisplayNameFor(E => E.Eid)</th>
<th>@Html.DisplayNameFor(E => E.Ename)</th>
<th>@Html.DisplayNameFor(E => E.Job)</th>
<th>@Html.DisplayNameFor(E => E.Salary)</th>
<th>@Html.DisplayNameFor(E => E.Status)</th>
</tr>
@foreach (var Emp in Model)
{
<tr>
<td>@Html.DisplayFor(E => Emp.Eid) </td>
<td>@Html.DisplayFor(E => Emp.Ename) </td>
<td>@Html.DisplayFor(E => Emp.Job) </td>
<td align="right">@Html.DisplayFor(E => Emp.Salary) </td>
<td align="center">@Html.CheckBoxFor(E => Emp.Status)</td>
</tr>
}
</table>

Add a view with the name “DisplayDepts.cshtml”, selecting layout Checkbox and write the below code in it
by deleting the existing code in the file:

@model IEnumerable<MVCFilters.Models.Department>
@{
ViewBag.Title = "Display Depts";
}
<table border="1" align="center">

242
<caption>Department Details</caption>
<tr>
<th>@Html.DisplayNameFor(D => D.Did)</th>
<th>@Html.DisplayNameFor(D => D.Dname)</th>
<th>@Html.DisplayNameFor(D => D.Location)</th>
<th>Employees</th>
</tr>
@foreach (var Dept in Model)
{
<tr>
<td>@Html.DisplayFor(D => Dept.Did) </td>
<td>@Html.DisplayFor(D => Dept.Dname) </td>
<td>@Html.DisplayFor(D => Dept.Location) </td>
<td>@Html.Action("DisplayEmpsByDept", new { Did = Dept.Did })</td>
</tr>
}
</table>

ChildActionOnly: in the above case “DisplayDepts” view is internally invoking “DisplayEmpsByDept” action method
so under each “Department” it will display the “Employees” corresponding to that “Department”. If required, we
can also directly call “DisplayEmpsByDept” action method from browser as below and access “Employee” data
corresponding to a particular “Department”.
http://localhost/MVCFilters/Home/DisplayEmpsByDept/10

If we want to restrict accessing the “DisplayEmpsByDept” action method directly from a browser as above
we need to decorate the method with [ChildActionOnly] attribute, so that we are not authorized to call that method
directly and should be invoked only as a child action. To test that go to “HomeController” and add the
“ChildActionOnly” attribute to “DisplayEmpsByDept” action method as following:

[ChildActionOnly]
public ViewResult DisplayEmpsByDept(int Id)
{
var Emps = from E in dc.Employees where E.Did == Id select E;
return View(Emps);
}

Note: now if we try to access “DisplayEmpsByDept” action method directly from a browser we get an error and to
test that try calling the method directly from the browser.

Add a view for “DisplayCustomers1” action method, choosing the layout CheckBox and write the below
code in it by deleting all the existing content in the file:

@model IEnumerable<MVCFilters.Models.Customer>
@{
ViewBag.Title = "Display Customer";
}

243
<table align="center" border="1">
<tr>
<td colspan="5">
<h3 style="text-align:center">Request Processed Time: @DateTime.Now.ToString("T")</h3></td>
</tr>
<tr>
<th>@Html.DisplayNameFor(C => C.Custid)</th>
<th>@Html.DisplayNameFor(C => C.Name)</th>
<th>@Html.DisplayNameFor(C => C.Balance)</th>
<th>@Html.DisplayNameFor(C => C.City)</th>
<th>@Html.DisplayNameFor(C => C.Status)</th>
</tr>
@foreach (var Customer in Model)
{
<tr>
<td>@Html.DisplayFor(C => Customer.Custid)</td>
<td>@Html.DisplayFor(C => Customer.Name)</td>
<td align="right">@Html.DisplayFor(C => Customer.Balance)</td>
<td>@Html.DisplayFor(C => Customer.City)</td>
@if (Customer.Status == true)
{
<td>Active</td>
}
else
{
<td>In-Active </td>
}
</tr>
}
</table>

Note: same as the above create views for the remaining 4 “DisplayCustomers” action methods also with the same
code.

OutputCache: in the above case “DisplayCustomers1” is not cached, so whenever we refresh the View the Processed
Time on top of the view will change which provides clarity for us that every time the View is refreshed the page gets
re-processed. Rest of the 3 “DisplayCustomers” action methods are cached for “45” seconds because we specified
that in the “Duration” property, so in that period if a new request is sent to those action methods it will display the
cached output of the View only without processing the whole View again and again.

Location attribute is used on “DisplayCustomers2” action method to specify the cache copy should be
created on the server because the default value is “Any” and in this case server decides where to store the cache
copy, but when changed to Server then cache copy will be stored on the Server Machine only.

VaryByParam attribute is used on “DisplayCustomers3” action method to specify that there should be a
separate cache copy created for each parameter value that is sent to the “City” attribute.

244
http://localhost/MVCFilters/Home/DisplayCustomers3?City=Bengaluru
http://localhost/MVCFilters/Home/DisplayCustomers3?City=Chennai
http://localhost/MVCFilters/Home/DisplayCustomers3?City=Delhi

VaryByCustom attribute is used on “DisplayCustomers4” action method to specify that there should be a
separate cache copy created for each type of browser i.e., 1 copy for Edge and 1 copy for IE, etc.

Without specifying cache details on the top of an action method we can use “CacheProfiles” i.e., by storing
the details of cache under “Web.config” file and then we can use them on action methods.

To test this, go to “Web.config” file and write the following code under <system.web> tag:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="MyCacheProfile" duration="45" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>

Now on the top of “DisplayCustomers5” action method specify the “Cache Profile” details as following:
[OutputCache(CacheProfile = "MyCacheProfile") ]
public ViewResult DisplayCustomers5()

Add a View to “GetComments” action method, choosing the layout CheckBox and write the below code in it:
@using(Html.BeginForm())
{
<div>
@Html.Label("Comments:")<br />@Html.TextArea("txtComments")
</div>
<div>
<input type="submit" value="Submit" name="btnComment" />
</div>
}

ValidateInput: Run the above view, enter some input into the TextArea and click on the “Submit” button which will
display the output on browser. Whereas if we try to enter the comments with any Html tags, for example “<b>Hello
World</b>” we get an error as following: “A potentially dangerous Request.Form value was detected from the client
(txtComments="<b>Hello</b>").”, because by default “ValidateInput” filters value is “true” only which will not allow
any Html Elements, whereas if we want to allow Html Elements as input then set the “ValidateInput” filter value as
“false” for “GetComments” Post action method as following:

[HttpPost, ValidateInput(false)]
public string GetComments(string txtComments)

Add a View to “AddEmployee” action method choosing the layout CheckBox and write the below code in it:
@model MVCFilters.Models.Employee

245
@using (Html.BeginForm())
{
<div>@Html.LabelFor(E => E.Ename)<br />@Html.TextBoxFor(E => E.Ename)</div>
<div>@Html.LabelFor(E => E.Job)<br />@Html.TextBoxFor(E => E.Job)</div>
<div>@Html.LabelFor(E => E.Salary)<br />@Html.TextBoxFor(E => E.Salary)</div>
<div>@Html.LabelFor(E => E.Did)<br />@Html.TextBoxFor(E => E.Did)</div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" />
</div>
}

ValidateAntiForgeryToken: run the above view to add a new Employee. The problem in the above is if we use the
“View Page Source” option of browser, copy the content from <form> to </form> tag, paste it in a new file and
change the “action” attribute value of <form> tag from “MVCFilters/Home/AddEmployee” to
http://localhost/MVCFilters/Home/AddEmployee, save the file as “AddEmployee.html” and when we open the
“AddEmployee.html” file in browser using it’s physical path and try to add a new Employee, still it adds a record into
the table. To restrict this, we need to use the “ValidateAntiForgeryToken” filter and to test it do the following:

Step 1: re-write the AddEmployee, HttpPost method as following:


[HttpPost, ValidateAntiForgeryToken]
public string AddEmployee(Employee Emp)

Step 2: in “AddEmployee.cshtml” file write “@Html.AntiForgeryToken()” statement inside the “<form>” tag, so that
if anyone copies the source code and try to use it for adding a new record i.e., same as we discussed above will not
be able to invoke the action method to add a record into the table.

Add a view to “DivideNums” action method choosing the layout CheckBox and write the below code in it:
@using (Html.BeginForm())
{
<div>@Html.Label("Enter 1st Number: ")<br />@Html.TextBox("num1")</div>
<div>@Html.Label("Enter 2nd Number: ")<br />@Html.TextBox("num2")</div>
<div>
<input type="submit" value="Divide" name="btnDiv" />
<input type="reset" value="Reset" />
</div>
}

HandleError: in the above view if we give the value of 2 nd number as zero or enter any non-integer values in both
Textbox’s or if the entered integer value is beyond the size of an integer, Exception gets raised in the program and
display the error details on browser screen and we call that screen as “Yellow screen of death.”. To avoid the problem
of displaying error details (Exception Messages) or “Yellow screen of death” to end users do the following changes
in your code:

Step 1: add a view in Shared folder of views with the name “Error.cshtml” without choosing a layout and write the
below code under its “<div>” tag:

246
<h1 style="background-color:lightgoldenrodyellow;color:orangered;text-align:center;text-decoration:underline">
Server Error Page
</h1>
<h3>An error occurred while processing your request. Re-check your input or contact customer support.</h3>

Step 2: go to “Web.config” file and “On” the “custom errors” option by writing the following code under
“<system.web>” tag:
<customErrors mode="On" />

Step 3: now in the HomeController class re-write the “DivideNums” HttpPost action method as below:
[HttpPost, HandleError]
public string DivideNums(int num1, int num2)

Now if we get any Internal Server Errors (Exceptions) in “DivideNums” methods, it will automatically
redirect to “Error.cshtml”.

Now in “HomeController” add a new action method “ShowView” as following:


[HandleError]
public ViewResult ShowView()
{
return View();
}
For the above action method, we have not created any view, so if we try to call this action method from a
browser it will raise an error and redirect to “Error.cshtml” view only because we have decorated the method with
“HandleError” attribute.

Now if we try to call any action method which is not existing in the application then we get an “on screen
error” again without displaying “Error.cshtml” with Http Status Code 404 because currently “HandleError” attribute
will handle only the errors with Status Code 5XX series only i.e., Internal Server Errors or Exceptions, whereas if we
want to handle client errors with their appropriate “Http Status Codes” do the following:

Step 1: add a new controller in Controller’s folder naming it as ErrorController and write the below code in it:
public class ErrorController : Controller
{
public ActionResult BadRequest()
{
return View();
}
public ActionResult Unauthorized()
{
return View();
}
public ActionResult PaymentRequired()
{
return View();
}

247
public ActionResult Forbidden()
{
return View();
}
public ActionResult NotFound()
{
return View();
}
}

Step 2: now under Shared folder of Views folder, add a new view naming it as “NotFound.cshtml” without choosing
a layout and write the below code under the “<div>” tag:

<h1 style="background-color:lightgoldenrodyellow;color:orangered;text-align:center;text-decoration:underline">
Page Not Found
</h1>
<h3>The requested page is either not available or moved to a different location or it's under construction or
maintanance.</h3>

Step 3: now go to “Web.config” file and re-write the custom errors element as following:
<customErrors mode="On">
<error statusCode="400" redirect="/MVCFilters/Error/BadRequest"/>
<error statusCode="401" redirect="/MVCFilters/Error/Unauthorized"/>
<error statusCode="402" redirect="/MVCFilters/Error/PaymentRequired"/>
<error statusCode="403" redirect="/MVCFilters/Error/Forbidden"/>
<error statusCode="404" redirect="/MVCFilters/Error/NotFound"/>
</customErrors>

Note: same as the above you can add a separate error page for each Http Status Code as per your requirements.

Handling Errors Controller Level: in the above case to handle errors we are applying “HandleError” attribute for
each Action method and without doing that we can apply “HandleError” attribute directly on the Controller class so
that it applies to all Action methods under that Controller and to test that delete “HandleError” attribute we have
used on “Http Post” action method of “DivideNums” and “ShowView” action method, and then use it on the
Controller class i.e., “HomeController” as following:

[HandleError]
public class HomeController : Controller

Handling Errors Globally: in the above approach we are applying “HandleError” attribute on Controller class which
must be done on every Controller in the project to handle the errors. To avoid this, we can apply filters globally to
the whole application or project and to do that do the following:

Step 1: Add a Code File under “App_Start” folder, naming it as “FilterConfig.cs” and write the below code in it:
using System.Web.Mvc;
namespace MVCFilters

248
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
}

Step 2: go to “Global.asax.cs” file in the project and write the below statement in “Application_Start” method:
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

Note: with the above action, errors that occur in all the action methods of all the controllers get handled.

Authentication and Authorization: Authentication is the process of obtaining identification credentials such as
username (Id) and password from a user and validating those credentials against some authority. If the credentials
are valid, the user that submitted the credentials is considered an authenticated user and once the user has been
authenticated, the authorization process determines whether that user has access to a resource or not.

ASP.NET supports different types of authentications like:


 Anonymous Authentication
 Windows Authentication
 Forms Authentication
 Open Authentication

Anonymous Authentication: This gives users access to the public areas of our Application without asking them for a
username or password. By default, the “IUSR” account, which was introduced in IIS 7.0, is used to allow anonymous
access. By default, IIS uses Anonymous authentication for every Application. To test this, open “IIS Manager” and in
the LHS we find “Connections Panel” and under that we find the “Server Name” (which will be same as our computer
name), expand it and under that we find a node “Sites”, expand it and under that we find a node “Default Web Site”,
expand it and under that we find our project “MVCFilters” (because we hosted it in IIS from our Visual Studio by
creating a Virtual Directory), select it and then in the RHS we find “Authentication” option, click on it which display
the various authentication modes available and under that we can see “Anonymous Authentication” is enabled.
Right click on the “Anonymous Authentication” and select “Edit” which display the user account i.e., “IUSR” which is
used for “Anonymous Authentication” as below:

Windows Authentication: we use Windows authentication when our “IIS Server” runs on a corporate network that
is using Microsoft Active Directory service domain identities or other Windows accounts to identify users. Windows

249
Authentication is a secure form of Authentication because the username and password are hashed before being
sent across the network. When you enable Windows Authentication, the client browser sends a strongly hashed
version of the password in a cryptographic exchange to the Web Server. This Authentication mode is best suitable
for Intranet Applications only.

Implementing Windows Authentication using Authorize Attribute: Create a new “ASP.NET Web Application”
project, naming it as “MVCAppWithWindowsAuth”, choose Empty Project Template, select “MVC CheckBox” and
click on the “Create Button”. Now host the project under IIS by creating a Virtual Directory and then open IIS
Manager select our “MVCAppWithWindowsAuth” project under the “Default Web Site” and now on the RHS select
the option “Authentication” will displays Authentication options and in that if you notice “Anonymous
Authentication” is enabled by default, so right click on it and select the option “Disable” and then right click on the
“Windows Authentication” and select the option “Enable” because by default it is “Disabled”.

Add a controller under Controller’s folder naming it as HomeController, add a view to Index action method
choosing a layout, delete the existing content in it and write the below code over there:

@{ ViewBag.Title = "Site - Home Page"; }


<h2>Site Home Page</h2>
<h3>
@Html.ActionLink("Manager Home Page", "Home", "Manager") <br />
@Html.ActionLink("Manager Help Page", "Help", "Manager") <br />
@Html.ActionLink("Staff Home Page", "Home", "Staff") <br />
@Html.ActionLink("Staff Help Page", "Help", "Staff")
</h3>
Add another 2 controllers under the Controllers folder with the names “ManagerController” and
“StaffController”, delete the existing Index Action method under the classes and write the below code in the 2 new
controller classes:

public class ManagerController : Controller


{
public ActionResult Home()
{
return View();
}
public ActionResult Help()
{
return View();
}
}

public class StaffController : Controller


{
public ActionResult Home()
{
return View();
}

250
public ActionResult Help()
{
return View();
}
}

Now add views to all the above action methods, choosing a layout and write the following code under them
by deleting the existing code in it:

Code under Manager’s Home - Action Method’s view:


@{ ViewBag.Title = "Manager - Home Page"; }
<h2>Manager Home Page</h2>
<h3>This page is accessible only to Managers.</h3>
<h4>Current User: @HttpContext.Current.User.Identity.Name</h4>
<br />
Back to site @Html.ActionLink("home page", "Index", "Home")

Code under Manager’s Help - Action Method’s view:


@{ ViewBag.Title = "Manager - Help Page"; }
<h2>Manager Help Page</h2>
<h3>This page is accessible to everyone.</h3>
<h4>Current User: @HttpContext.Current.User.Identity.Name</h4><br />
Back to site @Html.ActionLink("home page", "Index", "Home")

Code under Staff Home - Action Method’s view:


@{ ViewBag.Title = "Staff - Home Page"; }
<h2>Staff Home Page</h2>
<h3>This page is accessible only to Staff Members.</h3>
<h4>Current User: @HttpContext.Current.User.Identity.Name</h4><br />
Back to site @Html.ActionLink("home page", "Index", "Home")

Code under Staff Help - Action Method’s view:


@{ ViewBag.Title = "Staff - Help Page"; }
<h2>Staff Help Page</h2>
<h3>This page is accessible to everyone.</h3>
<h4>Current User: @HttpContext.Current.User.Identity.Name</h4><br />
Back to site @Html.ActionLink("home page", "Index", "Home")

Now run Home Controller’s - Index Action method which will display links for navigating to Manager Home
Page, Manager Help Page, Staff Home Page and Staff Help Page, and once we click on any link those pages get
opened without any restrictions because currently the site is running in Anonymous Authentication whereas if we
want Manager Home Page to be accessible only to Manager’s and Staff Home Page to be accessible only to Staff, we
can do that by using “Authorize” filter.

To do that first we need to create new user accounts on our machine and to create new user accounts do
the following, open “Computer Management” window and in that we find “Local Users and Groups” in LHS, expand

251
it and select Users which display users on your computer. To create a new user account right click on “Users” and
select “New User” option which opens a window and in that enter “UserName”, “Password” and “Confirm Password”
values, uncheck the CheckBox “User must change password at next logon” and check the CheckBox’s “User cannot
change password” and “Password never expires”, and then click “Create” button to create the user. Follow this
process and create 8 new user accounts with the name Manager1, Manager2, Staff1, Staff2, Staff3, Staff4, Staff5
and Staff6.

Now go to ManagerController class and use Authorize attribute on Home Action method as following:
[Authorize(Users = "Server\\Manager1, Server\\Manager2")]
public ActionResult Home()

Same as above go to StaffController class and use Authorize attribute on Home Action method as following:
[Authorize(Users = "Server\\Staff1, Server\\Staff2, Server\\Staff3, Server\\Staff4, Server\\Staff5, Server\\Staff6")]
public ActionResult Home()

Note: in the above case Server is my machine name and same as that you need to write your machine name there.

Now use the switch user option in your machine, log in by using any new user account and based on the
user you have logged in those Index Action Methods will be accessible whereas rest of other Action Methods in the
controller will run in Anonymous Authentication.

Applying Authorize Filter - Controller Level: if required we can use Authorize Filter - Controller level and in that case
all the Action Methods of that controller will be accessible to valid users only and we do that as following:

[Authorize(Users = "Server\\Manager1, Server\\Manager2")]


public class ManagerController : Controller
{
}
[Authorize(Users = "Server\\Staff1, Server\\Staff2, Server\\Staff3, Server\\Staff4, Server\\Staff5, Server\\Staff6")]
public class StaffController : Controller
{
}

Allowing Anonymous Authentication to some Action Methods in case we apply Authorize Filter Controller level:
when we apply Authorize Filter in controller level all action methods in that controller will be running under
Authentication Mode and if we want any action method to be running in Anonymous Authentication mode we need
to use “AllowAnonymous” filter on those Action Methods. In our above example we want Help Action Methods of
ManagerController and StaffController to run in Anonymous Authentication and to do that add “AllowAnonymous”
attribute to those methods in both controllers as following:
[AllowAnonymous]
public ActionResult Help()

Role Based Authentication: in the above case we have given authentication to users by specifying their names in a
comma-separated list but if at all we have multiple users like 5 Managers and 20 Staff Members we need to specify
the complete list of members under Authorize Filter and to avoid this we have an option of Role Based
Authentication.

252
User Groups: under the Operating System apart from Users we also find Groups and to check this open “Computer
Management” window, expand “Local Users and Groups” option which displays Users and Groups below, when we
select users, it displays existing users and when we select groups’ displays existing groups. Every group is a collection
of users, and every user must be members of some group, to check this, select users, double click on any username
which displays a window “Administrator Properties” and in that we find a tab “Member Of” click on it which displays
the list of groups to which this user belongs to and these groups are what we call as roles in our MVC Applications.

We can also create our own groups or roles under O.S. and to do that right click on Groups, select “New
Group” which opens a Window, enter group name in it as “ManagerGroup”, click on “Add” button which opens a
window in that under the last TextBox enter “Manager1” click “Check Names” button which displays
“ComputerName\Manager1” and repeat the same process to add “Manager2” also to this group. Now follow the
same process to create “StaffGroup” and add the 6 Staff members to this group.

Now replace “Users” property under Authorize filter to “Roles” and specify the role name which should be
as below for ManagerController and StaffController:

[Authorize(Roles = "ManagerGroup")]
public class ManagerController : Controller

[Authorize(Roles = "StaffGroup")]
public class StaffController : Controller

Custom Filters: In MVC, filters are used to inject logic at different levels of request processing and allow us to share
logics across Controllers and Action Methods. We are provided with various filters in MVC which we have used above
and apart from that we can also create our own filters to implement logic at various levels and we call them as
“Custom Filters”. We write custom filters for various reasons, like logging or for saving data to a Database before
any action execution or we could also create a filter for fetching data from the Database and setting them as global
values of our application. For example, let’s say we want to run security logic or a logging logic across the controllers,
and to do so; we can write a filter containing those logics and enable them across all controllers. When we enable a
filter across all controllers or actions, the filter executes on all upcoming HTTP requests.

As discussed, in ASP.NET MVC we have 5 types of filters and the sequence of running those filters is as below:
 The Authentication filter runs before any other filter or action method.
 The Authorization filter runs after the Authentication filter and before any other filter or action method.
 The Action filter runs before and after any action method.
 The Result filter runs before and after execution of any action result.
 The Exception filter runs only if filters or action methods or action results throw an exception.

The below diagram, explains the sequence of filter execution as shown below:

253
To create a custom filter, we need to perform the following tasks:
 Define a class inheriting from the pre-defined class “FilterAttribute”, so that the new class is also a Filter.
 Override any of the methods that are present in “FilterAttribute” class as per our requirements (optional).
 Implement any of the 5 filter “Interfaces” based on the type of Filter we are implementing, for example if we
are implementing Authentication Filters, we should implement IAuthenticationFilter interface and if we are
implementing Authorization Filters, we should implement IAuthorizationFilter interface and so on (mandatory).
 Apply the new filter on the Controller class or Action method where we want to use it.

Implementing Forms Authentication by defining a Custom Filter:


Create a new “ASP.NET Web Application” project naming it as “MVCAppWithFormsAuth”, choose Empty
Project Template, select “MVC Check Box” and click on the “Create Button”. Host the project on IIS by creating a
Virtual Directory. Add a controller in Controller’s folder naming it as “HomeController”, add a view to Index action
method by choosing the layout and write below code in it:

<h1 style="background-color:red;color:yellow;text-align:center">Home Page</h1>


<h4>This is Home Page of the site.</h4>

Right now, we can run the Index View or any other Views in the site directly because Anonymous
Authentication is enabled, but if we want to implement Forms Authentication, so that only Registered Users can
access the pages in site, we need to do that by following the below process:

Step 1: create a new table under our “MVCDB” database as following:

Create Table Users (UserId Varchar(20) Primary Key, Name Varchar(50), Password Varchar(16), Email Varchar(50),
Mobile Varchar(10), Status Bit Not Null Default 1)

Step 2: add ADO.NET Entity Data Model (DB First) in the “Models” folder naming it as “TestEF”, choose “EF Designer
from database” (DB First), provide the connection details for our “MVCDB” Database and choose “Users” table which
will create the necessary classes for working with data and here the Model class representing “Users” table will be
having the name as “User”.

Step 3: now we need to design Register and Login forms which requires data validations and to validate the data we
need to use data annotations. To do that let’s define 2 new classes “RegisterModel” and “LoginModel”, and apply
data annotations on those classes, so that we can use those classes for designing the Views by performing Model
Binding and we call this as MVVM (Model View – View Model) architecture.

Add 2 new classes in Model’s folder naming them as “RegisterViewModel.cs” and “LoginViewModel.cs” and
write the below code under the 2 classes:

using System.ComponentModel.DataAnnotations;
public class RegisterViewModel
{
[Display(Name = "User Id")]
[Required(ErrorMessage = "Can't leave the field empty.")]
[RegularExpression("[A-Za-z0-9]{6,20}", ErrorMessage = "User Id value is invalid.")]
public string UserId { get; set; }

254
[Required(ErrorMessage = "Can't leave the field empty.")]
[RegularExpression("[A-Za-z\\s]{3,50}", ErrorMessage = "Name value is invalid.")]
public string Name { get; set; }

[DataType(DataType.Password)]
[Required(ErrorMessage = "Can't leave the field empty.")]
[RegularExpression("[A-Z]{1}[a-z0-9@#$%_-]{7,15}", ErrorMessage = "Password is invalid.")]
public string Password { get; set; }

[Display(Name = "Confirm Password")]


[DataType(DataType.Password)]
[Compare("Password")]
public string ConfirmPassword { get; set; }

[Required(ErrorMessage = "Can't leave the field empty.")]


[DataType(DataType.EmailAddress)]
public string Email { get; set; }

[Required(ErrorMessage = "Can't leave the field empty.")]


[RegularExpression("[6-9]\\d{9}", ErrorMessage = "Phone is invalid.")]
public string Mobile { get; set; }
}

using System.ComponentModel.DataAnnotations;
public class LoginViewModel
{
[Display(Name = "User Id")]
[Required(ErrorMessage = "Can't leave the field empty.")]
[RegularExpression("[A-Za-z0-9]{6,20}", ErrorMessage = "User Id value is invalid.")]
public string UserId { get; set; }

[DataType(DataType.Password)]
[Required(ErrorMessage = "Can't leave the field empty.")]
[RegularExpression("[A-Z]{1}[a-z0-9@#$%_-]{7,16}", ErrorMessage = "Password is invalid.")]
public string Password { get; set; }
}

Step 4: add a new Controller under Controller’s folder naming it as “AccountController” and write the below code in
it by deleting all the existing code under the class:

using MVCAppWithFormsAuth.Models;
public class AccountController : Controller
{
MVCDBEntities dc = new MVCDBEntities();
public ViewResult Register()
{

255
return View();
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
else
{
User user = new User { UserId = model.UserId, Name = model.Name, Password = model.Password,
Email = model.Email, Mobile=model.Mobile, Status = true };
dc.Users.Add(user);
dc.SaveChanges();
return RedirectToAction("Login");
}
}
public ViewResult Login()
{
return View();
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
else
{
var user = from u in dc.Users where u.UserId == model.UserId && u.Password == model.Password &&
u.Status == true select u;
if(user.Count() == 0)
{
ModelState.AddModelError("", "Invalid Credentials");
return View(model);
}
else
{
Session["UserKey"] = Guid.NewGuid();
return RedirectToAction("Index", "Home");
}
}
}
}

256
Step 5: Add a view to Registration Action method by choosing “Create” under “Template:” DropDownList,
“RegisterViewModel (MVCAppWithFormsAuth.Models)” under “Model class:” DropDownList, uncheck all the
CheckBox’s on the screen and click on “Add” button:

Same as the above add a View to Login Action method by choosing “Create” under “Template:”
DropDownList, “LoginViewModel (MVCAppWithFormsAuth.Models)” under “Model class:” DropDownList, uncheck
all the CheckBox’s on the screen and click on “Add” button:

Install “Bootstrap”, “jQuery”, “jQuery.Validation”, and “Microsoft.jQuery.Unobtrusive.Validation” libraries


in our project using “Nuget Package Manager” and then drag and drop the following files into the “<head>” section
of “Register.cshtml” and “Login.cshtml”: “jquery-3.7.1.min.js”, “jquery.validate.min.js”,
“jquery.validate.unobtrusive.min.js” from Script’s folder and “bootstrap.min.css” from Content’s folder.

Now we can create new user accounts by using “Register View” and login into the application by using
“Login View” and once we successfully login, it will take to “Home Controller’s - Index Page”, but we can open this
Page even by directly calling it also because, right now we did not apply “Authentication” in our application.

Step 6: to apply Authentication let us define a custom “Authentication Filter” class under the Project. To do that,
first add a new folder under the project naming it as “Filters” and under that folder add a class naming it as
“AuthenticateFilter.cs” and write the below code under the class:

257
using System.Web.Mvc;
using System.Web.Mvc.Filters;
public class AuthenticateFilter : FilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
if (string.IsNullOrEmpty(Convert.ToString(filterContext.HttpContext.Session["UserKey"])))
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
if (filterContext.Result == null || filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/Account/Login");
}
}
}

Note: as explained above every filter should inherit from “FilterAttribute” class and implement any of the 5 pre-
defined filter Interfaces based on the type of filter we want to implement. In the current context we are
implementing an Authentication Filter, so we need to implement “IAuthenticationFilter” interface and write the logic
for the 2 abstract methods of the interface and those are: “OnAuthentication” and “OnAuthenticationChallenge”.

Step 7: now go to “HomeController.cs” file and apply the “AuthenticateFilter” attribute on the class so that
Authentication comes into picture when we try to access the Action methods of “HomeController” class and to that
first import the namespace “MVCAppWithFormsAuth.Filters” and then apply the filter on “HomeController” class as
below:
[AuthenticateFilter]
public class HomeController : Controller

From now when we try to access any Action Method of “Home Controller”, first “AuthenticateFilter” class
will check whether the “User” has a “UserKey” value which we have given on successful login to each User by storing
it in a Session. If that “UserKey” value is missing then it will redirect the User to “Login View” of “AccountController”,
so that unless and until a User is logged in to the application, he/she can’t access any page of “Home Controller”.

Note: If we want to apply this behavior to all the other Controllers in our Application, use the “AuthenticateFilter”
attribute on all the Controller Classes in the project except on “AccountController” class.

258
Ajax and JQuery
Ajax stands for Asynchronous JavaScript and XML is a web development technique using many web
technologies on the client side to create asynchronous web applications. With Ajax, Web Pages can send and retrieve
data from a server asynchronously (in the background) without interfering with the display and behavior of the
existing page. By de-coupling the data interchange layer from the presentation layer, Ajax allows web pages to
change content dynamically without the need to reload the entire page.

Ajax is not a single technology but rather a group of technologies like HTML and CSS are used in
combination, to mark up and style the information. The Web Page will be modified by Java Script to dynamically
display and allow the user to interact with the new information. The built-in “XMLHttpRequest” object within Java
Script is used to execute Ajax on Web Pages allowing Web Applications to load content on to the screen without
refreshing the page. XML or JSON are used for inter-change of the data. Ajax is not a new technology, or different
language, just existing technologies used in new ways.

Note: different browsers implement the Ajax differently that means if you’re adopting the typical Java Script way to
implement the Ajax you must write different code for different browsers to ensure that Ajax would work cross-
browser. But fortunately, JQuery simplifies the process of implementing Ajax by taking care of those browser
differences. It offers simple methods such as load(), $.get(), $.post(), etc. to implement the Ajax that works
seamlessly across all the browsers. XML is commonly used as the format for receiving server data, although any
format, including plain text, can be used. In practice, modern implementations commonly utilize JSON instead of
XML due to the advantage of JSON being native to Java Script.

To work with Ajax and JQuery, create a new “ASP.NET Web Application” project, naming it as
“MVCAppUsingAjax”, choose “Empty Project Template”, select MVC - Check Box and click on the Create - Button.
Add a folder under the project naming it as “Matches”, add an “XML File” under this folder naming it as “Score.xml”
and write the following code in it:

<Match1>
<Score>Match starts at 7:00 PM IST</Score>
</Match1>

To work with JQuery, we need to install the JQuery plug-in in our project and to do that open “Nuget
Package Manager”, search for “JQuery” and install “jQuery by jQuery Foundation, Inc.,” (current version is 3.7.1),
which will add a new folder under the project with the name Scripts and installs all the JQuery files into the folder.

Add a Controller in Controller’s folder naming it as “HomeController” and write the below code in the class:
using System.Xml.Linq; //For using LINQ to XML
public string GetScore()
{
//Gets the physical path of the file for the given virtual path
string physicalPath = Server.MapPath("~/Matches/Score.xml");
//Loads the XML file into the application memory from the specified location
var doc = XElement.Load(physicalPath);
//Reads the value or content of “Score” element from the xml file which is loaded
string score = doc.Element("Score").Value;
return score;
}

259
Now add a view to “Index” action method without choosing any layout and drag & drop the JQuery file
“jquery-3.7.1.min.js” from “Scripts” folder into the head section and write the below code under “<body>” tag by
deleting the existing “<div>” tag in it:

<body onload="LoadData()">
<div style="background-color:lightgreen;color:blueviolet">
Date & Time: @DateTime.Now.ToString()
</div>
<div style="background-color:yellow;color:red">
<marquee id="m1" behavior="alternate"></marquee>
</div>
<div style="background-color:coral;color:chartreuse">
Date & Time: @DateTime.Now.ToString()
</div>
<script>
function LoadData()
{
$.ajax({
url: "/Home/GetScore",
type: "get",
cache: false,
success: F1,
error: F2
});
window.setTimeout("LoadData()", 1000);
}
function F1(responseString)
{
$("#m1").html(responseString);
}
function F2()
{
window.alert("Error in server.");
}
</script>
</body>

Now run the Index View and watch the output which will display the current score value that is present
inside of “<Score>” element under the XML file and whenever we change the value under “<Score>” element it will
automatically display the modified score value with-in the “<marquee>” element of the page, because we have
called the “setTimeout” function with an interval of 1 second (1000 MilliSeconds) and all this happens behind the
screen without submitting the page to server, by Ajax.

Implementing Auto-Complete TextBox using Ajax and JQuery: Add “ADO.NET Entity Data Model” item under
Model’s folder of our previous project i.e., “MVCAppUsingAjax”, naming it as “TestEF”, choose “EF Designer from
database”, configure it with “Northwind” Database and choose the table “Products”.

260
Add a controller under Controller’s folder naming it as “ProductController” and write the below code in it:
using MVCAppUsingAjax.Models;
public class ProductController : Controller
{
NorthwindEntities dc = new NorthwindEntities();
public ViewResult DisplayProducts()
{
return View(dc.Products);
}
[HttpPost]
public ViewResult SearchProduct(string SearchTerm)
{
List<Product> Products;
if (SearchTerm.Trim().Length == 0)
{
Products = dc.Products.ToList();
}
else
{
//You can implement the Query in any of the below 2 ways:
Products = (from P in dc.Products where P.ProductName.Contains(SearchTerm) select P).ToList();
Or
Products = dc.Products.Where(P => P.ProductName.Contains(SearchTerm)).ToList();
}
return View("DisplayProducts", Products);
}
public JsonResult GetProducts(string term)
{
List<string> Products = dc.Products.Where(
P => P.ProductName.StartsWith(term)).Select(P => P.ProductName).ToList();
return Json(Products, JsonRequestBehavior.AllowGet);
}
}

Install “JQuery.UI.Combined” (for “AutoComplete” functionality) and “JQuery.UI.Theme.uidarkness” (for


setting a “Theme” for “AutoComplete” output) plug-ins in our project using “Nuget Package Manager”, add a view
to “DisplayProducts” Action method without choosing any layout and do the following in the View file:

Add the below statement on top of the View:


@model IEnumerable<MVCAppUsingAjax.Models.Product>

Drag and drop the below “CSS” and “JS” files under the <head> tag:
<script src="~/Scripts/jquery-3.7.1.min.js"></script>
<script src="~/Scripts/jquery-ui-1.13.2.min.js"></script>
<link href="~/Content/themes/ui-darkness/jquery.ui.theme.css" rel="stylesheet" />

261
Write the below logic for “AutoComplete” within the <head> tag:
<script>
$(function () {
$("#SearchTerm").autocomplete({
source: '@Url.Action("GetProducts")'
});
});
</script>

Now write the following code under <div> tag of body:


@using (Html.BeginForm("SearchProduct", "Product"))
{
<center>
<b>Product Name:</b>
@Html.TextBox("SearchTerm")
<input type="submit" id="btnSubmit" value="Search" />
</center>
}
<table border="1" align="center">
<caption>Product Details</caption>
<tr>
<th>@Html.DisplayNameFor(P => P.ProductID)</th>
<th>@Html.DisplayNameFor(P => P.ProductName)</th>
<th>@Html.DisplayNameFor(P => P.CategoryID)</th>
<th>@Html.DisplayNameFor(P => P.UnitPrice)</th>
<th>@Html.DisplayNameFor(P => P.UnitsInStock)</th>
</tr>
@foreach (var Product in Model)
{
<tr>
<td>@Html.DisplayFor(P => Product.ProductID)</td>
<td>@Html.DisplayFor(P => Product.ProductName)</td>
<td>@Html.DisplayFor(P => Product.CategoryID)</td>
<td>@Html.DisplayFor(P => Product.UnitPrice)</td>
<td>@Html.DisplayFor(P => Product.UnitsInStock)</td>
</tr>
}
</table>

262
ASP.NET Web API
ASP.NET Web API (Application Programming Interface) is a framework for building HTTP Services that can
be accessed from any client including browsers, desktops, and mobile devices. It is an ideal platform for building
“Restful Applications” on the .NET Framework.

In computer programming, an API is a set of sub-routines (methods) definitions, protocols, and tools for
building software and applications. Putting in simple terms, API is an interface which has a set of methods that allow
programmers to access specific features or data of an application, operating system, or other services.

Web API as the name suggests, is an API over the Web which can be accessed using HTTP protocol. It is a
concept and not a technology. We can build Web API using different technologies such as Java, .NET, Python etc. For
example, Twitter’s REST API’s provide programmatic access to read and write data using which we can integrate
twitter’s capabilities into our own application.

The ASP.NET Web API is an extensible framework for building HTTP based services that can be accessed in
different applications on different platforms such as Web, Windows, and Mobile etc. It works the same way as an
ASP.NET MVC Web Application except that it sends Data as a response instead of Views. It is like a Web Service or
WCF Service, but the exception is that it only supports HTTP Protocol.

Background of Web API: Connectivity between applications is a very important aspect from a business applications
perspective. Nowadays there are a lot of mobile applications and single page applications are being created and such
applications needs a strong service end that can provide these applications with the data and CRUD operations on
the data.

SOAP and ASP.NET Web Services: Traditionally, Web Services using SOAP and XML provided a great way of creating
connected web applications. SOAP is a standard XML based protocol that communicates over HTTP. We can think of
SOAP as message format for sending messages between applications using XML. It is independent of technology,
platform, and language too. ASP.NET Web Services provided an excellent way of creating SOAP based Web Services.

Problems with SOAP and Web Services: SOAP offered an excellent way of transferring the data between the
applications, but the problem with SOAP was that along with data a lot of other Metadata also needs to get
transferred with each request and response. This extra information is needed to find out the capabilities of the
service and other Meta Data related to the data that is being transferred coming from the server. This makes the
payload heavy even for small data. Also, Web Services needed the clients to create the proxy on their end. These
proxies will do the marshaling and un-marshaling of SOAP WSDL and make the communication between the
application and the Web Service possible. The problem with this proxy is that if the service is updated and the proxy
on the client is not, then the application might behave incorrectly.

263
Introduction of REST: REST stands for Representational State Transfer. This is a protocol for exchanging data over a
distributed environment. The main idea behind REST is that we should treat our services as resources, and we should
be able to use simple HTTP Protocols to perform various operations on that resource. For example, when we talk
about the Database as a resource, we usually talk in terms of CRUD operations i.e., Create (Insert), Retrieve (Select),
Update and Delete. Now the philosophy of REST is that for a remote resource all these operations should be possible,
and they should be possible using simple HTTP Protocols. Now the basic CRUD operations are mapped to the HTTP
Protocols in the following manner:

 GET: this map to the R (Read) part of the CRUD operation. This will be used to retrieve the required data from
the remote resource.
 POST: this map to the C (Create) part of the CRUD operation. This will create a new entry for the current data
that is being sent to the server.
 PUT: This map to the U (Update) part of the CRUD operation. This protocol will update the current
representation of the data on the remote server.
 DELETE: This map to the D (Delete) part of the CRUD operation. This will delete the specified data from the
remote server.

Let’s take a simple example of some remote resource that contains a Database for list of movies and the
list of movies can be retrieved using a URL like: www.moviewebsite.com/api/movies

To retrieve any specific movie, let’s think there is some ID for each movie that we can use to retrieve the
movie; the possible URL might look like: www.moviewebsite.com/api/movies/123

Since these are GET requests, data can only be retrieved from the server. To perform other operations, if
we use similar URI structure with PUT, POST or DELETE operation, we should be able to create, update and delete
the resource from server.

Now if we compare REST API with SOAP Service, we can understand the benefits of REST like:
 Firstly, only the data will be traveling to-and-fro from the server because the capabilities of the service are
mapped to the URIs and Protocols.
 Secondly, there is no need to have a Proxy at the client end because its only data that is coming and the
application can directly receive and process the data.

WCF REST Services: Windows Communication Foundation (WCF) came into existence much later than the Web
Service. It provided a much secure and mature way of creating the services to achieve whatever we were not able
to achieve using traditional Web Services, i.e., other protocols support and even duplex communication. With WCF,
we can define our service once and then configure it in such a way that it can be used via HTTP, TCP, IPC, and even
Message Queues. We can even configure WCF Services to create REST Services too i.e., WCF REST Services.

The problem with using WCF Restful Services is that we need to do a lot of configurations in a WCF Service
to make it a Restful Service. WCF is suited for scenarios where we want to create a service that should support special
action such as one way messaging, message queues, duplex communication or the services that need to conform to
WS* specifications, whereas using WCF for creating restful services, that will provide fully resource-oriented services
over HTTP is a little complex. Still WCF is the only option for creating the Restful services if there is a limitation of
using .NET 3.5 Framework.

264
Evolution of Web API: To overcome all the above problems, Microsoft came up with ASP.NET Web API to facilitate
the creation of Restful Services that can provide fully resource-oriented services for broad range of clients including
desktops, browsers, mobiles, and tablets. ASP.NET Web API is a framework for building REST Services easily and in a
rather simple way.

ASP.NET Web API Characteristics:


 ASP.NET Web API is an ideal platform for building Restful Services.
 ASP.NET Web API is built on top of ASP.NET and supports ASP.NET request/response pipeline.
 ASP.NET Web API maps HTTP Verbs to method names.
 ASP.NET Web API supports different formats of response data and built-in support for JSON, XML, and BSON
format.
 ASP.NET Web API can be hosted in IIS, Self-Hosted or other Web Servers that supports .NET 4.0+.
 ASP.NET Web API framework includes new “HTTPClient” class to communicate with Web API server. Http Client
can be used in ASP.MVC App’s, Windows Form App’s, Console App’s, or other Apps.

Creating a Web API Service: Create a new “ASP.Net Web Application” project naming it as “WebApiService”, choose
“Empty Project Template”, select “Web Api” CheckBox (which adds all the folders and references for working with
Web Api) and click on the “Create” Button.

Note: the folder structure here also will be same as the folder structure of an MVC Project like Controllers, Models
etc., but her we will not have View’s folder.

Adding a Web Api Controller: to add a Web Api Controller, right click on the Controllers folder and select the option
Add => Controller and in the window opened, select “Web Api” in the LHS and then select “Web Api 2 Controller -
Empty” in RHS and name it as “TestController” which adds a Controller under the project, but this controller class
inherits from “ApiController” which is present under the namespace “System.Web.Http”. Write the below code in
“TestController” class:

public class TestController : ApiController


{
//Declaring a List of strings and storing a set of colors in it
static List<String> Colors = new List<string>()
{
"Red", "Blue", "Green", "Purple", "Magenta"
};

//Responds for Get (Select) request


public IEnumerable<String> Get()
{
return Colors;
}
//Responds for Get (Select with condition) request with a parameter - id
public string Get(int id)
{
return Colors[id];
}

265
//Responds for Post (Insert) request
public void Post([FromBody] string color)
{
Colors.Add(color);
}
//Responds for Put (Update) request
public void Put(int id, [FromBody] string color)
{
Colors[id] = color;
}
//Responds for Delete (Delete) request
public void Delete(int id)
{
Colors.RemoveAt(id);
}
}
Run the project which will display the Uri http://localhost:port in the browser address bar, add “/Api/Test”
to it in the last, which will display all the Colors on the browser in XML Format, because by default every browser
will be sending a “Get” request to the Server, so Get method got executed displaying all the colors. If we add “/3”
after “Test” then also “Get” method only gets executed but the “Get” method which takes “Id” as a parameter will
execute and displays a single color in XML format.
http://localhost:port/Api/Test //For getting all the colors
http://localhost:port/Api/Test/3 //For getting single color with index 3

If we want to test Post, Put and Delete methods we need to use any Web Debugging Tool like Fiddler,
Postman, Swagger etc., so let’s use Postman and to do that first install Postman on your machines.

Working with Postman: To test all the operations of our Web API Service using Fiddler, first host the application on
IIS Web Server, then launch Postman App., click on the “+” button in RHS which opens a composer window as below:

Now under the TextBox “Enter URL or paste text”, enter this URL: http://localhost/WebApiService/Api/Test
and click on Send button which will display the output in the below as following:

266
Testing Post Method: post means insert or add, and to test this go to composer window, and there before the
address bar we find a drop-down and in that change GET to POST, and below the address bar select “body” tab and
in the below we get a drop-down with value “none” change to “raw” which shows another drop-down with a value
“Text” change it to “JSON” and enter the value you wanted to add in the TextArea below, for example lets enter the
value as “Black” (Data should be in double quotes) and click on Send button which will insert or add the value into
the resource i.e., List in our case and to confirm that change POST to GET in drop-down and click on Send button
again which displays the new value in List.

Note: If we want to test Put (Update) and Delete we need to make setting in Web.config file because when the
application is hosted on IIS, it will not support Put and Delete actions and to resolve this problem do the following:

Step 1: go to Web.config file and there we find a node <system.webServer> and under that we find <handlers> node,
write the following statement inside of that <handlers> node:
<remove name="WebDAV" />

Step 2: now under <system.webServer> if you find <modules> node, add the following under it:
<remove name="WebDAVModule"/>
Or else add the following:
<modules> <remove name="WebDAVModule"/> </modules>

Testing Put Method: to test Put or Update, go to composer window and in the drop-down change GET to PUT. To
update a value we need to the key to refer to the item we want to update and in our case Index is the key, so let’s
update the 3rd item in the List which means index 2 and to do that add “/2” to the URL in the address bar which
should now look as following: http://localhost/WebApiService/Api/Test/2 and below the address bar select “body”
tab and we get a drop-down below with value “none” change to “raw” which shows another drop-down with a
value “Text” change it to “JSON” and enter the value you wanted to add in the TextArea below, for example lets
enter the value as “White” (Data should be in double quotes) and click on Send button which will update the value
in the resource i.e., List in our case and to confirm that change Put to GET in drop-down and click on Send button
again which displays the new value in List.

Testing Delete Method: to test Delete go to composer windows, and in the drop-down change GET to Delete. To
delete a value also we need to the key to refer to the item we want to delete and in our case Index is the key, so
let’s delete the 4th item in the List which means index 3 and to do that add “/3” to the URL in the address bar which
should now look as following: http://localhost/WebApiService/Api/Test/3 and click on the Send button which will
delete the record and to check the output change Delete to GET in drop-down and also delete “/3” in the URL and
click on the Send button again which displays the new value in List.

Developing a Web API Service to perform CRUD Operations with Database: under the Models folder add “Ado.Net
Entity Data Model”, naming it as “TestEF” and choose “EF Designer from database” => Configure it with our “MVCDB”
database and choose the “Customer” Table. Add a new “Web API 2 Controller - Empty” under the project naming it
as “CustomerController” and write the below code in the class:

using System.Data.Entity;
using WebApiService.Models;
public class CustomerController : ApiController
{

267
MVCDBEntities dc = new MVCDBEntities();
public List<Customer> Get()
{
return dc.Customers.ToList();
}
public Customer Get(int id)
{
return dc.Customers.Find(id);
}
public HttpResponseMessage Post(Customer c)
{
try
{
c.Status = true;
dc.Customers.Add(c);
dc.SaveChanges();
return new HttpResponseMessage(HttpStatusCode.Created);
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage Put(Customer c)
{
try
{
Customer obj = dc.Customers.Find(c.Custid);
if (obj == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
obj.Name = c.Name;
obj.Balance = c.Balance;
obj.City = c.City;
dc.Entry(obj).State = EntityState.Modified;
dc.SaveChanges();
return new HttpResponseMessage(HttpStatusCode.OK);
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage Delete(int id)
{

268
try
{
Customer obj = dc.Customers.Find(id);
if (obj == null) {
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
obj.Status = false;
dc.Entry(obj).State = EntityState.Modified;
dc.SaveChanges();
return new HttpResponseMessage(HttpStatusCode.OK);
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
}

Consuming the WebApi Service using JQuery-Ajax from the same project in which WebApi was developed: add an
“MVC Controller” in the current project naming it as “HomeController” and this action will raise errors in the
application because we have opened an “Empty Project” and then selected “Web Api” Checkbox but now we are
adding an “MVC Controller”. To fix the errors we need to install 2 “Nuget Packages” => “Microsoft.AspNet.MVC” and
“Microsoft.AspNet.Web.Optimization”.

After installing the above 2 packages, open “Global.asax.cs” file and call “RegisterRoutes” method of
“RouteConfig” class, and to do that write the below statement under “Application_Start” method in the last line:
RouteConfig.RegisterRoutes(RouteTable.Routes);

Add a view to the existing “Index” Action method of “HomeController” without choosing any layout. Install
“JQuery” into the project using “Nuget Package Manager”, and write the below code in “<head>” section:

<script src="~/Scripts/jquery-3.7.1.min.js"></script>
<script>
function GetCustomers() {
$.ajax({
url: 'http://localhost/WebApiService/api/Customer',
type: 'get',
datatype: 'json',
success: BuildTable,
error: DisplayError
});
}
function BuildTable(Customers) {
$('#tblCustomers tbody').empty();
$.each(Customers, function (Index, Customer) {
var Status = (Customer.Status) ? 'Active' : 'In-Active';

269
$('#tblCustomers').append('<tr><td align=center>' + Customer.Custid + '</td><td>' + Customer.Name +
'</td><td align=right>' + Customer.Balance + '</td><td>' + Customer.City + '</td><td align=center>' + Status +
'</td></tr>');
});
}
function DisplayError() {
window.alert("Error on the server, could not load the data.");
}
function GetCustomer() {
$.ajax({
url: 'http://localhost/WebApiService/api/Customer',
type: 'get',
datatype: 'json',
data: {
'id': $('#Custid').val()
},
success: function (Customer) {
if (Customer == null) {
window.alert("No customer exists with the given id.");
$('#frmCustomer').trigger("reset");
$('#Custid').focus();
}
else {
$('#Name').val(Customer.Name);
$('#Balance').val(Customer.Balance);
$('#City').val(Customer.City);
}
},
error: DisplayError
});
}
function AddCustomer() {
$.ajax({
url: 'http://localhost/WebApiService/api/Customer',
type: 'post',
datatype: 'json',
data: $('#frmCustomer').serialize(),
success: ClearAndLoad,
error: DisplayError
});
}
function UpdateCustomer() {
$.ajax({
url: 'http://localhost/WebApiService/api/Customer',
type: 'put',
datatype: 'json',

270
data: $('#frmCustomer').serialize(),
success: ClearAndLoad,
error: DisplayError
});
}
function DeleteCustomer() {
var Status = confirm('Are you sure of deleting the current record?');
if (Status) {
$.ajax({
url: 'http://localhost/WebApiService/api/Customer/' + $('#Custid').val(),
type: 'delete',
datatype: 'json',
success: ClearAndLoad,
error: DisplayError
});
}
}
function ClearAndLoad() {
$('#frmCustomer').trigger("reset");
GetCustomers();
$('#Custid').focus();
}
</script>

Now write the below code under “<body>” tag by deleting the existing “<div>” tag over there:
<body onload="GetCustomers()">
<table width="100%">
<tr>
<td valign="top">
<table border="1" align="center" id="tblCustomers">
<caption>Customer Details</caption>
<thead>
<tr>
<th>Custid</th><th>Name</th><th>Balance</th><th>City</th><th>Status</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</td>
<td valign="top">
<form id="frmCustomer">
<table align="center">
<tr>
<td>Custid:</td>
<td>

271
<input id="Custid" name="Custid" />
<input type="button" id="btnSearch" name="btnSearch" value="..." onclick="GetCustomer()" />
</td>
</tr>
<tr>
<td>Name:</td><td><input id="Name" name="Name" /></td>
</tr>
<tr>
<td>Balance:</td><td><input id="Balance" name="Balance" /></td>
</tr>
<tr>
<td>City:</td><td><input id="City" name="City" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" id="btnInsert" name="btnInsert" value="Insert" onclick="AddCustomer()" />
<input type="button" id="btnUpdate" name="btnUpdate" value="Update"
onclick="UpdateCustomer()" />
<input type="button" id="btnDelete" name="btnDelete" value="Delete" onclick="DeleteCustomer()" />
<input type="reset" id="btnReset" name="btnReset" value="Clear" />
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>

Consuming the Web API Service from an MVC Application using JQuery from a different project: to test consuming
our “Web Api service” in a new MVC Project, create a new “ASP.NET Web Application” Project naming it as
“WebApiConsumer1”, choose Empty Project Template and select the “MVC” Check Box. Install “JQuery” package
using Nuget Package Manager. Add a controller in the project naming it as “HomeController” and add a view to the
existing Index Action Method without choosing a layout, copy the complete code which we implemented in
“Index.cshtml” of previous project i.e., “WebApiService” and paste it into the current “Index.cshtml” by deleting all
existing content.

Run the project but we will not get the output because of “CORS (Cross Origin Resource Sharing)” i.e., by
default for security reasons, browsers restrict Cross-Origin HTTP Requests initiated thru Scripts (JQuery, React,
Angular, etc), and to resolve this problem we need to enable “CORS” policy in our “WebApiService” project so that
it lets a Web Application running at one origin (domain) to access resources from an application at a different origin
(domain).

To enable CORS in our “WebApiService” project we need to first install a “Nuget Package” i.e.,
“Microsoft.AspNet.WebApi.Cors”, so open the Nuget Package Manager and install the package. After installing the
packing, we can enable CORS either for the whole Project or to a particular “Web Api” Controller class also.

272
To enable CORS for a particular Web API Controller class, do the following:
Step: 1 To enable CORS for a particular Api Controller class go to CustomerController.cs file and add [EnableCors]
attribute to CustomerController class by importing the namespace “System.Web.Http.Cors” as following:
[EnableCors("*", "*", "*") ]
public class CustomerController : ApiController

EnableCors attribute expects 3 parameters and those are:


 Origins, which should be a comma separated list of origins that are allowed to access the resource or use “*” to
allow all.
 Headers, which should be a comma separated list of headers that are supported by the resource or use “*” to
allow all or use “null” or empty string to allow none.
 Methods, which should be a comma separated list of methods that are supported by the resource or use “*” to
allow all or use “null” or empty string to allow none.

Step 2: Now go to “WebApiConfig.cs” file which is present under “App_Start” folder and write the following code in
the end of Register method which is present inside the class “WebApiConfig”:
config.EnableCors();

To enable CORS for the whole project do the following: to enable CORS for the whole project, without adding
“[EnableCors]” attribute to each Web Api Controller class, directly go to “WebApiConfig.cs” file which is present
under “App_Start” folder and write the below code in the end of Register method which is present inside of the class
“WebApiConfig” by importing the namespace “System.Web.Http.Cors”:

EnableCorsAttribute obj = new EnableCorsAttribute("*", "*", "*");


config.EnableCors(obj);

Note: after enabling Cors either Controller Level or Project Level we can start accessing the Web API from other
projects also.

Developing a new Web Api Service class with Image loading:


Step 1: Create a Table under our MVCDB Database with the name Students as following:
Create Table Students (Id Int Primary Key, Name Varchar(50), Photo VarBinary(max), Status Bit Not Null Default 1);

Step 2: Open the “TestEF.edmx” file under our “WebApiService” project, right click on it and choose the option
“Update Model from Database” and choose the “Students” table which we have created right now, from the “Update
Wizard” and click on Ok Button, which will add the “Students” table as an entity, with the name “Student” beside
the “Customer” entity which we have added earlier.

Step 3: Now add a “Web API 2 Controller” under the Controllers folder naming it as “StudentController” and write
the below code in the class:

using System.Data.Entity;
using WebApiService.Models;
public class StudentController : ApiController
{
MVCDBEntities dc = new MVCDBEntities();

273
public List<Student> Get()
{
return dc.Students.Where(S => S.Status == true).ToList();
}
public Student Get(int Id)
{
return dc.Students.Find(Id);
}
public HttpResponseMessage Post(Student student)
{
try
{
student.Status = true;
dc.Students.Add(student);
dc.SaveChanges();
return new HttpResponseMessage(HttpStatusCode.Created);
}
catch(Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage Put(Student student)
{
try
{
Student obj = dc.Students.Find(student.Id);
if (obj == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
else
{
obj.Name = student.Name;
obj.Photo = student.Photo;
obj.Status = true;
dc.Entry(obj).State = EntityState.Modified;
dc.SaveChanges();
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}

274
public HttpResponseMessage Delete(int Id)
{
try
{
Student obj = dc.Students.Find(Id);
if (obj == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
else
{
obj.Status = false;
dc.Entry(obj).State = EntityState.Modified;
dc.SaveChanges();
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
}

Note: build the project and compile it, so that we can consume it from other projects.

Consuming the Web Api Service from an MVC Application using C# Code: to test consuming the above “Web Api
service” from an MVC Project, create a new “ASP.NET Web Application” project naming it as “WebApiConsumer2”,
choose “Empty Project Template”, select “MVC” Check Box and click on “Create” button.

To call Web API from an MVC Application using C# code we need to first install a Nuget Package
“Microsoft.AspNet.WebApi.Client” in our project which provides all the types for invoking a Web API Service from
an “MVC Controller-Action Methods”.

Right now, our MVC Application is not getting its data from a Database, so we don’t have LINQ or Entity
Framework providing the Model Classes. Our MVC Application is getting its data from a Web API Service, so in this
case we are responsible to define the Model Classes explicitly in our project and to do that add a new class under
the Models folder naming it as “Student” and write the below code in it:

public class Student


{
public int Id { get; set; }
public string Name { get; set; }
public byte[] Photo { get; set; }
}

275
The current MVC Application is being designed to consume a Web API Service and to refer the service we
need the URL of the Service. So, go to “Web.config” file and add the following element under “<appSettings>” tag:
<add key="WebApiUrl" value="http://localhost/WebApiService/Api/" />

Add a controller in the Controllers folder naming it as “StudentController” and write the below code in it
deleting the existing Index action method:

using System.IO;
using System.Net.Http;
using System.Configuration;
using System.Threading.Tasks;
using WebApiConsumer2.Models;
public class StudentController : Controller
{
HttpClient client;
string serviceUrl;
public StudentController()
{
client = new HttpClient();
serviceUrl = ConfigurationManager.AppSettings.Get("WebApiUrl");
client.BaseAddress = new Uri(serviceUrl);
}
public ViewResult DisplayStudents()
{
Task<HttpResponseMessage> getTask = client.GetAsync("Student");
getTask.Wait();
HttpResponseMessage message = getTask.Result;
List<Student> students = new List<Student>();
if (message.IsSuccessStatusCode) {
students = message.Content.ReadAsAsync<List<Student>>().Result;
}
return View(students);
}
public ViewResult DisplayStudent(int Id)
{
Task<HttpResponseMessage> getTask = client.GetAsync("Student/" + Id);
getTask.Wait();
HttpResponseMessage message = getTask.Result;
Student student = new Student();
if (message.IsSuccessStatusCode) {
student = message.Content.ReadAsAsync<Student>().Result;
}
return View(student);
}
public ViewResult AddStudent()
{

276
return View(new Student());
}
[HttpPost]
public ActionResult AddStudent(Student student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null)
{
BinaryReader br = new BinaryReader(selectedFile.InputStream);
student.Photo = br.ReadBytes(selectedFile.ContentLength);
}
Task<HttpResponseMessage> postTask = client.PostAsJsonAsync("Student", student);
postTask.Wait();
HttpResponseMessage message = postTask.Result;
if (message.IsSuccessStatusCode) {
return RedirectToAction("DisplayStudents");
}
else {
return View();
}
}
public ViewResult EditStudent(int Id)
{
Task<HttpResponseMessage> getTask = client.GetAsync("Student/" + Id);
getTask.Wait();
HttpResponseMessage message = getTask.Result;
Student student = message.Content.ReadAsAsync<Student>().Result;
if (student.Photo != null) {
Session["Photo"] = student.Photo;
}
return View(student);
}
public ActionResult UpdateStudent(Student student, HttpPostedFileBase selectedFile)
{
if (selectedFile != null) {
BinaryReader br = new BinaryReader(selectedFile.InputStream);
student.Photo = br.ReadBytes(selectedFile.ContentLength);
}
else if (Session["Photo"] != null) {
student.Photo = (byte[])Session["Photo"];
}
Task<HttpResponseMessage> putTask = client.PutAsJsonAsync<Student>("Student", student);
putTask.Wait();
HttpResponseMessage message = putTask.Result;
if (message.IsSuccessStatusCode) {
return RedirectToAction("DisplayStudents");
}

277
else {
return View("EditStudent", student);
}
}
public ActionResult DeleteStudent(int Id)
{
Task<HttpResponseMessage> deleteTask = client.DeleteAsync("Student/" + Id);
deleteTask.Wait();
HttpResponseMessage message = deleteTask.Result;
if (message.IsSuccessStatusCode) {
return RedirectToAction("DisplayStudents");
}
else {
return View();
}
}
}

Add a view with the name DisplayStudents.cshtml, selecting layout Checkbox and write the below code in
it by deleting the whole content in the View:

@model IEnumerable<WebApiConsumer2.Models.Student>
<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>
<table border="1" align="center">
<caption>Student Details</caption>
<tr>
<th>@Html.DisplayNameFor(S => S.Id)</th>
<th>@Html.DisplayNameFor(S => S.Name)</th>
<th>@Html.DisplayNameFor(S => S.Photo)</th>
<th>Actions</th>
</tr>
@foreach (var Student in Model)
{
<tr>
<td>@Html.DisplayFor(S => Student.Id)</td>
<td>@Html.DisplayFor(S => Student.Name)</td>
@{
string imgSrc = "";
if (Student.Photo != null)
{
var base64 = Convert.ToBase64String(Student.Photo);
imgSrc = String.Format("data:image/jpeg;base64,{0}", base64);
}
}
<td><img src='@imgSrc' width="40" height="25" /></td>
<td>

278
@Html.ActionLink("View", "DisplayStudent", new { Id = Student.Id }) &nbsp;
@Html.ActionLink("Edit", "EditStudent", new { Id = Student.Id }) &nbsp;
@Html.ActionLink("Delete", "DeleteStudent", new { Id = Student.Id },
new { onclick = "return confirm('Are you sure of deleting the record?')" })
</td>
</tr>
}
<tr>
<td colspan="4" align="center">@Html.ActionLink("Add New Student", "AddStudent")</td>
</tr>
</table>

Generate a view for DisplayStudent action method and while adding the View, choose the Template as
Empty, Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below
code over there by deleting the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>


@{
string imgSrc = "";
if (Model.Photo != null) {
var base64 = Convert.ToBase64String(Model.Photo);
imgSrc = String.Format("data:image/jpeg;base64,{0}", base64);
}
}
<table border="1" align="center">
<caption>Student Details</caption>
<tr>
<td rowspan="2"><img src='@imgSrc' width="200" height="200" /></td>
<td>Sid: @Model.Id</td>
</tr>
<tr>
<td>Name: @Model.Name</td>
</tr>
<tr>
<td colspan="2" align="center">@Html.ActionLink("Back to Student Details", "DisplayStudents")</td>
</tr>
</table>

Generate a view for AddStudent action method and while adding the View, choose the Template as Empty,
Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Add New Student</h2>


@using (Html.BeginForm("AddStudent", "Student", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Id)<br />@Html.TextBoxFor(S => S.Id)</div>

279
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>@Html.LabelFor(S => S.Photo)<br /><input type="file" name="selectedFile" /></div>
<div>
<input type="submit" value="Save" name="btnSave" />
<input type="reset" value="Reset" name="btnReset" />
</div>
}
@Html.ActionLink("Back to Student Details", "DisplayStudents")

Generate a view for EditStudent action method and while adding the View, choose the Template as Empty,
Model Class as Student, choose “Use a layout page” CheckBox in the “Add View” window and write the below code
over there by deleting the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Edit Student</h2>


@{
string imgSrc = "";
if (Model.Photo != null)
{
var base64 = Convert.ToBase64String(Model.Photo);
imgSrc = String.Format("data:image/jpeg;base64,{0}", base64);
}
}
@using (Html.BeginForm("UpdateStudent","Student",FormMethod.Post,new { enctype = "multipart/form-data" }))
{
<div>@Html.LabelFor(S => S.Id)<br />@Html.TextBoxFor(S => S.Id, new { @readonly = "true" })</div>
<div>@Html.LabelFor(S => S.Name)<br />@Html.TextBoxFor(S => S.Name)</div>
<div>
@Html.LabelFor(S => S.Photo) <br />
<img src='@imgSrc' width="200" height="200" />
<input type="file" name="selectedFile" />
</div>
<div>
<input type="submit" value="Save" name="btnSave" />
</div>
}

Add a view for DeleteStudent Action method choosing a layout and write the below code in it by deleting
the existing “<h2>” element present in it:

<h2 style="text-align:center;background-color:yellowgreen;color:orangered">Delete Student Failed</h2>


<font color="red" size="4">
Delete student action resulted in an error.
</font>
@Html.ActionLink("Back to Student Details", "DisplayStudents")

280
ASP.NET Core
Nowadays, when it comes to the software development, everyone is talking about free, open-source, and
cross-platform development. As we all know that, Microsoft is well known for its Windows-Based products but now
we are in the new age of software development and for this, a new revolutionary product came into the market
from Microsoft, and it is ASP.NET Core.

History of ASP.NET: As we know, ASP.NET is a framework that has been used to develop data-driven Web
Applications for many years. Since then, ASP.NET Framework went through a steady evolutionary change, and finally,
the most decent evolution is ASP.NET Core.

ASP.NET Core is not a continuous part of the ASP.NET 4.x Framework, but instead it is a completely new
Framework. This Framework is actual a re-write of the current ASP.NET 4.x Framework, but with much smaller and
a lot more modular. Some people think that many things remain the same, but that is not completely true. The
ASP.NET Core is a big fundamental change to the ASP.NET Framework.

What is ASP.NET Core?


Ans: ASP.NET Core is a new version of ASP.NET Web Framework mainly targeted to run on .NET Core and above. It
is free, open-source, high-performance, lightweight, and cross-platform framework for building cloud-based
applications, such as Web Apps, IoT Apps and Mobile Apps.

It is designed to run on the cloud as well as on-premises. Same as .NET Core it was architected modular with
minimum overhead and then other more advanced features can be added as Nuget Packages as per application
requirements. This result in high performance, require less memory, less deployment size, and easy to maintain.

ASP.NET Core 9.0, 8.0, 7.0, 6.0, 5.0 and 3.x application can be targeted to develop and run-on top of the
.NET Core only whereas ASP.NET Core 1.x and 2.x application can be targeted to develop and run-on top of the .NET
Core (Cross-platform) as well as .NET Framework (Windows only).

Note: ASP.NET Core was initially launched as ASP.NET 5 but later it's renamed to ASP.NET Core.

Why ASP.NET Core?


Ans: Nowadays, the ASP.NET Core Framework became more and more popular among developers. There are several
reasons why modern developers are using it which are listed below:

Open Source: ASP.NET Core Framework is Open Source, and this is the main reason behind its popularity. The entire
source code of this ASP.NET Core is available at => https://github.com/aspnet and you are free to download the
source code and even you can also modify and compile your own version of it. “.NET Core” team is always there to
support your effort in the seamless development of the application.

Cross-Platform: The ASP.NET Core Framework is designed from scratch to keep in mind to be Cross-Platform for
both development and deployment also. So, we don’t need to build different applications for different platforms
using different Framework’s. The earlier version of ASP.NET Framework applications can run only on Windows
Platforms, whereas ASP.NET Core applications can be developed as well as run on different platforms such as
Windows, Mac, or Linux. We can host the earlier ASP.NET Framework applications on IIS only whereas we can host
the ASP.NET Core applications on IIS, Nginx, Docker, Apache, or even self-host deployment.

281
Editors: To develop ASP.NET Core applications we have multiple options like Visual Studio or Visual Studio Code as
well as if required, we can also use any third-party editors as per your choice.

CLI Support: Using CLI (Command Line Interface) commands you can develop and run .NET applications as well as
you can also publish the application using CLI command.

Fast: ASP.NET Core no longer depends on “System.Web.dll” for browser-server communication. ASP.NET Core allows
us to include packages that we need for the application and this will reduce the request pipelines and improves
performance and scalability.

IoC Container: One of the most important used design patterns in the real-time application is the “Dependency
Injection - Design Pattern”. It includes the built-in IoC (Inversion of Control) container for automatic dependency
injection which makes it maintainable and testable.

Unified MVC and Web API Framework: The ASP.NET Core provides a unified programming model for developing
both Web Apps and Web API. That means a single controller class can be used to handle both. A Controller we create
in ASP.NET Core (either Web App’s or Web API) application is going to inherit from the Controller base class and all
their action methods returns the “IActionResult” interface. The “IActionResult” interface provides several
implementations like “JsonResult”, “ViewResult” etc.

Integration with Modern UI Framework: It allows you to use and manage modern UI Frameworks such as Angular
JS, Angular, React JS, and Bootstrap, etc.

Handling Request and Response Pipeline: We can handle the request and response in the ASP.NET Core application
by using new Middleware Components. In earlier ASP.NET 4.x we generally use Handlers and Modules to handle the
Request and Response pipeline. The ASP.NET Core Framework provides lot of built-in Middleware Components and
we can use those Components to handle the request and response pipeline. If we want, we also can also create our
own Middleware components and use them.

Hosting: ASP.NET Core Web App’s can be hosted on multiple platforms with-in any Web Server such as IIS, Apache,
Nginx, Docker, etc. It is not dependent only on IIS as our standard .NET Framework Web App’s.

Side-by-Side Application Versioning: ASP.NET Core runs in .NET Core, which supports the simultaneous running of
multiple versions of applications.

Smaller Deployment Footprint: ASP.NET Core application runs on .NET Core, which is smaller than the full .NET
Framework. So, application which uses “.NET Core FX” libraries will be having a smaller deployment size, and this
reduces the deployment footprint.

Note: Many people are confused between “ASP.NET Core” and “.NET Core”. Please note that ASP.NET Core and .NET
Core are not the same. They are different, just like ASP.NET and .NET Framework are different. To understand, .NET
Core is a fast, lightweight, modular, and open-source framework for creating Web Applications, Desktop Applications
(CUI, GUI), Mobile Applications, Micro services, Cloud, Machine Learning, Game Development, and Internet of Things
(IOT) that can run on Windows, Linux, and Mac OS, whereas ASP.NET Core is a Web Application Framework under
.NET Core for building Web Applications only. So, .NET Core is a Software Platform on which ASP.NET Core
Applications run.

282
.NET Core vs. ASP.NET Core
.NET Core ASP.NET Core
.NET Core is Open-Source and Cross-Platform. ASP.NET Core is Open-Source and Cross-Platform.
.NET Core is a Runtime to execute applications which ASP.NET Core is a Web Framework to build Web, IoT
are built on it. and Mobile App’s on the top of .NET Core.
Install .NET Core Runtime to run applications and install There is no separate runtime and SDK available for
.NET Core SDK to build applications. ASP.NET Core. .NET Core runtime and SDK includes
ASP.NET Core libraries also.
.NET Core 9.0 - latest version. ASP.NET Core 9.0 - latest version.
Note: There is no separate versioning for ASP.NET Core. It is the same as the .NET Core versions.

What ASP.NET Core doesn’t have compared to ASP.NET?


Ans: If you are coming from ASP.NET 4.x, then you will not find the following things in ASP.NET Core:
 Global.asax File
 Web.config File
 Packages.config file
 HTTP Handlers and HTTP Modules

Creating ASP.NET Core Web Application


To create an ASP.NET Core Web Application, open Visual Studio 2022; click on the Create a new project
button which will open “Create a new project” window. This window displays different .NET Core application
templates, choose “ASP.NET Core Empty” template and click on the Next button which will open “Configure your
new project” window and here we need to give a name for our project for example “CoreTestProject1.Core5.0”, and
specify the location to save and click on the Next button, which will open “Additional Information” window and here
we need to select the “Target Framework” to build the application choose “.NET 5.0 (Out of support)” and also
uncheck all the checkboxes on this window and click on Create button. Once we click on the Create button, it will
create a new “ASP.NET Core Empty Project” and here we can understand how different components fit together to
develop an “ASP.NET Core application”. The project will be created with the following files and folder structure:

CoreTestProject1.Core5.0
 Connected Services
 Dependencies
 Properties
 launchSettings.json
 appsettings.json
 appsettings.Development.json
 Program.cs
 Startup.cs

Note: Until ASP.NET Core 5.0 we have a different coding style and from ASP.NET Core 6.0 we have a different coding
style. To understand the differences let us create a project in latest version of ASP.NET Core i.e., .NET 6.0.

Now same as the above project, create one more project with the name “CoreTestProject1.Core6.0” and
here select the “Target Framework” as “.NET 6.0 (Standard-term support)”, check “Do not use top-level statements”
and make sure all the other Checkbox’s are un-checked on this window, and click on Create button. This project will
be created with the following files and folder structure:

283
CoreTestProject1.Core6.0
 Connected Services
 Dependencies
 Properties
 launchSettings.json
 appsettings.json
 appsettings.Development.json
 Program.cs

Note: Up to ASP.NET Core 5.0 we find the file “Startup.cs” whereas from ASP.NET Core 6.0 we will not have
“Startup.cs” file anymore.

Run the ASP.NET Core Application’s which will open a browser and displays the output as “Hello World!”
and this output comes from the Configure method of the Startup class which is present inside the “Startup.cs” file
in case of ASP.NET Core 5.0, open the file and watch the code present in the Configure method and there you will
find the below statement in end of the method:

await context.Response.WriteAsync("Hello World!");

If we are working with ASP.NET Core 6.0 and above then this output comes from “Program.cs” file, open
the file and watch the code present over there, which displays a statement as below:

app.MapGet("/", () => "Hello World!");

Change the “Hello World!” string to something else and re-run the projects again which will display the
output accordingly. For example, let’s change the WriteAsync and MapGet methods code as following:

5.0 => await context.Response.WriteAsync(".NET Core Empty Web Application created using ASP.NET Core 5.0");

9.0 => app.MapGet("/", () => ".NET Core Empty Web Application created using ASP.NET Core 9.0");

ASP.NET Core Web App (Model-View-Controller) Template


The ASP.NET Core Web App (Model-View-Controller) template contains everything that is required to
create an ASP.NET Core MVC Web Application and this creates Models, Views, and Controller’s folders by default. It
also adds web-specific things such as Java Script, CSS files, Layout files, etc. which are necessary and required to
develop an MVC Application.

To create an MVC Application, open Visual Studio, click on create a new project button, in the window
opened choose “ASP.NET Core Web App (Model-View-Controller)” template and click on Next button, in the window
opened provide a name to the project as “CoreMVCProject5”, specify the location to save and click on Next button,
in the window opened choose Target Framework as “.NET 5.0 (Out of support)” and also make sure the Checkbox
“Configure for HTTPs is selected”, and click on the Create button which creates the project with the following files
and folder structure:

CoreMVCProject5
 Connected Services
 Dependencies

284
 Properties
 launchSettings.json
 wwwroot
 css
 js
 lib
 Controllers
 Models
 Views
 appsettings.json
 appsettings.Development.json
 Program.cs
 Startup.cs

Connected Services: This is the first element in our project structure and possibly the less used one. It is intended to
automate the steps necessary to connect a project to an external service (like Azure Storage).

Dependencies: This element of your project structure contains information of all packages and projects on which
our project depends. There are 4 main parts inside this node:

1. Analyzers: They help you make your code better, cleaner, and error-free. Each analyzer checks that your code
satisfies a list of rules incorporated in it. If any part of your code does not apply to one of the rules, you will see
either warning or an Error while you build your project. Please note that analyzers work only at compile time
and do not affect your resulting application.

2. Frameworks: This contains a list of frameworks your project depends on. This information is important if you
publish your web application to a Server (as opposed to a self-contained one). In this case, all the frameworks
listed here must be installed on the Server where you will run your app.

3. Packages: This is the main item which lists all the Nuget packages you added to your project. If any of those
packages depend on other packages, they will be installed automatically and listed as sub-nodes of the root-
level packages. You can remove each installed package here (right-click => Remove).

4. Projects: This is the list of other projects our project depends on in the current solution. You can reference other
projects by using the “Add Project Reference” command from the right-click menu.

Properties: This contains different properties of our project that we can modify by double-clicking on this node in
the Solution Explorer. Most of the properties here, affect the compile-time and debug-time behavior of your project.
The only item inside of this node is “launchSettings.json” file that contains the list of the launch profiles. Each profile
defines how to run your project, whether the browser should be opened or not, which port to use, which
environment variables should be set when we “Run” the project, etc. By default, we will be finding 2 profiles to run
the ASP.NET Core Web Application and those are: “IIS Express” profile and “CoreMVCProject5” profile. The
“launchSettings.json” file is as below in the project we have created:

{
"iisSettings": {
"windowsAuthentication": false,

285
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53245", //Port will different for you
"sslPort": 44375 //Port will different for you
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"CoreMVCProject5": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

Note: We can edit “launchSettings.json” file by using the project properties window also and to do that double click
on the Properties node in Solution Explorer and in the window opened, click “Debug Tab” in LHS and this provides
the option for editing “Launch Settings” and to do that click on “Open debug launch profiles UI”, link.

wwwroot: This folder is known as a “web root” folder and contains all the static files of our web application like CSS
files, Java Script files, Html files, and Image files. As you might figure out from its name, this will be the root folder
of our web application. So, if we add a new folder under “wwwroot” with the name “images” and under the folder
if we add an image file with the name “Autumn.jpg”, then we can access that image from browser by using the
address: “/images/Autumn.jpg”. To test this run the application hitting “F5” and then append “images/Autumn.jpg”
to the “URL” in the address which should now look as following in case of IIS Express or Kestrel Web Servers:
https://localhost:<port>/images/Autumn.jpg

Note: In traditional ASP.NET Application (i.e., Framework), static files can be served from the root folder of an
application or any other folder under it, which has been changed in ASP.NET Core. Now those files that are present
in the web root - “wwwroot” folder can be served over an http request. All other files are blocked and can’t be
served by default. Generally, there will be separate folders for different types of static files such as Java Script, CSS,
Images, and Library Scripts etc. in the “wwwroot” folder.

We can rename “wwwroot” folder to any other name as per our choice and set it as a web root while
preparing hosting environment in “Program.cs”. For example, if we change the “wwwroot” folder name as “myroot”
we need to specify that in Program class under “CreateHostBuilder” method.

By default, code in the method will be as following:


public static IHostBuilder CreateHostBuilder(string[] args) =>

286
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Change the above code as below to register our myroot folder as web root folder:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>().UseWebRoot("myroot");
});

Controllers: this folder contains all the Controller classes we define in our project.

Models: this folder contains Model classes i.e., Classes representing the Entities and Properties representing the
Attributes of Entities as well as all the Methods to manipulate the data.

Views: this folder contains all the View files that are required for this application and the extension of these files will
be “.cshtml” and we call these files as “Razor Pages”.

Till now we have looked over all the main folder's that are present with-in the “ASP.NET Core MVC
Application” project, now let's take a closer look at the files stored in the project’s root folder which are also most
important part of the project.

appsettings.json: this file is used to store information such as connection strings or application specific settings and
they are stored in JSON format, as the file extension suggests. If you are familiar with ASP.NET you may notice that
the function of this file is like “Web.config” file, and right now we find the below code in it:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

The settings in the file have a hierarchical structure and can be accessed with the “Configuration” object
defined in the Startup class or in any other place of your program where you injected “IConfiguration” service. For
example, if we want to read the value of key “Default” or “Microsoft” then the code will be as following:
var Data1 = Configuration.GetValue<string>("Logging:LogLevel:Default");
var Data2 = Configuration.GetValue<string>("Logging:LogLevel:Microsoft");

By default, in addition to “appsettings.json” file, the ASP.NET Core Project also includes an
“appsettings.Development.json” file and all the settings defined in this file are loaded only in the Development

287
Environment and are not available in Production. Same as this we can also define “appsettings.Production.json” for
settings in Production Environment and “appsettings.Test.json” for settings in QA & UAT Environment.

Program.cs: This file contains a class in it with the name Program and a static “Main” method which is the entry
point of our “Application”. Just like our Console App’s and Windows App’s, ASP.NET Core App’s also starts from
Program class only. The purpose of this method is to define the “host” and then pass the control to the “Startup”
class.

Code in Program class will be as following by default:


public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}

A host is an object that encapsulates an app’s resources, such as: Logging, Dependency Injection (DI),
Configuration, IHostedService Implementations, etc. As shown in the above code, CreateHostBuilder() method
returns an object that implements the IHostBuilder interface. Host is a static class that can be used for creating an
instance of IHostBuilder with pre-configured defaults by calling CreateDefaultBuilder() method which will create a
new instance of HostBuilder with pre-configured defaults.

Startup.cs: This file contains a class in it with the name “Startup” and it will serve three main purposes:
 It performs all initialization tasks like setting, application - wide constants.
 It registers all the services that are injected in this project thru the DI (Dependency Injection) container.
 It defines the middleware pipeline of your web-application.

Note: This class initially contains lot of code (as per the project i.e., Empty or Web App or MVC or Web API, which
has just been created) from the very beginning and will become even bigger when you start adding new features to
your application.

By default, Startup class in the ASP.NET MVC Core application includes three main parts:
1. The Constructor, where you can initialize variables, set some configuration settings, or performs application-
wide initializations. By default, the ASP.NET Core project template contains 1 line of code in the constructor
which initializes the in-class property Configurations with the configuration object passed by the Dependency
Injection container, so we can use it in other methods and right now the code in the constructor is as below:
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

288
2. The ConfigureServices method, where we register all necessary services like “Authentication/Authorization
Service”, “MVC or Razor Page or Web Api Services”, “Service for working with Database”, as well as we register
different “Application Services to DI (Dependency Injection) Container” here and by default in an ASP.NET Core
MVC Application the method contains below code in it:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}

Note: the order of the services you register in “ConfigureServices” method is not important and this method is
executed only once upon application start and this method contains calls such as “services.AddDbContext”,
“services.AddRazorPages”, “services.AddControllersWithViews”, and “services.AddControllers”, etc. All these
methods are extension methods.

3. The Configure method is the place where we can set up the Middleware Pipeline for our ASP.NET Core Web
Application project. Unlike the services registered in the ConfigureServices (remember, their order is not
important), the order of all Middleware’s defined in Configure method has crucial significance.

What is a Middleware?
Ans: ASP.NET Core introduced a new concept called Middleware. A middleware is nothing but a class which is
executed on every request in ASP.NET Core Application. There will be multiple Middleware’s in an ASP.NET Core
Application. It can be either Framework provided Middleware added via Nuget or our own custom Middleware. We
can set the order of Middleware execution in the request pipeline. Each Middleware adds or modifies Http Request
and passes control to the next Middleware component.

Note: At the beginning of the pipeline, we need to place the “Middleware’s” that are necessary for auxiliary tasks
(like logging or authentication), and that don’t consume a lot of memory and processing time.

By default, in an ASP.NET Core MVC Application the method contains below code in it:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see
https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

289
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}

Exception Handling Middleware: the first line in the method defines different middleware’s for Development and
Production modes i.e., if we are in the Development Mode, we define middleware’s that will catch all exceptions in
the pipeline and show a special page with extra information about the error (exception message, stack trace, etc.),
whereas in the Production and Staging Mode, we catch all exceptions and then re-direct the request to the specified
path i.e., “Home/Error” in our case.

Processing static files (UseStaticFiles) Middleware: the next middleware in the pipeline is “UseStaticFiles()” which
takes care of all static files, i.e., if the application gets a request for “.js”, “.css”, or an image files, this middleware
looks for a file with the requested name inside of the “wwwroot” folder and returns it back if found. If not found it
will send back a response with a 404-status code (not found).

Routing (UseRouting and UseEndpoints): the next pair of middleware’s are, the most important ones in the pipeline
since they define the routing for all other endpoints in your web application. In simple words, they match a particular
request to a particular endpoint, a piece of executable code that handles the request.

How exactly does it work?


Ans: In the Configure method first we call “app.UseRouting()” middleware to add the “Endpoint Routing”
middleware to our pipeline and after that, we need to call “app.UseEndpoints()” middleware to add “Endpoint”
middleware to the pipeline and define the endpoints. Each endpoint is an object that contains (as mentioned above)
a delegate (so, a piece of code) that handles the request. We can use such extension methods as MapGet, MapPost,
and others to add an endpoint that matches a particular request path or a path template. For example, the following
pattern “/something/{path*}”, will be matched for all requests started with “/something/”. To test this, change the
pattern in the code as following:

pattern: "NIT/{controller=Home}/{action=Index}/{id?}");

Now all the requests should contain the word "NIT" before the controller’s name, as following:
http://localhost:port/NIT/Controller_Name/Action_Name => http://localhost:port/NIT/Home/Index

When the web application gets a new request, it’s not processed by any middleware defined before
“UseRouting” middleware and then the Endpoint Routing Middleware matches it to some endpoint. Then Endpoint
Middleware calls the endpoint’s delegate to handle the request. All other middleware’s that are added after
app.UseRouting() and before app.UseEndpoints() can see which endpoint was selected by EndpointRouting
Middleware and they can change something (e.g., apply an authorization policy) before EndpointMiddleware
dispatches to the selected endpoint.

Authorization (UseAuthorization): this middleware is added for authorizing a user if the current request is
anonymous, but the selected endpoint requires authorization.

290
Both “ConfigureServices” and “Configure” methods are called implicitly while the application starts. You
just only need to define the services and middleware’s here correspondingly.

Note: If the same project is created using .NET 6.0 and above Frameworks then we will not find the class “Startup”
and the code of this class will be present directly under “Program” class only. By default, the code under
“Program.cs” file will be with-out any class over there, because .NET 6.0 uses C# 10.0 version and in this version, we
are provided with a feature called Top-Level Statement’s i.e., if the project has a single Main method and all the
code, if required to be defined under the Main method only then with-out explicitly defining a Class and Main
method it will directly write the code in the file as below:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.


if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Note: if you still want to see the class; while creating the project, in the window where we select the Framework
version, select the Checkbox “Do not use top-level statements” so that you will find the code with a class and Main
method also. To test that, create a new MVC Application project naming it as “CoreMVCProject6”, and in the window
where we choose Target Framework select “.NET 6.0 (Long-term support)” and select the Checkbox’s “Configure for
HTTPs” and “Do not use top-level statement’s”, click on Create button which creates the project with-out a Startup
class and code under the Program class will be as following:

namespace CoreMVCProject6
{
public class Program
{
public static void Main(string[] args)
{

291
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.


if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");

// The default HSTS value is 30 days. You may want to change this for production scenarios, see
https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
}
}
}

Note: Because we don’t have Startup class here and all code need to be defined in the Main method of Program
class only, follow the below guidelines to write the code:
 All the code we need to write under “ConfigureServices” method of “Startup” class should be implemented
before this statement => “var app = builder.Build();”.
 All the code we need to write under “Configure” method of “Startup” class should be implemented after this
statement => “var app = builder.Build();”.

Why do we have a Main method in ASP.NET Core?


Ans: The most important point that you need to keep in mind is, an ASP.NET Core Web Application initially starts as
a “Console Application” and the Main method is an entry point to that application. When we execute the ASP.NET
Core Web Application first it looks for Main method and this is the method from where the execution starts. Main
method will then configure ASP.NET Core and starts it, and at this point of time the application becomes a Web
Application. If we look at the body of Main method, there we will find that, it makes a call to “CreateHostBuilder()”
method by passing the command line arguments “args” as a parameter value and the code in the “Main” method
will be as following:

public static void Main(string[] args)


{
CreateHostBuilder(args).Build().Run();
}

292
Within the Main method, on this “IHostBuilder” object, the Build method is called which builds a Web Host.
Then it hosts our ASP.NET Core Web Application within that Web Host (Web Server). Finally, on the Web Host (Web
Server), it calls the Run method, which will run the Web Application and it starts listening to the incoming HTTP
Requests.

CreateHostBuilder method returns an object that implements IHostBuilder interface. Host is a static class
that can be used for creating an instance of IHostBuilder with pre-configured defaults by calling its
CreateDefaultBuilder method which will create a new instance of HostBuilder with pre-configured defaults.
Internally, it will also configure Kestrel (Internal Web Server for ASP.NET Core), IIS Integration, and other
configurations. Below is the code we find in CreateHostBuilder method:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

As part of setting the Web Host, the CreateDefaultBuilder method will do several things, like:
 Setting up the Web Server.
 Loading the application configuration from various configuration sources.
 Configuring logging.

Configuring and setting up the Web Server by CreateDefaultBuilder method:


ASP.NET Core Web Application can be hosted in “IIS Express” or “Local IIS” or “Kestrel” Web Servers and it
supports 2 different hosting models, those are:
 In Process Hosting
 Out of Process Hosting

Note: when we create a new ASP.NET Core MVC Application by default it is created with In-Process hosting model
for hosting the application in Local IIS or IIS Express or Kestrel. To verify that, open Project Properties Window and
in that on LHS select the option “Debug” and on the right, click on “Open debug launch profiles UI” link which opens
a window and, in that select, “IIS Express” on LHS and on the right we find “Hosting Model” option with the default
value “In Process”.

In case of In-Process hosting, “CreateDefaultBuilder” method when sees the value as In-Process, will
internally host the application inside “Web Server’s Worker Process” i.e., “iisexpress.exe” for “IIS Express”,
“w3wp.exe” for “IIS” and “<ProjectName>.exe” for “Kestrel”. By default, Visual Studio uses IIS Express to run Web
Applications up to ASP.NET Core 5.0 and Kestrel to run Web Applications from ASP.NET Core 6.0.

What is IIS Express?


Ans: IIS Express is a lightweight, self-contained version of IIS which is designed for Web Application Development.
The most important point that you need to remember is we use IIS Express only in development, not on production
or staging and in production and staging we generally use IIS.

What is IIS Web Server, and how to run ASP.NET Core Web Application in IIS Web Server?
Ans: Internet Information Services (IIS) is a flexible, secure, and manageable Web Server for hosting anything on the
Web. To host our ASP.NET Core Web Application on IIS Web Server first open Visual Studio in Administrator Mode,

293
go to Project Properties => select Debug Tab in the LHS and on the right, click on “Open debug launch profiles UI”
link which opens a window and, in that click on “Create a new profile” option in the LHS-Top and select the option
IIS which adds a new Profile with the name as “Profile1” rename it as “IIS” and now on the right fill the below details:

 Under “Environment Variables” Textbox enter the value as “ASPNETCORE_ENVIRONMENT=Development”.


 Check the “CheckBox” Launch Browser.
 Under “App URL” Textbox enter the value as: http://localhost/CoreMVCProject5 for CoreMVCProject5.

Leave rest of the options as is and close the window. Now in the “Standard Toolbar” under “Debug Target
DropDownList” by default it will be showing “IIS Express” upto ASP.NET Core 5.0 and “Project Name (Kestrel)” from
ASP.NET Core 6.0, change it to “IIS”, run the project and watch the URL in address bar. Now if we open the
“launchSettings.json” file we will find some changes made to the file as following:

Under “iisSettings” it will add a new “Name-Value” item as following:


"iis": {
"applicationUrl": "http://localhost/CoreMVCProject5",
"sslPort": 0
}

In the bottom of the file, it will create a new Profile i.e., “IIS” Profile as following:
"IIS": {
"commandName": "IIS",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}

What is Kestrel Web Server and how to run ASP.NET Core Web Application in Kestrel Web Server?
Ans: As we already know that ASP.NET Core is a Cross-Platform Framework, which means it supports us to develop
and run our applications on different Operating System’s such as Windows, Linux, or Mac. The Kestrel is the Cross-
Platform Web Server for ASP.NET Core App’s, which means this Web Server supports all the platforms and versions
that ASP.NET Core supports. By default, it is included as an Internal Web Server in the .NET Core Application.

The Kestrel Web Server generally used as an edge server i.e., the internet facing Web Server which directly
processes incoming HTTP Request from the clients. In case of Kestrel Web Server, the Process Name that is used to
host and run the ASP.NET Core Application is our Project Name only and to check this open “launchSettings.json”
file and we will find the below code:

"CoreMVCProject5": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": https://localhost:5001;http://localhost:5000,

294
"dotnetRunMessages": "true"
}

Under profile settings we find 3 profiles “IIS Express”, “CoreMVCProject5” (our Project Name) and “IIS”
(which we have created explicitly). “IIS Express” profile is used to run the application under IIS Express and we find
the “iisSettings” on the top of “launchSettings.json” file and the Application URL is: http://localhost:PortNo (Port
No. will vary from project to project and machine to machine) and below this we also find SSL Port with some value,
because we created our project for “https” protocol. “CoreMVCProject5” profile is used to run the application by
using the Kestrel Web Server and the Application URL’s are: http://localhost:5000 and https://localhost:5001 (if
SSL option has been selected by us while creating the project).

In the “Standard Tool Bar” under “Debug Target DropDownList” of Visual Studio, we find “IIS Express”
selected by default, so when we hit F5 and run the project it will run using “IIS Express.exe” and in the browsers
address bar we see the Port No. which is shown in “launchSettings.json” file. We can change the profile from “IIS
Express” to “CoreMVCProject5” so that the application runs on Kestrel Web Server and now we see the Port No. as
5000 for Http Protocol and 5001 for Https Protocol and notice that it will launch a new Command Window running
the Kestrel Web Server on Port No. 5000 and 5001 (Provided Http’s option is selected while project creation).

Note: We can also run the ASP.NET Core Application from the command line by using the “.NET Core CLI (Command
Line Interface)” which will use Kestrel as Web Server. To run .NET Core Application using .NET Core CLI Command,
open “Developer Command Prompt for VS”. Now change the directory to the folder where we saved our Project i.e.,
“<Drive>:\<Personal_Folder>\CoreMVCProject5\CoreMVCProject5”, so change to that folder and execute the
“dotnet run” command as shown below:

<Drive>:\<Personal_Folder>\CoreMVCProject5\CoreMVCProject5> dotnet run

Once we type the “dotnet run” command and press enter key, .NET Core CLI builds and runs the application
and it also shows the URL to access our application as following => http://localhost:5000 and
https://localhost:5001 (provided Https option is selected while project creation), and if you remember these port
are configured in “launchSettings.json” file of our application under “CoreMVCProject5” profile which is nothing but
the profile for the Kestrel Web Server. Now open any browser and navigate to http://localhost:5000 or
https://localhost:5001 (provided Http’s option is selected while project creation), which displays the output.

Note: Till now even we ran our application in “IIS Express” or “IIS” or “Kestrel Web Server” all these are “In-Process
Hosting” only and now let’s learn about “Out of Process Hosting”.

Out-Of-Process Hosting: to run the application in “OutOfProcess” we need to configure it either in the “Project File”
or under “Debug” option of Project Properties Window.

Option 1: Configuring in Project File: in Solution Explorer, right click on the Project and select the option “Edit Project
File” which will open “CoreMVCProject5.csproj” file in the document window. In this file we need to add the
<AspNetCoreHostingModel> tag under <PropertyGroup> tag with value as “OutOfProcess” as shown below:
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>

Option 2: Specify the Hosting Model as OutOfProcess in Project Properties Window: open the Project Properties
Window, select Debug tab in LHS and on the right click on “Open debug launch profiles UI” link and change the value
of “Hosting Model” in the DropDownList as “Out of Process”.

295
What is Out of Process Hosting in ASP.NET Core?
Ans: In case of ASP.NET Core => “Out of Process” Hosting Model there will be 2 Web Servers.

1. An internal Web Server which is the Kestrel Web Server.


2. An external Web Server which can be IIS Express or IIS or Apache or Nginx or Tomcat, etc.

The very important point that we need to keep in mind is depending on how you are running your
application with the “Out of Process” hosting model, the external Web Server may or may not come into picture. As
we already discussed that Kestrel Web Server is a Cross-Platform Web Server that is already embedded with your
ASP.NET Core Application. So, if we are using “Out of Process” Hosting Model for our ASP.NET Core Application, then
Kestrel Web Server can be used in one of the following ways:

Option 1: we can use Kestrel Web Server as an internet-facing Web Server which will directly process the incoming
HTTP Requests and in this scenario only Kestrel Web Server is used, and external Web Server is not going to be used
at all. So, when we run the application using the .NET Core CLI then Kestrel is the only Web Server that is going to be
used to handle and process all the incoming HTTP Requests. To test this, open Visual Studio Developer Command
Prompt and run the application as explained earlier.

Now open any browser and navigate to the URL: http://localhost:5000, which will display the output on the
browser, and in this case even if we specified the ASP Net Core Hosting Model as “OutOfProcess” also it host the
application in Kestrel and it only will respond for the incoming requests.

Option 2: The Kestrel Web Server can also be used with the combination of a Reverse Proxy Server such as IIS
Express, IIS, Tomcat, Apache, or Nginx. When we run our ASP.NET Core Application directly from Visual Studio
choosing IIS or IIS Express Profile, setting the “AspNetCoreHostingModel” element value as “OutOfProcess” then IIS
or IIS Express will be used as Reverse Proxy Server and Kestrel is used as Internal Web Server.

To test this go to “Startup.cs” file in our project, import the namespace “Microsoft.AspNetCore.Http” and
then in the “Configure” method we find “app.UseEndPoints” method call and we need to change the code of it.

By default, the code in it will be as following:


app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

296
Re-write the code in the method as below:
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync(System.Diagnostics.Process.GetCurrentProcess().ProcessName);
});
});

Now set the hosting model as “Out of Process” either in the project property window or in project file and
then choose “CoreMVCProject5” profile to run the project which will display the process name as
“CoreMVCProject5” only which means the Kestrel Web Server is processing our incoming request directly and the
URL in the address bar is pointing to Port No. 5001, so there is no “Reverse Proxy Server” in usage.

Now choose “IIS” or “IISExpress” profile and run the project which will display the process name as
“CoreMVCProject5”, which means the Kestrel Web Server is processing our incoming request, and if we watch the
URL in the address bar it is pointing to IIS or IIS Express, so in this case there is a “Reverse Proxy Server” in usage i.e.,
IIS Express or IIS which is taking the incoming request and Kestrel Web Server which is processing the requests.

Now the question that comes to our mind is, if Kestrel can be used by itself as a Web Server which can directly
handle and process the incoming HTTP Request’s, then why do we need a reverse proxy server?
Ans: This is all because, the reverse proxy server provides an additional layer of security and configuration which is
not available with Kestrel Server, and it also maintains load balancing. So, it is a good choice to use Kestrel Server
along with a Reverse Proxy Server. When we use Kestrel along with the Reverse Proxy Server, then the Reverse Proxy
Server will receive all the incoming HTTP Requests from client’s and then forwards that request to the Kestrel Web
Server for processing. Once the Kestrel Web Server process that request, then it sends the response back to the
reverse proxy server which then sends response back to the requested client over the internet.

297
Working with ASP.NET Core MVC Applications
Create a new “ASP.NET Core Empty” project, naming it as “CoreTestProject”, choose the Target Framework
as “.NET 5.0 (Out of Support) or .NET 6.0 (Long Term Support) or .NET 7.0 (Standard Term Support) or .NET 8.0 (Long
Term Support) or .NET 9.0 (Standard Term Support)” select the Checkbox’s “Configure for HTTPS” and “Do not use
top-level statements”, and click on “Create” button.

Right now, we have chosen an “Empty Project Template”, so we can configure it as an ASP.NET Core Web
App or Web API or MVC Application also. To make it as an MVC Application, do the following changes:

ASP.NET Core 5.0 => Open “Startup.cs” file and write the below code under “ConfigureServices” method of the class:
services.AddControllersWithViews();

ASP.NET Core 6.0 and above => Open “Program.cs” file and write the below statement just above the statement
“var app = builder.Build();”.
builder.Services.AddControllersWithViews();

Now add Static Files and End Points Middleware as below:


ASP.NET Core 5.0 => Now under the Configure method of Startup class add “UseStaticFiles” middleware above
“app.UseRouting” statement as following:
app.UseStaticFiles();
ASP.NET Core 6.0 and above => Now under Program class write the above statement just below the statement “var
app = builder.Build();”.

ASP.NET Core 5.0 => Delete all the code that is present in “UseEndpoints” block and write the below code over there
which should now look as following:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

ASP.NET Core 6.0 and above => Now in the bottom of “Program.cs” file we find a statement “app.MapGet("/", () =>
"Hello World!");”, comment it or delete it and write the below code over there:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

Note: after all the above changes our application is now an “MVC Application”, so we can now add “wwwroot”,
“Controllers”, “Models” and “Views” folders as per our requirements. So let us add all the 4 folders under our Project
from Solution Explorer.

Adding a Controller in Controllers Folder: Now let’s add a new Controller choosing the option “MVC Controller –
Empty” under “Add New Scaffolded Item” window, naming it as “HomeController”. If we observe the parent class
of “HomeController”, it is “Controller” only just like in our “ASP.NET MVC” but, this class is defined in
“Microsoft.AspNetCore.Mvc” namespace, whereas in “ASP.NET MVC” the class “Controller” is defined in
“System.Web.Mvc” namespace.

298
In the “HomeController” by default we find a “Action Method” with the name “Index” and the return type
of the method is “IActionResult” Interface which is the parent of all the “Action Results” in an ASP.NET Core MVC
Application, whereas in ASP.NET MVC Applications the parent of all Action Results is a class i.e., “ActionResult”.

Adding a View to Index Action Method: Now right click on the “Index” action method which is present in
“HomeController” class and select the option “Add View” and in the window opened, choose “Razor View – Empty”
and click on the “Add” button which will add a new View with the name “Index.cshtml” by creating a folder under
the “Views” folder with the name “Home” and the View gets added into the “Home” folder. Write the below code
in it and execute:
<h3>Home Controller - Index View</h3>

Now hit “F5” and run the project which will display a Message Box asking about SSL Certificate because we
have chosen “Configure for HTTPs” option while creating the project click on “Yes” button which will display a
Security Warning window asking for installing the certification on your machine click “Yes” button again which will
launch the browser and displays the output.

Note: now if you observe the URL in Browser’s - Address Bar, the protocol will be “HTTPs”. In ASP.NET Core 6.0 and
above the default Web Server - Visual Studio uses to run the Web App’s is Kestrel and the Port used for HTTPS in
Kestrel will be different and for HTTP will be different. We can verify the ports used in “launchSettings.json” file. You
can even change the Server by choosing a Profile in Debug Target Dropdown List that is present in Standard Toolbar.

Routing: This is responsible for matching incoming HTTP Requests and then dispatching those requests to the
applications executable Endpoints. Endpoints are the applications units of executable request-handling code which
are defined in the application and configured when the app starts. The Endpoint matching process can extract values
from the requests URL and provide those values for request processing. All ASP.NET Core templates include routing
in their generated code. Routing is registered in the middleware pipeline of Startup class upto ASP.NET Core 5.0 and
Program class from ASP.NET Core 6.0.

MVC Supports 2 different types of Routings:


1. Conventional Routing
2. Attribute Routing

Conventional Routing: this is a pattern matching system for URL, which maps incoming requests to a particular
Controller and Action method. In conventional routing we set all the routes in “RouteConfig.cs” file in “ASP.NET
MVC” by calling the method “MapRoute”, whereas in “ASP.NET Core MVC” we do that by calling
“MapControllerRoute” method in Startup class for Core 5.0 and Program class for Core 6.0 and above.

Attribute Routing: this is a simple routing mechanism, compared to conventional routing. All the concepts are just
like the conventional approach only but here, we define routes and attributes on a Controller or Action method. This
was introduced from “ASP.NET MVC 5” and was available in “ASP.NET Core MVC” also. To use attribute routing in
“ASP.NET MVC 5” we need to call the method “MapMvcAttributeRoutes” in “RouteConfig.cs” file whereas in case of
“ASP.NET Core MVC” we need to call the method “MapControllers” in Startup class for ASP.NET 5.0 and Program
class in ASP.NET Core 6.0 and above.
Route Type Method to use in MVC 5 Methods to use in MVC Core
Conventional: MapRoute MapControllerRoute
Attribute: MapMvcAttributeRoutes MapControllers

299
To test “Attribute Routing” go to “Startup.cs” file (ASP.NET Core MVC 5.0) of our current project i.e.,
“CoreTestProject”, delete the code which we have implemented in “UseEndPoints” block earlier and then call
“MapControllers” method over there and it should now look as below:

Old Code (Conventional): app.UseEndpoints(endpoints =>


{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

New Code (Attribute): app.UseEndpoints(endpoints =>


{
endpoints.MapControllers();
});

If you are working with ASP.NET Core MVC 6.0 and above go to Program class, delete or comment the
method call “MapControllerRoute” and call the method “MapControllers”.

Old Code (Conventional): app.MapControllerRoute(


name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

New Code (Attribute): app.MapControllers();

Note: after doing the above action if we try to run the “Index.cshtml” view we get a “404 – Page Not Found” error
because there is no route pattern defined anywhere.

To define the routing pattern, go to “Home Controller” class and write the following statements above the
“Index” action method which should now look as following:

[Route("")] //https://localhost:Port
[Route("Home")] //https://localhost:Port/Home
[Route("Home/Index")] //https://localhost:Port/Home/Index
public IActionResult Index()
{
return View();
}

Note: The above statements when added on the top of action method will be launching the view when we use the
corresponding URL's.

We can even set attribute routes on Controllers also and to test this write the below statement above the
Controller class which should now like as following:

[Route("Home")]
public class HomeController : Controller

300
In this case we don’t require using controller name while setting the route for Index action method and it
should be as following:
[Route("/")] //https://localhost:Port
[Route("")] //https://localhost:Port/Home
[Route("Index")] //https://localhost:Port/Home/Index
public IActionResult Index()

In attribute routing we can hide the original name of the controller and action method so that end users
can’t view the name of the controller and action method and to do that we need to specify an alias name in the
route as following:

Specifying an alias name to Controller:


[Route("Test")]
public class HomeController : Controller

Specifying an alias name to Action Method:


[Route("/")] //https://localhost:Port
[Route("")] //https://localhost:Port/Test
[Route("Demo")] //https://localhost:Port/Test/Demo
public IActionResult Index()

Without hard coding controller names or action method names in attribute routes we can use the concept
of “Token Replacements”, for example we can define the route for Controller as:
[Route("[controller]")]
public class HomeController : Controller

In the above case "[controller]" is a token which is replaced with the name of the Controller in runtime and
same as this we can also do this for action methods also as following:
[Route("/")] //https://localhost:Port
[Route("")] //https://localhost:Port/Home
[Route("[action]")] //https://localhost:Port/Home/Index
public IActionResult Index()

We can also use "[controller]/[action]" token on Controller class as following:


[Route("[controller]/[action]")]
public class HomeController : Controller

In this case route for Index action method will be as following:


[Route("/")] //https://localhost:Port
[Route("/Home")] //https://localhost:Port/Home
[Route("")] //https://localhost:Port/Home/Index
public IActionResult Index()

Route Constraints: we use these to restrict the browser requests to match a particular route and we can even use
regular expressions to specify a route constraint.
alpha => Accepts only alphabets (Upper or Lower Case) {x:alpha}
bool => Accepts only boolean values {x:bool}

301
datetime => Accepts only DateTime values {x:datetime}
decimal => Accepts only decimal values {x:decimal}
double => Accepts a 64-bit floating-point value {x:double}
float => Accepts a 32-bit floating-point value {x:float}
int => Accepts a 32-bit integer value {x:int}
long => Accepts a 64-bit integer value {x:long}
max => Accepts a numeric up to a given maximum value {x:max(10)}
min => Accepts a numeric up to a given minimum value {x:min(5)}
range => Accepts a numeric within given range of values {x:range(10,50)}
length => Accepts a string with a specified length {x:length(6)}
Or
=> Accepts a specified range of characters {x:length(1,9)}
maxlength => Accepts a string with a given maximum length {x:maxlength(9)}
minlength => Accepts a string with a given minimum length {x:minlength(5)}
regex => Matches a given value with a specified regular expression.
{x:regex(^\d{{4}}-\d{{4}}-\d{{4}}$)}

To practice route constraints first set the route for controller as below:
Route("[controller]")]
public class HomeController : Controller

Define a new action method in the Controller class as following:


[Route("Display1/{id?}")]
public string Display1(int id)
{
return "Value of id is: " + id;
}

The above action method gets executed when we use the below URL’s:
https://localhost:port/Home/Display1 //Valid
https://localhost:port/Home/Display1/10 //Valid
https://localhost:port/Home/Display1/A //Valid
https://localhost:port/Home/Display1/false //Valid
https://localhost:port/Home/Display1/Hello //Valid
https://localhost:port/Home/Display1/34.56 //Valid

In the above case we defined "{id?}" as a route parameter and it is optional so if we do not pass a value to
id or if we pass a value of different data types, it will not raise any error but id value will be "0", whereas if we want
the parameter value to be an integer, or any other particular data type or if we want to apply any other restrictions
on the action method parameters, we should use route constraints.

Add a new action method into the Home Controller class as following:
[Route("Display2/{id:int}")]
public string Display2(int id)
{
return "Value of id is: " + id;
}

302
In the above case we need to call the Display2 action method by explicitly passing an integer value only,
whereas if we try to pass any other type of values or if we do not pass a value, we get error.

https://localhost:port/Home/Display2/10 //Valid
https://localhost:port/Home/Display2 //Error
https://localhost:port/Home/Display2/Hello //Error
https://localhost:port/Home/Display2/34.56 //Error
https://localhost:port/Home/Display2/false //Error
https://localhost:port/Home/Display2/A //Error

Note: if you want to call the above method without passing a value make int as nullable int i.e., “int?”.

[Route("Display3/{id:double?}")]
public string Display3(double id)
{
return "Value of id is: " + id;
}

In the above method id parameter is defined to accept a double value so we can pass an integer or a double
also as following:
https://localhost:port/Home/Display3 //Valid
https://localhost:port/Home/Display3/10 //Valid
https://localhost:port/Home/Display3/34.56 //Valid
https://localhost:port/Home/Display3/A //Error
https://localhost:port/Home/Display3/Hello //Error
https://localhost:port/Home/Display3/false //Error

[Route("Display4/{id:min(50)}")]
public string Display4(int id)
{
return "Value of id is: " + id;
}

The above method is defined with a constraint to accept an integer with a minimum value of 50, so any
value less than 50 throws an error:
https://localhost:port/Home/Display4 //Error
https://localhost:port/Home/Display4/-10 //Error
https://localhost:port/Home/Display4/49 //Error
https://localhost:port/Home/Display4/50 //Valid
https://localhost:port/Home/Display4/51 //Valid

[Route("Display5/{id:max(100)}")]
public string Display5(int id)
{
return "Value of id is: " + id;
}

303
The above method is defined with a constraint to accept an integer with a maximum value of 100, so any
value greater than 100 throws an error:
https://localhost:port/Home/Display5 //Error
https://localhost:port/Home/Display5/99 //Valid
https://localhost:port/Home/Display5/100 //Valid
https://localhost:port/Home/Display5/101 //Error
https://localhost:port/Home/Display5/-10 //Valid

[Route("Display6/{id:range(51, 100)}")]
public string Display6(int id)
{
return "Value of id is: " + id;
}

The above method is defined with a constraint to accept an integer within a range of 51 to 100, so any value
less than 51 and greater than 100 throws an error:
http://localhost:port/Home/Display6 //Error
http://localhost:port/Home/Display6/50 //Error
http://localhost:port/Home/Display6/51 //Valid
http://localhost:port/Home/Display6/100 //Valid
http://localhost:port/Home/Display6/101 //Error

[Route("Display7/{name:length(5)}")]
public string Display7(string name)
{
return "Name of the user is: " + name;
}

The above method is defined with a constraint to accept a string value with a length of 5 characters, so any
value less than 5 or greater than 5 characters, throws an error:
http://localhost:port/Home/Display7 //Error
http://localhost:port/Home/Display7/Abcd //Error
http://localhost:port/Home/Display7/Abcde //Valid
http://localhost:port/Home/Display7/Abcdef //Error
http://localhost:port/Home/Display7/false //Valid
http://localhost:port/Home/Display7/12345 //Valid

[Route("Display8/{name:length(3, 10)}")]
public string Display8(string name)
{
return "Name of the user is: " + name;
}

The above method is defined with a constraint to accept a string value with a minimum length of 3
characters and maximum length of 10 characters, so any value less than 3 characters or greater than 10 characters,
throws an error:

304
http://localhost:port/Home/Display8 //Error
http://localhost:port/Home/Display8/AB //Error
http://localhost:port/Home/Display8/Sai //Valid
http://localhost:port/Home/Display8/Venkat //Valid
http://localhost:port/Home/Display8/Bangarraju //Valid
http://localhost:port/Home/Display8/DavidWarner //Error

[Route("Display9/{name:minlength(3)}")]
public string Display9(string name)
{
return "Name of the user is: " + name;
}

The above method is defined with a constraint to accept a string value with a minimum length of 3
characters, so any value less than 3 characters, throws an error:
http://localhost:port/Home/Display9 //Error
http://localhost:port/Home/Display9/AB //Error
http://localhost:port/Home/Display9/Sai //Valid
http://localhost:port/Home/Display9/Bangarraju //Valid
http://localhost:port/Home/Display9/DavidWarner //Valid

[Route("Display10/{name:maxlength(10)}")]
public string Display10(string name)
{
return "Name of the user is: " + name;
}

The above method is defined with a constraint to accept a string value with a maximum length of 10
characters, so any value greater than 10 characters, throws an error:
http://localhost:port/Home/Display10 //Error
http://localhost:port/Home/Display10/AB //Valid
http://localhost:port/Home/Display10/Sai //Valid
http://localhost:port/Home/Display10/Bangarraju //Valid
http://localhost:port/Home/Display10/DavidWarner //Error

[Route("Display11/{name:alpha}")]
public string Display11(string name)
{
return "Name of the user is: " + name;
}

The above method is defined with a constraint to accept only string values so any value other than string,
throws an error:
http://localhost:port/Home/Display11 //Error
http://localhost:port/Home/Display11/Raju //Valid
http://localhost:port/Home/Display11/1234 //Error

305
http://localhost:port/Home/Display11/34.56 //Error
http://localhost:port/Home/Display11/false //Valid

[Route("Display12/{flag:bool}")]
public string Display12(bool flag)
{
if (flag)
return "Hello India!";
else
return "Hello World!";
}

The above method is defined with a constraint to accept only boolean values so any value other than
boolean, throws an error:
http://localhost:port/Home/Display12 //Error
http://localhost:port/Home/Display12/true //Valid
http://localhost:port/Home/Display12/Hello //Error
http://localhost:port/Home/Display12/34.56 //Error
http://localhost:port/Home/Display12/false //Valid

[Route("Display13/{aadhar:regex(^\\d{{4}}-\\d{{4}}-\\d{{4}}$)}")]
public string Display13(string aadhar)
{
return "Aadhar Id of the user is: " + aadhar;
}

The above method is defined with a constraint to accept Aadhar Id by using a regular expression, so any
value that doesn't match with the expression will throw an error:
http://localhost:port/Home/Display13 //Error
http://localhost:port/Home/Display13/1234-1234-1234 //Valid
http://localhost:port/Home/Display13/1234-1234-123 //Error
http://localhost:port/Home/Display13/1234-1234-12345 //Error
http://localhost:port/Home/Display13/1234-1234=1234 //Error

[Route("Display14/{id}/{name}")]
public string Display14(int id, string name)
{
return "Id of the user is: " + id + " and name of the user is: " + name;
}

The above method is defined with 2 mandatory parameters id and name, so if we try to call it with any
other value other than those it will throw an error:
http://localhost:50293/Home/Display14 //Error
http://localhost:50293/Home/Display14/101 //Error
http://localhost:50293/Home/Display14/101/Raju //Valid
http://localhost:50293/Home/Display14/101/Raju/50.56 //Error

306
Creating Views (User Interfaces) in MVC CORE
Create a new “ASP.NET Core Empty” project naming it as “MVCCoreTagHelpers”, choose Target Framework
as “.NET 5.0 (Out of Support)” or “.NET 6.0 (Long Term Support)” or “.NET 7.0 (Standard Term Support)” or “.NET 8.0
(Long Term Support) or .NET 9.0 (Standard Term Support)” and click on the Create button. Because we have chosen
an empty project template, configure the project to work as an MVC Application as explained earlier and then do
the following:

Add a new folder under the project naming it as “Models”, add a new class in to that folder naming it as
“LoginModel” and write the below code in it importing “System.ComponentModel.DataAnnotations” namespace:

public class LoginModel


{
[EmailAddress]
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public bool RememberMe { get; set; }
}

Add a new folder under the project naming it as “Controllers”, add a new Controller class into the folder
naming it as “AccountController”, and write the below code in it by deleting the existing Index action method:

public ViewResult Login()


{
return View();
}

Add a view to “Login” action method and to do that right click on the method that is present in the
Controller class, select the option “Add View” which launches a window, in that select “Razor View-Empty”, click on
“Add” button which opens a window asking for a name, enter name as “Login.cshtml” and click “Add” button.

Note: now in the view we need to import the Model class to access the properties of Model class, as following:
@model MVCCoreTagHelpers.Models.LoginModel

In the above statement we are prefixing the “Namespace-Name” before the “Model Class-Name”, and we
need to do this in every View where we are using “Model Binding”. To simplify the coding or decrease the typing
work MVC Core introduced an option called as “ViewImports” i.e., it is a new “.cshtml” file present under the Views
folder just like “_ViewStart.cshtml”, but with the name “_ViewImports.cshtml” and we can use this file for importing
all the required namespaces for Views, so that we don’t require to do that again and again in each View.

If we create a project of type “ASP.NET Core Empty” then we will not have “_ViewImports.cshtml” by
default in our project so we need to explicitly add it, and to do that right click on the Views folder and select the
option Add => View which will open a new window and in that window select “Razor View Empty” and click on the
“Add” button which opens another window and in that window select the template “Razor View Imports” which
displays “_ViewImports.cshtml” as the name of file, click on “Add” button to add it to the Project. By default, the file
will be empty and, in the file, write the below statement:
@using MVCCoreTagHelpers.Models

307
Note: If we create a project of type “ASP.NET Core Web App (Model-View-Controller)”, then we don’t require doing
all the above things because my default “_ViewImports.cshtml” file is added, and the Models namespace is also
imported.

Now in “Login.cshtml” without prefixing the namespace name before Model class name we can directly
write it as following:
@model LoginModel

Installing Bootstrap for designing Views: if we want to use bootstrap for styling of elements, we need to first install
bootstrap in our projects and we can do that either by using “NuGet Package Manager” or “Library Manager” for
managing all the client-side libraries.

Now write the below code in the “Login.cshtml” file by deleting all the content in the file except the Model
class import statement, for creating the Login Form using “HtmlHelpers”:

<html>
<head>
<title>Login Form</title>
<link href="~/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<h1>Login Form</h1>
<section>
@using (Html.BeginForm("Login", "Account", FormMethod.Post,
new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<hr />
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
@Html.TextBoxFor(m => m.Email, new { @class = "col-md-4 form-control" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
@Html.PasswordFor(m => m.Password, new { @class = "col-md-4 form-control" })
</div>
<div class="form-group">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
<div class="form-group">
<input type="submit" value="Log In" class="btn btn-primary" />
<input type="reset" value="Reset" class="btn btn-primary" />
</div>
}
</section>

308
</body>
</html>

In the View what we have created above, we used “Html Helpers” to design the UI or View whereas “MVC
Core” provided us “Tag Helpers” for UI or View designing.

How to use Tag Helpers?


Ans: To use the In-built Tag Helpers, we must import them by using “@addTagHelper” directive in
“_ViewImports.cshtml” file. If our project is “ASP.NET Core Empty” we need to perform importing explicitly whereas
if the project is “ASP.NET Core Web App (Model-View-Controller)” then it is automatically imported and to check
that go to “_ViewImports.cshtml” and watch the code, and there we find the below statement and if not found do
it manually:
@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers

Note: The above statement will import all the Tag helpers that are present in the namespace
“Microsoft.AspNetCore.Mvc.TagHelpers” and as discussed above if we import a library in “_ViewImports.cshtml” file
then it will be available for all the views. If you don’t want any views to use globally imported Tag Helpers, you can
use @removeTagHelper in the respective view.

If we want to use these Tag Helpers in our Login Page, then delete all the content that is present inside of
<section></section> tags in the code present there and write the below code inside of <section></section> tags:

<form asp-controller="Account" asp-action="Login" class="form-horizontal" role="form">


<hr />
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<input asp-for="Email" class="col-md-4 form-control" />
</div>
<div class="form-group">
<label asp-for="Password" class="col-md-2 control-label"></label>
<input asp-for="Password" class="col-md-4 form-control" />
</div>
<div class="form-group">
<input asp-for="RememberMe" />
<label asp-for="RememberMe" class="col-md-2 control-label"></label>
</div>
<div class="form-group">
<input type="submit" value="Log In" class="btn btn-primary" />
<input type="reset" value="Reset" class="btn btn-primary" />
</div>
</form>

MVC Core Tag Helpers: these will enable server-side code to participate in creating and rendering HTML elements
in Razor Pages. There are many built-in Tag Helpers for common tasks - such as creating forms, links, loading assets
and more - and even more available in public GitHub repositories as NuGet packages as well as we can also create
our own Tag Helpers.

309
Tag Helpers are authored in C#, and they target HTML Elements based on the element or attribute name.
For example, the built-in “LabelTagHelper” class targets the HTML Label Element when the “LabelTagHelper”
attributes are applied. If we are familiar with HTML Helpers in MVC 5, Tag Helpers will reduce the explicit transitions
between HTML and C# in Razor views i.e., in many cases, HTML Helpers provide an alternative approach to a specific
Tag Helper, but it’s important to recognize that Tag Helpers don’t replace HTML Helpers and there is no Tag Helper
available for every HTML Helper.

What Tag Helpers provide?


Ans: Tag Helpers provide an HTML friendly development experience for the most part, Razor markup using Tag
Helpers looks like standard HTML. Front-end designers who are familiar with HTML/CSS/JavaScript can edit Razor
without learning C# Razor syntax.

Tag Helpers are a way to make developers more productive and be able to produce more robust, reliable,
and maintainable code using information that is available on the server. For example, historically the mantra of
updating images was to change the name of image whenever we change the image because Images will be cached
by the browsers for performance reasons, and unless we change the name of an image, you risk clients getting a
stale copy. Historically, after an image was edited, the name must be changed and each reference to the image in
the web application needed to be updated. Not only this is labor intensive, but it’s also errors prone (you could miss
a reference, accidentally enter the wrong string). The built-in “ImageTagHelper” can do this work automatically for
us i.e., this will append a version number to the image name, so whenever the image changes, the server
automatically generates a new unique version for the image, so clients are guaranteed to get the latest image. This
robustness and labor savings comes essentially free by using the “ImageTagHelper”.

All the built-in Tag Helpers target the standard HTML Elements and provide server-side attributes for those
elements. For example, the <input> element used in our views contains the “asp-for” attribute and this attribute
extracts the name of the specified Model Property into the rendered HTML.

What are Tag Helpers?


Ans: Tag Helpers are Classes written in C# but are attached to HTML Elements to run server-side code from Razor
Views, in other words, Views that are created in HTML do have their presentation logic defined in C#, which is
ultimately executed on Web Server. Examples of some built-in Tag Helpers are Anchor tag, Environment tag, etc.

Form TagHelper: this is used for creating Form element.

Tag helper we use:


<form asp-controller="Home" asp-action="Index">
<!-- Input and Submit elements -->
</form>

Rendered HTML will be as following:


<form method="post" action="/Home/Index">
<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<generated value>">
</form>

Note: MVC runtime generates action attribute value based on the Form Tag Helper Attributes => asp-controller and
asp-action. The Form Tag Helper also generates a hidden Request Verification Token to prevent cross-site request

310
forgery (when used with [ValidateAntiForgeryToken] filter attribute in HTTP Post action method). Protecting a pure
HTML Form from cross-site request forgery is difficult; the Form Tag Helper provides this service free for you. The
default method is “Post” even if not specified.

Using a named route: The asp-route Tag Helper attribute can also generate markup for the HTML action attribute.
An application with a route named “RegisterRoute” could use the following markup for the Registration Page:

public class AccountController : Controller


{
[Route("/Account/Register", Name = "RegisterRoute")]
public ActionResult Registration()
{
return "This is a Registration Page.";
}
}

Tag helper we use:


<form asp-route="RegisterRoute">
<!-- Input and Submit elements -->
</form>

This renders the below HTML:


<form method="post" action="/Account/Register">
<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<generated value>">
</form>

Form Action Tag Helper: This generates the form action attribute based on the Button or Input type - image tags.
The form action attributes controls where a form submits its data. It binds to <input> elements of type image and
<button> elements. The Form Action Tag Helper enables the usage of several “AnchorTagHelper” “asp- attributes”
to control what “form action” link is generated for the corresponding element. For example, if we define a Controller
class with a set of action methods using attribute routing along with a name to the route then we can use form
action tag helper to generate submit links.

public class AccountController : Controller


{
[Route("/Account/Login", Name = "LoginRoute")]
public string Login()
{
return "This is a Login Page.";
}
[Route("/Account/Register", Name = "RegisterRoute")]
public string Register()
{
return "This is a Registration Page.";
}
}

311
Submit to controller’s action method example:
<form method="post">
//Place controls for Login
<button asp-controller="Account" asp-action="Login">Login</button>
//Place controls for Register
<button asp-controller="Account" asp-action="Register">Register</button>
</form>

Submit to route example:


<form method="post">
//Place controls for Login
<button asp-route="LoginRoute">Login</button>
//Place controls for Register
<button asp-route="RegisterRoute">Register</button>
</form>

The Input Tag Helper: This renders an Html input element.


<input asp-for="<Expression Name>">

Note: The Input Tag Helper sets the HTML “type” attribute based on the .NET type. The below table lists, some
common .NET types, and generated HTML types:

.NET Type Input Type


bool type="checkbox"
string type="text"
DateTime type="datetime-local"
Byte, int, single, double type="number"

The following table shows some common data annotations attributes that the input tag helper will map to
specific input types:

Attribute Input Type


[EmailAddress] type="email"
[Url] type="url"
[HiddenInput] type="hidden"
[Phone] type="tel"
[DataType(DataType.Password)] type="password"
[DataType(DataType.Date)] type="date"
[DataType(DataType.Time)] type="time"

The Select Tag Helper: Generates select and associated option elements for properties of your model. The Select
Tag Helper’s “asp-for” specifies the model property name for the select element and “asp-items” specifies the option
for elements. For example:

public class CountryModel


{
public string City { get; set; }

312
public List<SelectListItem> Cities { get; } = new List<SelectListItem>
{
new SelectListItem { Value = "C1", Text = "Delhi" },
new SelectListItem { Value = "C2", Text = "Kolkata" },
new SelectListItem { Value = "C3", Text = "Mumbai" },
new SelectListItem { Value = "C4", Text = "Chennai" },
new SelectListItem { Value = "C5", Text = "Bengaluru" },
new SelectListItem { Value = "C6", Text = "Hyderabad"}
};
}

Tag helper we use: <select asp-for="City" asp-items="Model.Cities"></select >

Multi-select: The Select Tag Helper will automatically generate the multiple = "multiple" attribute if the property
specified in the “asp-for” attribute is an “IEnumerable”. For example, given the following model:

public class CountryModel


{
public List<string> City { get; set; }
public List<SelectListItem> Cities { get; } = new List<SelectListItem>
{
new SelectListItem { Value = "C1", Text = "Delhi" },
new SelectListItem { Value = "C2", Text = "Kolkata" },
new SelectListItem { Value = "C3", Text = "Mumbai" },
new SelectListItem { Value = "C4", Text = "Chennai" },
new SelectListItem { Value = "C5", Text = "Bengaluru" },
new SelectListItem { Value = "C6", Text = "Hyderabad"}
};
}

Tag helper we use: <select asp-for="City" asp-items="Model.Cities"></select >

Anchor Tag Helper: Anchor Tag Helper enhances the standard HTML anchor (<a ... ></a>) tag by adding new
attributes.
public class StudentController : Controller
{
[Route("/Student/GetStudent", Name = "StudentGet")]
public ActionResult GetStudent()
{
return View();
}
}
Tag helper we use: <a asp-controller="Student" asp-action="GetStudent">Display all Students</a>

asp-route: The asp-route attribute is used for creating a URL link directly to a named route. Using routing attributes,
a route can be named as shown in the “StudentController” and used in its “GetStudent” action:
Tag helper we use: <a asp-route="StudentGet">Student Details</a>

313
Image Tag Helper: The Image Tag Helper enhances the “<img>” tag to provide cache-busting behavior for static
image files. Cache-busting string means a unique value representing the hash of the static image file appended to
the asset’s URL. The unique string prompts clients (and some proxies) to reload the image from the host web server
and not from the client's cache.

Tag helper we use: <img src="~/images/asplogo.png" asp-append-version="true">

Environment Tag Helper: The Environment Tag Helper conditionally renders its enclosed content based on the
current hosting environment i.e., this Tag Helper’s include or exclude attributes can be used to specify a comma-
separated list of environment names. If any of the given environment names match the current environment, the
enclosed content is rendered.

To work with “Image” and “Environment” TagHelpers add 2 new action methods in “AccountController”
class of “MVCCoreTagHelpers” project and write the below code under the existing Login method:

public ViewResult Index()


{
return View();
}
public ViewResult Register()
{
return View();
}

To work with “ImageTagHelper” add a new folder with the name “images” under “wwwroot” folder and
copy an image into it with the name “Register.jpg”. Add a View to Register action method and write the below code
in it by deleting the exiting content in it:

<!DOCTYPE html>
<html>
<head>
<title>Registration Form</title>
<link href="~/lib/bootstrap/css/bootstrap.css" rel="stylesheet" />
</head>
<body>
<h1>Registration Form</h1>
<img src="~/images/Register.jpg" class="card-img-top" />
</body>
</html>

Call the Register action method to launch “Register.cshtml” file, now replace the image in images folder
with a new image but the image name should be “Register.jpg” only and launch Register view again but you will see
old image only but not the new image because of the cache busting behavior of the browser and to resolve the
problem add “asp-append-version="true"” to the image tag which should now look as following:

<img src="~/images/Register.jpg" class="card-img-top" asp-append-version="true" />

314
When we add the new attribute to Image Tag it will generate a unique hash value based on the image
content and appends to the image name, so whenever image changes (not the name) a new hash value will be
generated, appended to the image name, and then loads the image from the server without loading it from browser
cache.

To work with EnvironmentTagHelper add a new view to Index action method and write the below code in
it by deleting the exiting content in it:

@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment env


<!DOCTYPE html>
<html>
<head>
<title>Index Form</title>
<environment include="Development">
<link href="~/lib/bootstrap/css/bootstrap.css" rel="stylesheet" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href=https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.1/css/bootstrap.min.css
crossorigin="anonymous" referrerpolicy="no-referrer"
integrity="sha512-
6KY5s6UI5J7SVYuZB4S/CZMyPylqyyNZco376NM2Z8Sb8OxEdp02e1jkKk/wZxIEmjQ6DRCEBhni+gpr9c4tvA==" />
</environment>
</head>
<body>
<h3>Environment: @env.EnvironmentName</h3>
</body>
</html>

The Environment Tag Helper conditionally renders its enclosed content based on the current hosting
environment and to test this, run the Index view and in the browser use “View Page Source” option, and watch the
“<link>” tag in “<head>” section which will be loading the assets from “local folder” because our project is right now
running in “Development” environment and to change it open “launchSettings.json” file present under Properties
and change ("ASPNETCORE_ENVIRONMENT": "Development") as ("ASPNETCORE_ENVIRONMENT": "Production")
and run Index action method again and watch the “<link>” tag by using “View Page Source” which will now load the
assets from “CDN”.

Custom Tag Helpers: We can also develop our own Tag Helpers and consume them in our applications and to do
that we need to follow the below process:

Step 1: Add a new folder under the project with the name “TagHelpers”.
Step 2: Define a new class inheriting from the pre-defined class “TagHelper” which is present under the namespace
“Microsoft.AspNetCore.Razor.TagHelpers”. The name of the class should be same as the tag we are targeting
suffixed with TagHelper.
Step 3: Now under the class define all the properties we are expecting for our tag.
Step 4: Implement logic under the class by overriding the method “Process” of “TagHelper” class.
Step 5: Import the project namespace in “_ViewImports.cshtml” file.
Step 6: Start consuming the new TagHelper class in the required Views.

315
Creating a Custom Tag Helper:
Step 1: Add a new folder under the project naming it as “TagHelpers” and add a new class in the folder naming it as
“EmailTagHelper.cs” and write the below code by importing “Microsoft.AspNetCore.Razor.TagHelpers” namespace:

public class EmailTagHelper : TagHelper {


public string? MailTo { get; set; }
public string? InnerHtml { get; set; }
public string? DomainName { get; set; }
public string? TargetAddress { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output) {
output.TagName = "a";

if (!String.IsNullOrEmpty(TargetAddress))
output.Attributes.SetAttribute("href", $"mailto:{TargetAddress}");
else
output.Attributes.SetAttribute("href", $"mailto:{MailTo}@{DomainName}");

if (!String.IsNullOrEmpty(InnerHtml))
output.Content.SetContent(InnerHtml);
else if(!String.IsNullOrEmpty(TargetAddress))
output.Content.SetContent(TargetAddress);
else
output.Content.SetContent($"{MailTo}@{DomainName}");
}
}
In the above case we are targeting the “<email>” tag and implementing the logic so whenever we use the
“<email>” tag in our View file it will be changing to “<a>” tag and the 4 properties we defined in the class (MailTo,
DomainName, TargetAddress, and InnerHtml) will be defining the way how “<a>” tag is rendered.

Step 2: go to “_ViewImports.cshtml” file and import the project namespace on top of the file as following:
@addTagHelper *, MVCCoreTagHelpers

Step 3: Write the below code in <body> tag of “Index.cshtml” file by deleting the existing code present there:
<h3>Click to navigate:</h3>
<a class="btn btn-primary" href="/Home/Login">Login</a>
@Html.ActionLink("Register", "Register", "Home", null, new { @class="btn btn-primary" })
<a class="btn btn-primary" asp-controller="Home" asp-action="About">About</a>
<br /><br />
<strong>Support:</strong>
<email target-address="[email protected]"></email><br />
<strong>Marketing:</strong>
<email mail-to="marketing" domain-name="nareshit.com"></email><br />
<strong>Sales:</strong>
<email mail-to="sales" domain-name="nareshit.com" inner-html="Contact"></email>

Note: Now run the “Index.cshtml” file and watch the output of the “<email>” tag by using “View Page Source” option
where we notice “<a>” tags getting generated for all “<email>” tags.

316
Data Management using XML
Create a new “ASP.NET Core Web App (Model-View-Controller)” naming it as “MVCDHProject”, choose
Target Framework as “.NET 9.0 (Standard Term Support)”, and click on the Create button. Install the package “Razor
Runtime Compilation” using “Nuget Package Manager”.

Open Program.cs file and modify the code of below statement:


Old Code: builder.Services.AddControllersWithViews();
New Code: builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation();

Add a new XML File in the Project naming it as “Customer.xml” and write the below code in it:
<Customers>
<Customer>
<Custid>101</Custid>
<Name>Scott</Name>
<Balance>25000</Balance>
<City>Hyderabad</City>
<Status>True</Status>
</Customer>
<Customer>
<Custid>102</Custid>
<Name>Smith</Name>
<Balance>35000.00</Balance>
<City>Chennai</City>
<Status>True</Status>
</Customer>
<Customer>
<Custid>103</Custid>
<Name>David</Name>
<Balance>45000.00</Balance>
<City>Bengaluru</City>
<Status>True</Status>
</Customer>
</Customers>

Add a new class in to the Models folder naming it as “Customer” and write the below code in it:
public class Customer
{
public int Custid { get; set; }
public string? Name { get; set; }
public decimal? Balance { get; set; }
public string? City { get; set; }
public bool Status { get; set; }
}

317
Add another new class in to the Models folder naming it as “CustomerXmlDAL” and write the below code in it:
using System.Data;
public class CustomerXmlDAL
{
DataSet ds;
public CustomerXmlDAL()
{
ds = new DataSet();
ds.ReadXml("Customer.xml");
//Adding Primary Key on Custid of DataTable
ds.Tables[0].PrimaryKey = new DataColumn[] { ds.Tables[0].Columns["Custid"] };
}
public List<Customer> Customers_Select() {
List<Customer> customers = new List<Customer>();
foreach (DataRow dr in ds.Tables[0].Rows)
{
Customer obj = new Customer
{
Custid = Convert.ToInt32(dr["Custid"]),
Name = (string)dr["Name"],
Balance = Convert.ToDecimal(dr["Balance"]),
City = (string)dr["City"],
Status = Convert.ToBoolean(dr["Status"])
};
customers.Add(obj);
}
return customers;
}
public Customer Customer_Select(int Custid) {
//Finding a DataRow based on its Primary Key value
DataRow? dr = ds.Tables[0].Rows.Find(Custid);
Customer customer = new Customer
{
Custid = Convert.ToInt32(dr["Custid"]),
Name = Convert.ToString(dr["Name"]),
Balance = Convert.ToDecimal(dr["Balance"]),
City = Convert.ToString(dr["City"]),
Status = Convert.ToBoolean(dr["Status"])
};
return customer;
}
public void Customer_Insert(Customer customer) {
//Creating a new DataRow based on the DataTable structure
DataRow dr = ds.Tables[0].NewRow();
//Assigning values to each Column of the DataRow
dr["Custid"] = customer.Custid;

318
dr["Name"]= customer.Name;
dr["Balance"] = customer.Balance;
dr["City"] = customer.City;
dr["Status"] = customer.Status;
//Adding the new DataRow to DataTable
ds.Tables[0].Rows.Add(dr);
//Saving data back to XML file
ds.WriteXml("Customer.xml");
}
public void Customer_Update(Customer customer) {
//Finding a DataRow based on its Primary Key value
DataRow? dr = ds.Tables[0].Rows.Find(customer.Custid);
//Finding the Index of DataRow by calling IndexOf method
int Index = ds.Tables[0].Rows.IndexOf(dr);
//Overriding the old values in DataRow with new values based on the Index
ds.Tables[0].Rows[Index]["Name"] = customer.Name;
ds.Tables[0].Rows[Index]["Balance"] = customer.Balance;
ds.Tables[0].Rows[Index]["City"] = customer.City;
//Saving data back to XML file
ds.WriteXml("Customer.xml");
}
public void Customer_Delete(int Custid) {
//Finding a DataRow based on its Primary Key value
DataRow? dr = ds.Tables[0].Rows.Find(Custid);
//Finding the Index of DataRow by calling IndexOf method
int Index = ds.Tables[0].Rows.IndexOf(dr);
//Deleting the DataRow from DataTable by using Index
ds.Tables[0].Rows[Index].Delete();
//Saving data back to XML file
ds.WriteXml("Customer.xml");
}
}

Add a new Controller into Controllers folder naming it as “CustomerController” and write the below code in it:
using MVCDHProject.Models;
public class CustomerController : Controller
{
CustomerXmlDAL obj = new CustomerXmlDAL();
public ViewResult DisplayCustomers()
{
return View(obj.Customers_Select());
}
public ViewResult DisplayCustomer(int Custid)
{
return View(obj.Customer_Select(Custid));
}

319
public ViewResult AddCustomer()
{
return View();
}
[HttpPost]
public RedirectToActionResult AddCustomer(Customer customer)
{
obj.Customer_Insert(customer);
return RedirectToAction("DisplayCustomers");
}
public ViewResult EditCustomer(int Custid)
{
return View(obj.Customer_Select(Custid));
}
public RedirectToActionResult UpdateCustomer(Customer customer)
{
obj.Customer_Update(customer);
return RedirectToAction("DisplayCustomers");
}
public RedirectToActionResult DeleteCustomer(int Custid)
{
obj.Customer_Delete(Custid);
return RedirectToAction("DisplayCustomers");
}
}

Add a View to DisplayCustomers Action method and write the below code by deleting existing code over there:
@model IEnumerable<Customer>
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<table border="1" align="center" class="table-condensed">
<tr>
<th>@Html.DisplayNameFor(C => C.Custid)</th>
<th>@Html.DisplayNameFor(C => C.Name)</th>
<th>@Html.DisplayNameFor(C => C.Balance)</th>
<th>@Html.DisplayNameFor(C => C.City)</th>
<th>@Html.DisplayNameFor(C => C.Status)</th>
<th>Actions</th>
</tr>
@foreach (Customer customer in Model)
{
<tr>
<td align="center">@Html.DisplayFor(C => customer.Custid)</td>
<td>@Html.DisplayFor(C => customer.Name)</td>
<td>@Html.DisplayFor(C => customer.Balance)</td>
<td>@Html.DisplayFor(C => customer.City)</td>
<td align="center">@Html.DisplayFor(C => customer.Status)</td>

320
<td>
<a asp-action="DisplayCustomer" asp-route-Custid="@customer.Custid">View</a> &nbsp;
<a asp-action="EditCustomer" asp-route-Custid="@customer.Custid">Edit</a> &nbsp;
<a asp-action="DeleteCustomer" asp-route-Custid="@customer.Custid"
onclick="return confirm('Are you sure of deleting the record?')">Delete</a>
</td>
</tr>
}
<tr><td colspan="6" align="center"><a asp-action="AddCustomer">Add New Customer</a></td></tr>
</table>

Add a View to DisplayCustomer Action method and write the below code by deleting existing code over there:
@model Customer
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<table border="1" align="center">
<tr><td>Custid: </td><td>@Model.Custid</td></tr>
<tr><td>Name: </td><td>@Model.Name</td></tr>
<tr><td>Balance: </td><td>@Model.Balance</td></tr>
<tr><td>City: </td><td>@Model.City</td></tr>
<tr><td>Status: </td><td>@Model.Status</td></tr>
</table>
<div style="text-align:center">
<a asp-action="DisplayCustomers" align="center">Back to Customer Details</a>
</div>

Add a View to AddCustomer Action method and write the below code by deleting existing code over there:
@model Customer
<form asp-controller="Customer" asp-action="AddCustomer">
<div><label asp-for="Custid"></label><br /><input asp-for="Custid" /></div>
<div><label asp-for="Name"></label><br /><input asp-for="Name" /></div>
<div><label asp-for="Balance"></label><br /><input asp-for="Balance" /></div>
<div><label asp-for="City"></label><br /><input asp-for="City" /></div>
<div><label asp-for="Status"></label><br /><input asp-for="Status" /></div>
<div><input type="submit" value="Save" /><input type="reset" value="Reset" /></div>
<div><a asp-action="DisplayCustomers" align="center">Back to Customer Details</a></div>
</form>

Add a View to EditCustomer Action method and write the below code by deleting existing code over there:
@model Customer
<form asp-controller="Customer" asp-action="UpdateCustomer">
<div><label asp-for="Custid"></label><br /><input asp-for="Custid" readonly /></div>
<div><label asp-for="Name"></label><br /><input asp-for="Name" /></div>
<div><label asp-for="Balance"></label><br /><input asp-for="Balance" /></div>
<div><label asp-for="City"></label><br /><input asp-for="City" /></div>
<div><label asp-for="Status"></label><br /><input asp-for="Status" disabled /></div>

321
<div>
<input type="submit" value="Update" />
<a asp-action="DisplayCustomers" align="center">Cancel</a>
</div>
</form>

What is the Problem in the above implementation?


Ans: As we can see in the above “CustomerController” class, to get the Customer Data, Controller depends on
“CustomerXmlDAL” class. So, with-in the Controller class we have created the instance of “CustomerXmlDAL” class
and then invoking all the methods of that class as per our requirements. So, there is a tight coupling between
“CustomerController” class and “CustomerXmlDAL” classes. Tomorrow if there are multiple implementation to DAL
class then we need to change the name of DAL call in all the Controller classes where we used “CustomerXmlDAL”
because Controller and DAL are tightly coupled with each other.

Note: We can overcome this problem with the help of “Dependency Injection Design Pattern”.

What is Dependency Injection (DI) Design Pattern?


Ans: Dependency Injection is a process of injecting the instance of a class into another class that depends on it. The
Dependency Injection is the most used “Design Pattern” nowadays to remove the dependencies between the
instances and this allows us to develop loosely coupled software components.

Dependency Injection Pattern involves 3 types of classes:


 Client Class: The Client class is a class that depends on the Service class (Controller classes in our case).
 Service Class: The Service class is the Interface or Implementation Classes that provides services to the Client.
 Injector Class: The Injector class injects the Service class instance into the Client class (Program class).

Dependency Injection in ASP.NET Core: ASP.NET Core Framework is designed from scratch to provide in-built
support for Dependency Injection. ASP.NET Core Framework injects instances of dependency classes through
constructor or method or property by using a built-in IOC (Inversion of Control) container.

What are the advantages of using ASP.NET Core Dependency Injection?


Ans: ASP.NET Core Dependency Injection allows us to develop loosely coupled software components. Using ASP.NET
Core Dependency Injection, it is very easy to swap with a different implementation of a service.

What type of Services ASP.NET Core Dependency Injection provides to us?


Ans: there are two types of services that ASP.NET Core Dependency Injection provides us, those are:
1. Framework Services: services that are a part of ASP.NET Core Framework such as “IApplicationBuilder”,
“IConfiguration”, “IServiceCollection”, “ILoggerFactory”, “IWebHostEnvironment”, etc.
2. Application Services: these are services (custom types) which we as a programmer create for our application.

Note: To let the “IoC” container automatically inject our Application Services, we first need to register them with
the “IoC” container whereas Framework Services are already registered which can be directly injected.

How to register a Service with ASP.NET Core Dependency Injection Container?


Ans: We register a service with ASP.NET Core Dependency Injection Container within the “ConfigureServices”
method of the “Startup” class upto ASP.NET Core 5.0 and “Program” class from ASP.NET Core 6.0. Before we register

322
a Service with the Dependency Injection Container, it is important to understand the lifetime of a service, i.e., when
a client class receives the dependency instance through dependency injection, whether the instance it receives is
unique or not, depends on the lifetime of the service.

Setting the lifetime of the dependency instance determines how many times the dependency object needs
to be created and we are provided with 3 options to set the lifetime of the service, those are:
1. Singleton: in this case, the “IoC” container will create and share a single instance of a service object throughout
the application’s lifetime.
2. Scoped: in this case, the “IoC” container will create an instance of the specified service type once per request
and will be shared in a single request.
3. Transient: in this case, the “IoC” container will create a new instance of the specified service type every time
you ask for it (Single Call).

How to register a service with Dependency Injection Container?


Ans: ASP.NET Core Framework provides 3 extension methods to register a service with the ASP.NET Core
Dependency Injection Container and those methods will determine the lifetime of that service.
 AddSingleton<Interface, Class>() Or AddSingleton(type Interface, type Class)
 AddScoped<Interface, Class>() Or AddScoped(type Interface, type Class)
 AddTransient<Interface, Class>() Or AddTransient(type Interface, type Class)

Note: The built-in “IoC” container manages the lifetime of a registered service i.e., it automatically disposes the
service instance based on the specified lifetime.

AddSingleton: when we use this method to register a service, then it will create a singleton service which means a
single instance of that service is created and shared among all the components of the application that require it. This
instance is created when the first request comes to the service (one instance for all users).

AddScoped: when we use this method to register a service, then it will create a scoped service i.e., an instance of
the service is created once per each HTTP Request and uses that instance in other calls of the same request (one
instance for each request).

AddTransient: when we use this method to register a service, then it will create a transient service. It means a new
instance of the specified service is created each time when it is requested, and they are never shared (one instance
for each method call in a request).

When to use what?


Ans: In real-time, we need to register components such as Application-Wide Configuration as Singleton. Database
access classes like Entity Framework Contexts are recommended to be registered as Scoped so that the connection
can be re-used. If you want to run anything in Parallel, then it is better to register the component as Transient.

What are the different Types of Dependency Injections in .NET Core?


Ans: Injector class can inject the dependency objects (service class) into a client class in 3 different ways, those are:
1. Constructor Injection: when the Injector - injects the dependency object i.e., service class object/instance
through the client class constructor, then it is called Constructor Injection.
2. Property Injection: when the Injector injects the dependency object i.e., service class object/instance through
the public property of client class, then it is called as Property Injection or Setter Injection.
3. Method Injection: when the Injector injects the dependency object i.e., service class object/instance through a
public method of the client class, then it is called as Method Injection.

323
Note: we can also manually inject dependency object i.e., service into client class by implementing the below code:
var services = HttpContext.RequestServices;
var obj = (<Interface_Name>)services.GetService(typeof(<Interface_Name>));

To implement “Depdendency Injection” into our application i.e., “MVCDHProject” do the following:
Step 1: Define an interface under Model’s folder with the name “ICustomerDAL” and write the below code in it.
public interface ICustomerDAL {
List<Customer> Customers_Select();
Customer Customer_Select(int Custid);
void Customer_Insert(Customer customer);
void Customer_Update(Customer customer);
void Customer_Delete(int Custid);
}

Step 2: Go to “CustomerXmlDAL” class and make “ICustomerDAL” interface as its parent as following:
public class CustomerXmlDAL : ICustomerDAL

Step 3: Register the “Service Class” for “Dependency Injection” in “Startup class upto ASP.NET Core 5.0” or “Program
class from ASP.NET Core 6.0 and above” by calling any of the 3 register methods => “AddSingleton” or
“AddTransient” or “AddScoped” based on your requirement, by importing “MVCDHProject.Models” namespace:

ASP.NET Core 5.0: Write the below code in “Startup” Class under “ConfigureServices” Method:
services.AddSingleton<ICustomerDAL, CustomerXmlDAL>();
Or
services.AddScoped<ICustomerDAL, CustomerXmlDAL>();
Or
services.AddTransient<ICustomerDAL, CustomerXmlDAL>();

From ASP.NET Core 6.0: Write the below code in “Program” class just above the statement =>
var app = builder.Build();
builder.Services.AddSingleton<ICustomerDAL, CustomerXmlDAL>();
Or
builder.Services.AddScoped<ICustomerDAL, CustomerXmlDAL>();
Or
builder.Services.AddTransient<ICustomerDAL, CustomerXmlDAL>();

Note: for our application what we have been developing, “AddScoped” will be the best option because in Insert,
Update and Delete we have multiple methods getting executed in each request.

Step 4: Now go to “CustomerController” class and in top of the class we have created instance of “CustomerXmlDAL”
class, delete it and write the below code to perform Constructor Injection of Service over there:
private readonly ICustomerDAL obj;
public CustomerController(ICustomerDAL obj) {
this.obj = obj;
}
Note: after doing all the above changes run the Project again and check the output of all the Action Methods which
executes as is. Now we can start implementing the DAL Class logic targeting different Data Sources.

324
Implementing DAL Class targeting SQL Server
Now let’s implement a new DAL Class targeting SQL Server, and to do that let’s use Entity Framework Core
which is an extension to Entity Framework.

Entity Framework Core:


 This is the new version of Entity Framework after EF 6.x.
 It is open-source, lightweight, extensible and cross-platform version of Entity Framework data access
technology.
 Entity Framework is an Object/Relational Mapping (O/RM) Framework.
 EF Core is intended to be used with .NET Core applications. However, it can also be used with standard .NET
4.5+ Framework-based applications.
 EF Core is a complete re-write, compared to EF 6 but maximum all options of EF 6 are available in EF Core.

EF Core Development Approaches: EF Core supports only 2 development approaches.


1. Code-First
2. Database-First

 EF Core mainly targets Code-First approach and provides very limited support for Database-First approach
because the visual designer for DB Modeling is not supported.
 In Code-First approach, EF Core API creates Database and Tables using migrations, based on the conventions
and configuration provided in our domain classes. This approach is useful in Domain Driven Design (DDD).
 In Database-First approach, EF Core API creates Domain and Context classes based on our existing Database
using EF Core commands. This has limited support in EF Core as it doesn’t have Visual Designer or Wizard.

EF Core Vs EF 6: EF Core is a new and improved version of Entity Framework for .NET Core applications. EF Core
continues to support the following features and concepts, same as EF 6:
1. DbContext and DbSet
2. Data Model
3. Querying using Linq-to-Entities
4. Change Tracking
5. Save Changes
6. Migrations

EF Core will include most of the features of EF 6 gradually. However, there are some features of EF 6 which
are not supported in EF Core such as:
1. EDMX/Graphical Visualization of Model
2. Entity Data Model Wizard (for DB-First approach)
3. Automated Migration
4. Inheritance Strategies: Table per type (TPT) & Table per concrete class (TPC)
5. Many-to-Many without join entity
6. Lazy loading of related data
7. Stored procedure mapping with DbContext for CUD operation

EF Core includes the following new features which are not supported in EF 6:
1. Easy relationship configuration
2. Batch INSERT, UPDATE, and DELETE operations
3. In-memory provider for testing

325
4. Support for “IoC” (Inversion of Control)
5. Unique constraints
6. Shadow properties
7. Alternate keys
8. Global query filter
9. Field mapping
10. DbContext pooling and patterns for handling disconnected entity graphs

EF Core Database Providers (Libraries): Entity Framework Core uses provider model to access many different
Database’s. Entity Framework Core provides access too many Databases through plug-in libraries called Database
Providers and we need to install those providers as Nuget packages. List of available providers can be found at the
following location: https://docs.microsoft.com/en-us/ef/core/providers/?tabs=dotnet-core-cli

To work with Entity Framework Core in our applications we need to install the below 2 packages from NuGet:
 Microsoft.EntityFrameworkCore.Tools
 Microsoft.EntityFrameworkCore.SqlServer

Microsoft.EntityFrameworkCore.Tools: contains a set of types and tools for Scaffolding, using which we can perform
migrations. This is common for any Database we want to work with like SQL Server or Oracle or My SQL and this
package internally depends on another package: Microsoft.EntityFrameworkCore.Design.
 Microsoft.EntityFrameworkCore.Design: contains shared design-time components for Entity Framework Core
Tools.

Microsoft.EntityFrameworkCore.SqlServer: contains a set of types which are required to work with SQL Server
Database and this package internally depends on 2 other packages: Microsoft.EntityFrameworkCore.Relational and
Microsoft.Data.SqlClient.
 Microsoft.EntityFrameworkCore.Relational: contains all the types that are required in common to work with
any Relational Database.
 Microsoft.Data.SqlClient: contains all the types which are required to work with SQL Server Database.

To work with SQL Server using Entity Framework Core in our existing “MVCDHProject” application, perform
the below actions:
Step 1: Install the above 2 specified Nuget packages.
Step 2: Go to “Customer.cs” file and apply “Data Annotations” on it by importing the required namespaces:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Customer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Custid { get; set; }

[MaxLength(100)]
[Column(TypeName = "Varchar")]
public string Name { get; set; }

326
[Column(TypeName = "Money")]
public decimal? Balance { get; set; }

[MaxLength(100)]
[Column(TypeName = "Varchar")]
public string City { get; set; }

public bool Status { get; set; }


}

Step 3: Now add a new class in to the Models folder with the name “MVCCoreDbContext” and this class is our
“DbContext” and under this class write the below code:

using Microsoft.EntityFrameworkCore;
public class MVCCoreDbContext : DbContext
{
public MVCCoreDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<Customer> Customers { get; set; }
}

Note: the above class “MVCCoreDbContext” is not specifically configured to work with SQL Server Database, but was
designed generic to work with any Relational Database, so this is also loosely coupled with the Database we want to
work with. We need to now inject the information of Database we want to work with, thru the Injector class i.e.,
either Startup upto ASP.NET Core 5.0 or Program from ASP.NET Core 6.0.

Step 4: Open “appSettings.json” file and write the “ConnectionString” for connecting to SQL Server just below the
(“AllowedHosts”: “*”) statement, that should now look as following:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"ConStr": "Data Source=Server;User Id=Sa;Password=123;Database=MvcCoreDB;TrustServerCertificate=True"
}
}

Step 5: Because “MVCCoreDbContext” class is loosely coupled we need to register this class in Startup Class upto
ASP.NET Core 5.0 and Program Class from ASP.NET Core 6.0, to tell whether it has to connect with SQL Server or SQL
Lite or My SQL or Oracle or Postgre SQL or Cosmos Database’s, so that the Dependency Injection Container will tell

327
“MVCCoreDbContext” class to which Database it has to connect with, in runtime. To register the Context class, we
need to use “AddDbContext” method and to do that write the below code:

ASP.NET Core 5.0: go to “ConfigureServices” method of “Startup” class, import “Microsoft.EntityFrameworkCore”


namespace and write the below code:

services.AddDbContext<MVCCoreDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ConStr")));

ASP.NET Core 6.0 and above: go to “Program” class, import “Microsoft.EntityFrameworkCore” namespace and write
the below code just above the statement => var app = builder.Build();

builder.Services.AddDbContext<MVCCoreDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("ConStr")));

Note: “UseSqlServer” is an extension method under “DbContextOptionsBuilder” class which is added on install of
“Microsoft.EntityFrameworkCore.SqlServer” package; same as this when we install the “Oracle Provider” package it
will add another extension method with the name “UseOracle” and so on for other Databases.

Step 6: Add a class in Model’s folder naming it “CustomerSqlDAL” and implement the interface “ICustomerDAL” and
provide implementation to all the abstract methods of interface, targeting SQL Server Database.

public class CustomerSqlDAL : ICustomerDAL


{
private readonly MVCCoreDbContext context;
public CustomerSqlDAL(MVCCoreDbContext context)
{
this.context = context;
}
public List<Customer> Customers_Select()
{
var customers = context.Customers.Where(C => C.Status == true).ToList();
return customers;
}
public Customer Customer_Select(int Custid)
{
return context.Customers.Find(Custid);
}
public void Customer_Insert(Customer customer)
{
context.Customers.Add(customer);
context.SaveChanges();
}
public void Customer_Update(Customer customer)
{
customer.Status = true;

328
context.Update(customer);
context.SaveChanges();
}
public void Customer_Delete(int Custid)
{
Customer customer = context.Customers.Find(Custid);
customer.Status = false;
context.SaveChanges();
}
}
Note: in the above class we are using Dependency Injection to inject the Context class object thru the Constructor.

Step 7: We are using the Code First Approach in our application and we are not provided with Automatic Migrations
in EF Core, so we need to run few Scaffolding Commands to create the Database and Tables and to do that open
“Package Manager Console” and run the below commands 1 after the other.
PM> Add-Migration InitialMigration

The above command will create a folder under the project with the name “Migrations” and in the folder it
will create a file with the name “TimeStamp_InitialMigration.cs” and in this file we find “Create Table” and other
SQL Statements which must be executed on the Database, and to execute them run the below command:
PM> Update-Database //This command will create the Database and Table on SQL Server.

Step 8: Now go to Startup Class for ASP.NET Core 5.0 or Program Class for ASP.NET Core 6.0 and above, and change
the “Service Class Name” in the method where we registered the interface i.e., Service Class Name
“CustomerXmlDAL” should be changed to “CustomerSqlDAL”, as below:

ASP.NET Core 5.0:


services.AddSingleton<ICustomerDAL, CustomerSqlDAL>();
Or
services.AddTransient<ICustomerDAL, CustomerSqlDAL>();
Or
services.AddScoped<ICustomerDAL, CustomerSqlDAL>(); //Preferred

ASP.NET Core 6.0:


builder.services.AddSingleton<ICustomerDAL, CustomerSqlDAL>();
Or
builder.services.AddTransient<ICustomerDAL, CustomerSqlDAL>();
Or
builder.services.AddScoped<ICustomerDAL, CustomerSqlDAL>(); //Preferred

For our application “AddScoped” is the right option because we are dealing with Database Connections.
Now run the “CustomerController” and invoke the Action Methods to perform CRUD Operations, and the advantage
here is the same Controller and Views can be used now also without re-writing them again.

Migration in Entity Framework Core: Migration is a feature which keeps the Database schema in sync with our Entity
Classes by preserving data. EF Core API builds the EF Core Model from the Domain (Entity) Classes and EF Core

329
Migrations will create or update the Database schema based on EF Core Model. Whenever we change the Domain
Classes, you need to run Migration to keep the Database schema up to date. EF Core Migrations are a set of
commands that we can executed in “NuGet Package Manager Console” or in “Dotnet Command Line Interface”.

PMC Command Dotnet CLI Command


--------------------------------------------------------------------------------------------------------------------------------------------------------
Add-Migration <migration name> Add <migration name>
Usage: Creates a migration by adding a migration snapshot.

Remove-Migration Remove
Usage: Removes the last migration snapshot.

Update-Database Update
Usage: Updates the database schema based on the last migration snapshot.

Script-Migration Script
Usage: Generates a SQL script by using all the migration snapshots.

Adding a Migration: At the very first time, when we define the initial Domain Classes and there is no Database for
our Application then we need to create our first migration, to create the Database as well as whenever we change
our Domain Classes, we need to create a new migration to update the Database.

Package Manager Console: PM> Add-Migration InitialMigration


.NET CLI: <drive>:\<Personal Folder>\MVCDHProject\MVCDHProject> dotnet ef migrations Add InitialMigration

Note: in the above statements, “InitialMigration” is the name of Migration which will create a Migration folder with
2 files in it:

1. <timestamp>_<InitialMigration>.cs: this file includes migration operations in the Up() and Down() methods.
The Up() method includes code for creating Database Objects and Down() method includes code for dropping
Database objects.

2. <contextclassname>ModelSnapshot.cs: this is a snapshot of your current model which is used to determine


what is changed when creating the next migration.

Updating the Database: we use this command to create or update Database schema based on the Migration we
have created above.

Package Manager Console: PM> Update-Database

.NET CLI: <drive>:\<Personal Folder>\MVCDHProject\MVCDHProject> dotnet ef database Update

Note: This command will create the Database (if it is not existing) based on the Context, Domain Classes and the
Migration Snapshot, which is created using the “add-migration” or “add” commands. If this is the first migration, it
will also create a Table with the name “__EFMigrationsHistory”, which will store the names of all migrations that are
executed till now which are applied to the Database.

330
Removing a Migration: we can remove the last migration, provided it is not applied to the Database. Use the
following remove commands to remove the last created migration files which will revert the model snapshot.

Package Manager Console: PM> Remove-Migration

.NET CLI: <drive>:\<Personal Folder>\MVCDHProject\MVCDHProject> dotnet ef migrations Remove

Note: if the migration is already applied to Database, then it will throw an exception and displays below error
message:

The migration “<Migration Name>” has already been applied to the database. Revert it and try again. If the migration
has been applied to other databases, consider reverting its changes using a new migration instead.

Reverting a Migration: suppose we changed our domain classes and created a second migration with the name
“NewMigration1” using the “add-migration” command and applied that migration to Database using “Update
Command” but, for some reason, we want to revert or rollback the Database to its previous state then we need to
use the “Update-Database <migration name>” command to revert the Database to the specified previous migration
snapshot.

Package Manager Console: PM> Update-Database InitialMigration

.NET CLI: <drive>:\<Personal Folder>\MVCDHProject\MVCDHProject> dotnet ef database Update InitialMigration

The above command will revert the Database based on specified migration named “InitialMigration” and
removes all the changes applied for second migration named “NewMigration1”. This will also remove the entry from
the “__EFMigrationsHistory” table in the Database. But this will not remove the migration file related to
“NewMigration1”, so we need to use the Remove command and remove them from the project.

Generating a SQL Script: use this command to generate a SQL script for the database.

Package Manager Console: PM> script-migration


.NET CLI: <drive>:\<Personal Folder>\MVCDHProject\MVCDHProject> dotnet ef migrations script

The above command will include a script for all the migrations by default, and we can specify a range of
migrations also by using the “-to” and “-from” options.

Help Commands: Package Manager Console provides us a command called “get-help” using which we can get help
about any required topic.

Package Manager Console: PM> Get-Help EntityFramework

The above command will provide information about the “EF Core Commands” and same as this we can also
use “Get-Help” on each “EFCore” Commands as following:

Package Manager Console: PM> Get-Help Add-Migration

331
To try the above commands, do the following:
Step 1: Go to Customer class and add a new property in the class as below:
public string State { get; set; }

Step 2: Open Package Manager Console and create a new migration as below: PM> Add-Migration Update1

The above action will create a new migration file under “Migrations” folder with the name “<time
stamp>_Update1.cs” which contains an “Up” method for adding the new column and “Down” method for dropping
the column. The Snapshot file will contain the modifications that are made.

Step 3: Go to Customer class again and add a new property as below:


public string Country { get; set; }

Step 4: Open PMC and create a new migration as below: PM> Add-Migration Update2

The above action will create a new migration file under “Migrations” folder with the name “<time
stamp>_Update2.cs” which contains an “Up” method for adding the new column and “Down” method for dropping
the column. The Snapshot file will contain the modifications that are made.

Step 5: we can now use the Remove Migration command to remove the last created migration file as following at
Package Manager Console: PM> Remove-Migration

The above action will remove the last migration file i.e., “Update2” and this action will also update the
Snapshot file.

Step 6: let us apply “Update1” migration on the Database and to do that use the below command at Package
Manager Console: PM> Update-Database

The above action will update the last migration file i.e., “Update1” to the Database but the property
“Country” is not removed from the “Customer” class, which should be explicitly removed by us or we can even create
a new “Migration” for that property update.

Step 7: Open Package Manager Console and create a new migration as below: PM> Add-Migration Update2

The above action will create a new migration file under “Migrations” folder with the name “<time
stamp>_Update2.cs” which contains an “Up” method for adding the new column and “Down” method for dropping
the column. The Snapshot file will contain the modifications that are made.

Step 8: Go to Customer class again and add a new property as below:


public string Continent { get; set; }

Step 9: Open Package Manager Console and create a new Migration as below: PM> Add-Migration Update3

The above action will create a new migration file under “Migrations” folder with the name “<time
stamp>_Update3.cs” which contains an “Up” method for adding the new column and “Down” method for dropping
the column. The Snapshot file will contain the modifications that are made.

Step 10: Open Package Manager Console and update the Database as below: PM> Update-Database

332
The above action will update both Migrations to the Database i.e., “Update2” and “Update3” also, and we
can verify this by connecting to SQL Server and querying on the table: “__EFMigrationsHistory” which will show the
history of all migrations we have created till now.

Note: now if we try to use the “Remove-Migration” command it will throw an error as all the migrations are updated
to the Database and to test that go to Package Manager Console and use the below command:
PM> Remove-Migration

Rollback Migration: If we want to bring our Database Schema, back to its any state i.e., to any of the Migrations we
applied, we can revert to a migration and to do that, we need to use “Update-Database” command with the
“Migration Name” (you can get the name of Migration to where we want to rollback, from the
“__EFMigrationsHistory” table) we want to revert, and to test that go to Package Manager Console and use the
below command:
PM> Update-Database <time stamp value>_InitialMigration

The above action will roll back to “InitialMigration” and updates the table “__EFMigrationsHistory” but it
will not remove the Migration Files under the project and to remove them we need to use “Remove-Migration”
command for 3 times because each time it remove only 1 migration.

Note: these actions will not remove the properties we added in our Customer class, so go there and explicitly delete
them also.

Data Seeding: this is a process of populating Database-Tables with some initial data and to do that we need to
override “OnModelCreating” method in our “DataContext” class i.e., “MVCCoreDbContext”, and to test this process
write the below code in the class:

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Customer>().HasData(
new Customer { Custid = 101, Name = "Sai", Balance = 50000.00m, City = "Delhi", Status = true },
new Customer { Custid = 102, Name = "Sonia", Balance = 40000.00m, City = "Mumbai", Status = true },
new Customer { Custid = 103, Name = "Pankaj", Balance = 30000.00m, City = "Chennai", Status = true },
new Customer { Custid = 104, Name = "Samuels", Balance = 25000.00m, City = "Bengaluru", Status = true }
);
}

Note: generally, seed data is performed in the initial stages only i.e., the first time we create the Database then only
we will perform data seeding (preferably in initial migration).

Step 2: go to Package Manager Console and create a new migration as below:


PM> Add-Migration SeedData

Step 3: update the Database from Package Manager Console using the below statement:
PM> Update-Database

Note: This action will update the migration “SeedData” to the Database and inserts the 4 records into Table but
before updating the migration, go to the Database and delete if there are any existing records in the table.

333
Handling Errors in ASP.NET Core MVC Applications
In Web Applications we generally come across 2 different types of Errors:
1. Http Status Code Based Errors (4XX) => Client Errors
2. Exceptions (5XX) => Server Errors

Handling Client Errors: These errors occur if at all the request contains bad syntax or cannot be fulfilled. This category
of status codes is intended for situations in which the error seems to have been caused by client. For example, if we
try to send a request for a page which is not existing then it is “404; Not Found Error”. To handle these errors, MVC
Core provides us 3 Middle Wares and they are:

1. UseStatusCodePages
2. UseStatusCodePagesWithRedirects
3. UseStatusCodePagesWithReExecute

Note: to test these, first change the “ASPNETCORE_ENVIRONMENT” setting to “Production” in “launchSettings.json”
under “IIS Express” and “Kestrel Web Server” profile because by default it is “Development”.

To use these Middleware’s first let’s try to access a page which is not existing in the site, for example:
http://localhost:port/Customer/GetCustomer this will display an error page to the user which we generally see in
real-time when a resource was not found.

UseStatusCodePage: this Middleware component adds a “StatusCodePage” with a default response that displays
the “Status Code” and “Status Message”. To use the above Middleware, do the following actions in “Startup.cs” file
upto ASP.NET Core 5.0 and “Program.cs” file from ASP.NET Core 6.0:

Upto ASP.NET Core 5.0: go to “Startup.cs” file and change the existing code that is present under “Configure”
method of the class as below. Old code you find in the method will be as following:

if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
else {
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
Change it as below:
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
else {
app.UseStatusCodePages();
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

From ASP.NET Core 6.0: go to “Program.cs” file and change the existing code that is present under the class as below.
Old code you find over there will be as following:

334
if (!app.Environment.IsDevelopment()) {
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
Change it as below:
if (!app.Environment.IsDevelopment()) {
app.UseStatusCodePages();
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

Now try to access a page which is not existing again, but now we see the Error Page displaying the Status
Code and Status Message as following: “Status Code: 404; Not Found”.

UseStatusCodePagesWithRedirects: this Middleware specifies that the response should be handled by redirecting
to the given location URL template which may include “{0}” => Place Holder for Status Code. To use this Middleware,
do the following:

Step 1: Add a controller in our “MVCDHProject” naming it as “ErrorController” and write the below code in it by
deleting the existing code in the class:

[Route("ClientError/{StatusCode}")]
public IActionResult ClientErrorHandler(int StatusCode)
{
switch(StatusCode)
{
case 400:
ViewBag.ErrorTitle = "Bad Request";
ViewBag.ErrorMessage = "The server can’t return a response due to an error on the client’s end.";
break;
case 401:
ViewBag.ErrorTitle = "Unauthorized or Authorization Required";
ViewBag.ErrorMessage = "Returned by server when the target resource lacks authentication credentials.";
break;
case 402:
ViewBag.ErrorTitle = "Payment Required";
ViewBag.ErrorMessage = "Processing the request is not possible due to lack of required funds.";
break;
case 403:
ViewBag.ErrorTitle = "Forbidden";
ViewBag.ErrorMessage = "You are attempting to access the resource that you don’t have permission to view.";
break;
case 404:
ViewBag.ErrorTitle = "Not Found";
ViewBag.ErrorMessage = "The requested resource does not exist, and server does not know if it ever existed.";
break;

335
case 405:
ViewBag.ErrorTitle = "Method Not Allowed";
ViewBag.ErrorMessage = "Hosting server supports the method received, but the target resource doesn’t.";
break;
default:
ViewBag.ErrorTitle = "Client Error Occured";
ViewBag.ErrorMessage = "There is a Client-Error in the page, re-check the input you supplied.";
break;
}
return View("ClientErrorView");
}

Step 2: Add a new View in the Shared folder of our project naming it as “ClientErrorView” and write the below code
in it:

<h2 class="alert-danger">
Client Error Page - @ViewBag.ErrorTitle
</h2>
<p style="text-align:justify;font-size:large">
@ViewBag.ErrorMessage
</p>

Step 3: Go to “Startup.cs” or “Program.cs” file (based on the version you are targeting), comment the method
“UseStatusCodePages();” and in that place call the method “UseStatusCodePagesWithRedirects” as below:
app.UseStatusCodePagesWithRedirects("/ClientError/{0}");

In this case when we get any status code-based error or client error it will redirect to “ErrorController”
passing the “StatusCode” as a parameter and invokes the method “ClientErrorHandler” because we have defined a
route to “UseStatusCodePagesWithRedirects” method as “[Route("ClientError/{StatusCode}")]” and now
“ClientErrorHandler” method will launch the view i.e., “ClientErrorView” and displays the details of error.

Note: whenever a client error occurs “UseStatusCodePagesWithRedirects” Middleware will transfer the control to
browser with a redirection response (302) and then browser will send a new request to the action method with the
route “ClientError” and passes the status code 404 (in our case now) so that the URL in address bar gets updated to
http://localhost:port/ClientError/404. The drawback in this case is there is an extra round trip between the Browser
and Web Server.

UseStatusCodePagesWithReExecute: this Middleware specifies that the response body should be generated by re-
executing the request pipeline using an alternate path which may include “{0}” Placeholder for Status Code. We can
overcome the problem of “UseStatusCodePagesWithRedirects” with “UseStatusCodePagesWithReExecute”
Middleware, because in this case it will not perform a re-direction but transfers the control from 1 page to another
page directly on the server itself, so the URL in browsers address bar will not be updated i.e., it will be still showing
the original requested URL only. To test this, go to “Startup.cs” or “Program.cs” file (based on the version you are
targeting), comment the method call “UseStatusCodePagesWithRedirects” and call the new method
“UseStatusCodePagesWithReExecute” as following:
app.UseStatusCodePagesWithReExecute("/ClientError/{0}");

336
Handling Server Errors: to handle server errors we need to configure the middleware “UseExceptionHandler” and
specify the address where it has to be redirected when there is a server error. Currently in an “MVC Project” it is
already configured, so if we observe the code in Configure” method of Startup class (Upto ASP.NET Core 5.0) and
Program class (From ASP.NET Core 6.0) we notice the statement: “app.UseExceptionHandler("/Home/Error");”, and
right now this is already configured to invoke the “Error” action method of “Home” Controller, so whenever there is
a server error it will redirect to the Home Controller - Error Action method. To test this, go to “CustomerSqlDAL”
class and re-write “Customer_Select” method as below:

public Customer Customer_Select(int Custid) {


Customer customer = context.Customers.Find(Custid);
if (customer == null) {
throw new Exception("No customer exist's with given Custid.");
}
return customer;
}

Now send a request for DisplayCustomer action method with Customer-Id which is not existing as below:
https://localhost:port/Customer/DisplayCustomer?Custid=110

Note: the above request will now cause a Server Error (Exception) and redirects to Home Controller – Error Action
method and displays the corresponding View over there. If we want to handle the error on our own without using
the pre-defined code, do the following:

Step 1: Go to “Startup.cs” or “Program.cs” file (based on the version you are targeting), change the code which is
calling the method “UseExceptionHandler” as below, so that whenever there is an error without going to Home
Controller - Error Action method, it will redirect to the Action Method with the route name as “ServerError”:
app.UseExceptionHandler("/Home/Error"); => app.UseExceptionHandler("/ServerError");

Step 2: Go to “ErrorController” class and add the below action method in that class by importing the namespace
“Microsoft.AspNetCore.Diagnostics”:

[Route("ServerError")]
public IActionResult ServerErrorHandler() {
var ExceptionDetails = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
ViewBag.ErrorTitle = ExceptionDetails.Error.GetType().Name;
ViewBag.Path = ExceptionDetails.Path;
ViewBag.ErrorMessage = ExceptionDetails.Error.Message;
return View("ServerErrorView");
}
Note: The “ServerErrorHandler” action method is defined with the route as "ServerError" so it gets invoked when
there is a server error as we configured it in Startup Class (Upto ASP.NET Core 5.0) and Program Class (From ASP.NET
Core 6.0), which launches the view "ServerErrorView" by passing the details of the error thru ViewBag.

Step 3: Add a View in Shared folder, naming it as "ServerErrorView.cshtml" and write the below code in it:

<h2 class="align-content-xl-center alert-danger">Server Error Page - @ViewBag.ErrorTitle</h2>


<h4>There is a error at @ViewBag.Path, and the details of the error are:</h4>
<p style="text-align:justify;font-size:large;color:red">@ViewBag.ErrorMessage</p>

337
ASP.NET Core Identity Framework
It is an API that supports UI Login functionality by managing users, passwords, profile data, roles, tokens,
email confirmation, and more. Users can create an account with the login information stored in Identity or they can
use external login providers that include Facebook, Google, Microsoft, and Twitter Accounts. Identity is typically
configured using an SQL Server Database to store usernames, passwords, and profile data. Alternatively, another
persistent store can be used, for example, Azure Table Storage.

To work with ASP.NET Core Identity, do the following:


Step 1: Install “Microsoft.AspNetCore.Identity.EntityFrameworkCore” package by using NuGet Package Manager.

Step 2: Go to our context class i.e., “MVCCoreDbContext” and change the parent class of it from “DbContext” to
“IdentityDbContext” by importing “Microsoft.AspNetCore.Identity.EntityFrameworkCore” namespace and this
“IdentityDbContext” class internally inherits from “DbContext” class anyhow.

Step 3: In our “DbContext” class i.e., “MVCCoreDbContext” with-in the existing “OnModelCreating” method which
we have overridden earlier, write the below statement in top of the method, so that the base class i.e.,
“IdentityDbContext”, “OnModelCreating” method also gets executed, and we need to do this call because there is
some logic implemented in the parent class for setting “IdentityUserLogin” model’s key property:
base.OnModelCreating(modelBuilder);

Step 4: Register “IdentityFramework” in our application by importing “Microsoft.AspNetCore.Identity” namespace:

Upto ASP.NET Core 5.0: Go to “Startup.cs” file, and write the below code under “ConfigureServices” method:

services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<MVCCoreDbContext>();

From ASP.NET Core 6.0: Go to “Program.cs” file, and write the below code just above the statement:
“var app = builder.Build();”

builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<MVCCoreDbContext>();

Step 5: Add Authentication Middleware to request pipeline using the below statement:
app.UseAuthentication();

Upto ASP.NET Core 5.0: Go to “Startup.cs” file, and write the above statement in “Configure” method between
“UseRouting” and “UseAuthorization” Middleware’s.

From ASP.NET Core 6.0: Go to “Program.cs” file, and write the above statement between “UseRouting” and
“UseAuthorization” Middleware’s:

Step 6: Now open Package Manager Console and create a new Migration as below:
PM> Add-Migration AddIdentity

Step 7: Update the new migration i.e., “AddIdentity” as below, so that all the required Tables gets created on our
Database i.e., “MVCCoreDb”:
PM> Update-Database

338
Step 8: Now under the Models folder define the below classes:

using System.ComponentModel.DataAnnotations;
public class UserViewModel
{
[Required]
public string? Name { get; set; }

[Required]
[DataType(DataType.Password)]
public string? Password { get; set; }

[DataType(DataType.Password)]
[Display(Name = "Confirm Password")]
[Compare("Password", ErrorMessage = "Confirm password should match with password.")]
public string? ConfirmPassword { get; set; }

[Required]
[EmailAddress]
[Display(Name = "Email Id")]
public string? Email { get; set; }

[Required]
[RegularExpression("[6-9]\\d{9}", ErrorMessage = "Mobile No. Is Invalid")]
public string? Mobile { get; set; }
}

using System.ComponentModel.DataAnnotations;
public class LoginViewModel
{
[Required]
public string? Name { get; set; }

[Required]
[DataType(DataType.Password)]
public string? Password { get; set; }

[Display(Name = "Remember Me")]


public bool RememberMe { get; set; }
}

Step 9: Now under the Controllers folder add a new controller with the name “AccountController”, delete the
existing Index Action method in it and write the below code:

using MVCDHProject.Models;
using Microsoft.AspNetCore.Identity;

339
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> userManager;
private readonly SignInManager<IdentityUser> signInManager;
public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
{
this.userManager = userManager;
this.signInManager = signInManager;
}

public IActionResult Register()


{
return View();
}
[HttpPost]
public async Task<IActionResult> Register(UserViewModel userModel)
{
if (ModelState.IsValid)
{
//IdentityUser represents a new user with a given set of attributes
IdentityUser identityUser = new IdentityUser { UserName = userModel.Name, Email = userModel.Email,
PhoneNumber = userModel.Mobile };
//Creates a new user and returns a result which tells about success or failure
var result = await userManager.CreateAsync(identityUser, userModel.Password);
if (result.Succeeded)
{
//Performing a Sign-In into the appliction
await signInManager.SignInAsync(identityUser, false);
return RedirectToAction("Index", "Home");
}
else
{
foreach (var Error in result.Errors)
{
//Displaying error details to the user
ModelState.AddModelError("", Error.Description);
}
}
}
return View(userModel);
}
}

UserManager class provides options for managing users in a persistence store.


IdentityUser class represents a user in the identity system.
SignInManager class provides options for user sign in.

340
Adding a Register View: right click on the Register action method in the “AccountController” class, select “Add
View”, in the window opened select “Razor View”, click “Add” button, in the window opened, select Template as
“Create”, Model Class as “UserViewModel (MVCDHProject.Models)” and click on the “Add” button which will create
a View with the name “Register.cshtml”. After the View is created, make any changes in the design (if required) and
then run the view to register new users.

Note: When we want to create a new user-account a set of rules are pre-defined on Username and Password, under
2 classes: “UserOptions” and “PasswordOptions”.

“UserOptions” class defines options for user validations and in this class, there is a property
“AllowedUserNameCharacters” which contains the list of allowed characters for the “Username” and in this the code
is as following:

public class UserOptions


{
public string AllowedUserNameCharacters { get; set; } =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
public bool RequireUniqueEmail { get; set; }
}

“PasswordOptions” class defines options for password validations and in this class, there are properties like
RequiredLength, RequiredDigit, RequiredLowerCase, RequiredUpperCase, etc. to validate the password, and in this
class the code is as following:

public class PasswordOptions


{
public int RequiredLength { get; set; } = 6;
public int RequiredUniqueChars { get; set; } = 1;
public bool RequireNonAlphanumeric { get; set; } = true;
public bool RequireLowercase { get; set; } = true;
public bool RequireUppercase { get; set; } = true;
public bool RequireDigit { get; set; } = true;
}
We can override these options as per our requirements and we need to do that in “Startup.cs” file upto
ASP.NET Core 5.0 and “Program.cs” file from ASP.NET Core 6.0. For example, if we want to set the “RequiredLength”
as 8 characters and “RequireDigit” as false do the following:

ASP.NET Core 5.0: go to “Startup.cs” file and re-write the “Services.AddIdentity” method as following:

Old Code:
services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<MVCCoreDbContext>();

New Code:
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;

341
options.Password.RequireDigit = false;
}).AddEntityFrameworkStores<MVCDbContext>();

ASP.NET Core 6.0 and above: go to “Program.cs” file and re-write the “builder.Services.AddIdentity” method as
following:

Old Code:
builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<MVCCoreDbContext>();

New Code:
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireDigit = false;
}).AddEntityFrameworkStores<MVCCoreDbContext>();

Step 10: Implementing “Login Action”, and to do that go to “AccountController” class and add the below 2 Action
Methods in the class:

public IActionResult Login()


{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel loginModel)
{
if(ModelState.IsValid)
{
var result = await signInManager.PasswordSignInAsync(loginModel.Name, loginModel.Password,
loginModel.RememberMe, false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Invalid login credentials.");
}
}
return View(loginModel);
}

Add a View to Login Action method and to do that, right click on Login method in the Controller class, select
“Add View”, in the window opened select “Razor View”, click on “Add” button, in the window opened select
Template as “Create”, Model Class as “LoginViewModel (MVCDHProject.Models)” and click on the “Add” button
which will create a View with the name “Login.cshtml”. Make any necessary changes to the View (if required) and
run it to Login into the application with the user accounts you have registered.

342
Providing Login, Register and Logout links: Let’s provide links for Login and Register if the user is not signed-in and
if signed-in, lets display Username and Logout links on the top of every page and to do that do the following:

i. Open “_ViewImports.cshtml” file that is present in “Views” folder and write the below statement in it:
@using Microsoft.AspNetCore.Identity

ii. Open “_Layout.cshtml” file that is present in the “Shared” folder of “Views” folder and write the below statement
on top of the file to inject “SignInManager”:
@inject SignInManager<IdentityUser> signInManager

iii. In “_Layout.cshtml” file, we find a “<div>” tag with an un-ordered list containing links for “Home” and “Privacy”
Views and with-in that “<ul>” add 1 more “<li>” to the existing 2 “<li>'s” to display a link for Managing Customers:

<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Customer" asp-action="DisplayCustomers">Customers</a>
</li>

Now after the “</ul>” tag with-in the same “<div>” tag write the below code to add Login, Logout and
Register links on the RHS:

<ul class="navbar-nav ml-auto">


@if (signInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark">@User.Identity.Name</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Account" asp-action="Logout">Logout</a>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Account" asp-action="Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Account" asp-action="Login">Login</a>
</li>
}
</ul>

Step 11: Implementing Logout Action, and to do that go to “AccountController” class and add the below action
method over there:

public async Task<IActionResult> Logout()


{

343
await signInManager.SignOutAsync();
return RedirectToAction("Login");
}

Authorization: this refers to the process that determines what a user can do. For example, in a Library Management
Application an administrative user can create a document library, add documents, edit documents, and delete them.
A non-administrative user working with the library is only authorized to read the documents. Authorization is
independent from authentication. However, authorization requires an authentication mechanism. Authentication is
the process of ascertaining who a user is. Now let’s implement authorization in our application, so that only logged-
in users can perform Edit, Insert and Delete operations on Customer, whereas all other users can View the Customers
data. To implement this, we have 2 options:

Option 1: Authorize Attribute - by using Authorize attribute we can specify that this action method is accessible only
to authorized users and to test that, go to Customer Controller class and on top of “AddCustomer” (Get Method),
“EditCustomer” and “DeleteCustomer” add the Authorize attribute as following by importing
“Microsoft.AspNetCore.Authorization” namespace:

[Authorize]
public ViewResult AddCustomer()

[Authorize]
public ViewResult EditCustomer(int Custid)

[Authorize]
public RedirectToActionResult DeleteCustomer(int Custid)

Note: Now run the application and try to access the above 3 action methods without signing into the application,
which will redirect you to Login Page.

Without using Authorize attribute on each action method we can use it directly on the Controller class also,
so that all Action methods in the class can be accessed only by Authorizing and in this case if we want to provide
Anonymous access to any of the methods in that Controller class we need to use “AllowAnonymous” attribute on
those methods.

To test this comment or delete Authorize attribute we used on the 3 action methods and apply the
Authorize attribute on Controller class as well as on the top of “DisplayCustomer” and “DisplayCustomers” action
methods use “AllowAnonymous” attributes as following:

[Authorize]
public class CustomerController : Controller

[AllowAnonymous]
public ViewResult DisplayCustomers()

[AllowAnonymous]
public ViewResult DisplayCustomer(int Custid)

344
Note: “AllowAnonymous” attribute by passes all authorization statements i.e., if we combine “AllowAnonymous”
and “Authorize” attributes, then “Authorize” attribute is ignored. For example, if you apply “AllowAnonymous” at
Controller level, any “Authorize” attributes on that Controller’s action methods will be ignored.

Option 2: if we want to apply authorization on all the controllers in the project, then without applying it on each and
every controller we can do that in “Startup.cs” file for ASP.NET Core 5.0 and “Program.cs” file for ASP.NET Core 6.0
and above and to do that, first import the 2 namespaces: “Microsoft.AspNetCore.Authorization” and
“Microsoft.AspNetCore.Mvc.Authorization”, and re-write the statement “services.AddControllersWithViews()” as
below:

ASP.NET Core 5.0: go to “Startup.cs” file and re-write the code of “AddControllersWithViews” method that is present
under “ConfigureServices” method as below:

Old Code:
Services.AddControllersWithViews();

New Code:
services.AddControllersWithViews(configure =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
configure.Filters.Add(new AuthorizeFilter(policy));
});

ASP.NET Core 6.0 and above: go to “Program.cs” file and re-write the code of “AddControllersWithViews” method
that is present above the statement => “var app = builder.Build();” as below:

Old Code:
builder.Services.AddControllersWithViews();

New Code:
builder.Services.AddControllersWithViews(configure =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
configure.Filters.Add(new AuthorizeFilter(policy));
});

With this change, now any Controller in the project will not run because we enabled Authentication
application level i.e., Home Controller, Error Controller and Account Controller also will not run, and to over the
problem add “AllowAnonymous” attribute on the top of these 3 Controller classes by importing
“Microsoft.AspNetCore.Authorization” namespace:

[AllowAnonymous]
public class HomeController : Controller
[AllowAnonymous]
public class ErrorController : Controller
[AllowAnonymous]
public class AccountController : Controller

345
Return URL: after bringing Authentication into picture if we try to open any of the secured resource it will first open
Login View to Login, but after the Login process is completed it will take us to Index action of Home controller but
not to the View we have selected and to overcome this problem, when we are being re-directed to Login Page from
any secure resource then the “URL” will contain the address of the page to where it has to be redirected after Login,
and we find it with the Key-Name “ReturnUrl”, so we can use this “Return-URL” for redirecting back to the original
View we requested after a successful Login and to do that make the below changes:

Step 1: Go to “LoginViewModel.cs” and add a new property in the Model class to read the Return-URL as below:
public string ReturnUrl { get; set; } = "";

Step 2: Go to “Login.cshtml” and read the “ReturnUrl” which is present in the form of “Query String” and to do that,
do the following change on the top of the page:

Old Code:
@
{
ViewData["Title"] = "Login";
}

New Code:
@
{
ViewData["Title"] = "Login";
var returnUrl = Context.Request.Query["ReturnUrl"];
}

Step 3: Now pass the “returnUrl” value to Login’s Post Action Method as a route and to that, change the code of
“<form>” tag as following:

Old Code:
<form asp-action="Login">

New Code:
<form asp-action="Login" asp-route-ReturnUrl="@returnUrl">

Step 4: In the Login’s Post Action Method of Account Controller change the code under “Succeeded” condition as
below:

Old Code:
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Invalid login credentials.");
}

346
New Code:
if (result.Succeeded)
{
if (string.IsNullOrEmpty(loginModel.ReturnUrl))
return RedirectToAction("Index", "Home");
else
return LocalRedirect(loginModel.ReturnUrl);
}
else
{
ModelState.AddModelError("", "Invalid login credentials.");
}
Note: Now run the application and watch the difference.

Email Confirmation: this is quite an important part of the user registration process. It allows us to verify the
registered user is indeed an owner of the provided email.

Why email confirmation is important?


Ans: let’s imagine a scenario where two users with similar email addresses want to register in our application, for
example “Rajann” registers first with “[email protected]” instead of “[email protected]” which is his actual address
and without email confirmation, this registration will execute successfully. Now, “Rajan” comes to registration page
and tries to register with his email “[email protected]” and our application will return an error that the user with
that email is already registered. So, thinking that he already has an account, he just resets the password and
successfully logs in to the application. We can understand with this now where this could lead, and what problems
it could cause.

To overcome this problem, it is a good practice to ask a user to confirm the email after registration and to
implement this in our application do the following changes:

Step 1: Add a new View in the Shared folder of Views folder with the name “DisplayMessages.cshtml”, to display
any information or error messages to the end users, and write the below code in it deleting the existing content:

<h1 class="bg-info text-white">@TempData["Title"]</h1>


<div class="container">
<p class="text-justify text-primary">@TempData["Message"]</p>
</div>

Step 2: Go to Register Post Action Method in Account Controller class and re-write the code under the “Succeeded”
condition as following:

Old Code:
if (result.Succeeded)
{
//Code implemented for an automatic Sign-In after the registration is complete.
await signInManager.SignInAsync(identityUser, false);
return RedirectToAction("Index", "Home");
}

347
New Code:
if (result.Succeeded)
{
//Implementing logic for sending a mail to confirm the Email
var token = await userManager.GenerateEmailConfirmationTokenAsync(identityUser);
var confirmationUrlLink = Url.Action(
"ConfirmEmail", "Account", new { UserId = identityUser.Id, Token = token }, Request.Scheme);
//Passing the information to SendMail method to send the Mail
SendMail(identityUser, confirmationUrlLink, "Email Confirmation Link");
TempData["Title"] = "Email Confirmation Link";
TempData["Message"] = "A confirm email link has been sent to your registered mail, click on it to confirm.";
return View("DisplayMessages");
}

Step 3: To send an Email from our application, first install “MailKit” package from NuGet Package Manager and then
in the Account Controller class import the namespaces “System.Text”, “MimeKit” and “MailKit.Net.Smtp”, and add
a new method in the class for sending an Email as following:

public void SendMail(IdentityUser identityUser, string requestLink, string subject)


{
StringBuilder mailBody = new StringBuilder();
mailBody.Append("Hello " + identityUser.UserName + "<br /><br />");
if (subject == "Email Confirmation Link") {
mailBody.Append("Click on the link below to confirm your email:");
}
else if (subject == "Change Password Link") {
mailBody.Append("Click on the link below to reset your password:");
}
mailBody.Append("<br />");
mailBody.Append(requestLink);
mailBody.Append("<br /><br /> ");
mailBody.Append("Regards");
mailBody.Append("<br /><br />");
mailBody.Append("Customer Support.");

BodyBuilder bodyBuilder = new BodyBuilder();


bodyBuilder.HtmlBody = mailBody.ToString();

MailboxAddress fromAddress = new MailboxAddress("Customer Support", "<Use your Email Id here>");


MailboxAddress toAddress = new MailboxAddress(identityUser.UserName, identityUser.Email);

MimeMessage mailMessage = new MimeMessage();


mailMessage.From.Add(fromAddress);
mailMessage.To.Add(toAddress);
mailMessage.Subject = subject;
mailMessage.Body = bodyBuilder.ToMessageBody();

348
SmtpClient smtpClient = new SmtpClient();
smtpClient.Connect("smtp.gmail.com", 465, true);
smtpClient.Authenticate("<Use your Email Id here>", "<Generate an App Password and use it here>");
smtpClient.Send(mailMessage);
}

Note: to send mails from your Gmail Account first you need to go to “Manage your Google Account” => Select
“Security” tab => scroll down to “Signing in to Google” => under that set the “2-Step Verification” property value as
“On” and configure it. Search for “App passwords” which open a window asking for an App Name, enter some name
in the TextBox over there for example “TestApp” and click on Create button which displays a “16-character
Password”, use this password in your application as password for the Email.

Step 4: To generate token for Email Confirmation, Change Email and Reset Password, etc. we need to register a
default Token Provider in by calling “AddDefaultTokenProviders” method under “Startup.cs” file upto ASP.NET Core
5.0 and “Program.cs” file from ASP.NET Core 6.0 as following:

ASP.NET Core 5.0: go to “Startup.cs” file and change the code of “services.AddIdentity” method which is present in
“ConfigureServices” method as below:

Old Code:
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireDigit = false;
}).AddEntityFrameworkStores<MVCCoreDbContext>();

New Code:
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireDigit = false;
}).AddEntityFrameworkStores<MVCCoreDbContext>().AddDefaultTokenProviders();

ASP.NET Core 6.0 and above: go to “Program.cs” file and change the code of “builder.Services.AddIdentity” method
which is present above the statement => “var app = builder.Build();” as below:

Old Code:
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireDigit = false;
}).AddEntityFrameworkStores<MVCCoreDbContext>();

New Code:
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
{

349
options.Password.RequiredLength = 8;
options.Password.RequireDigit = false;
}).AddEntityFrameworkStores<MVCCoreDbContext>().AddDefaultTokenProviders();

After doing all the above changes whenever a new user registers, then a mail is generated and sent to his
registered mail with mail confirmation link that contains an Email Confirmation Token and User Id. Token is a unique
“ID” value that is generated for email confirmation, change email and change password, to identify the user when
he clicks on the link.

Step 5: Now with-out confirming the email a user should not be allowed to login into the application and to that, go
to Post Action of Login Method which is present in “AccountController” class and add the below code in top of the
if condition i.e., inside “if (ModelState.IsValid)” condition:

//Code to check whether Email is confirmed or not


var user = await userManager.FindByNameAsync(loginModel.Name);
if (user != null && (await userManager.CheckPasswordAsync(user, loginModel.Password)) &&
user.EmailConfirmed == false)
{
ModelState.AddModelError("", "Your email is not confirmed.");
return View(loginModel);
}

Step 6: Now when the user clicks on the Confirmation Link in his mail it will redirect to “ConfirmEmail” action method
of Account Controller class, so let’s define “ConfirmEmail” Action Method in Account Controller as following:

public async Task<IActionResult> ConfirmEmail(string userId, string token)


{
if(userId != null && token != null)
{
var User = await userManager.FindByIdAsync(userId);
if(User != null)
{
var result = await userManager.ConfirmEmailAsync(User, token);
if(result.Succeeded)
{
TempData["Title"] = "Email Confirmation Success.";
TempData["Message"] = "Email confirmation is completed. You can now login into the application.";
return View("DisplayMessages");
}
else
{
StringBuilder Errors = new StringBuilder();
foreach (var Error in result.Errors)
{
Errors.Append(Error.Description + "<br />");
}

350
TempData["Title"] = "Confirmation Email Failure";
TempData["Message"] = Errors.ToString();
return View("DisplayMessages");
}
}
else
{
TempData["Title"] = "Invalid User Id.";
TempData["Message"] = "User Id which is present in confirm email link is in-valid.";
return View("DisplayMessages");
}
}
else
{
TempData["Title"] = "Invalid Email Confirmation Link.";
TempData["Message"] = "Email confirmation link is invalid, either missing the User Id or Confirmation Token.";
return View("DisplayMessages");
}
}

Implementing Password Reset Functionality: Now let’s implement password reset functionality in our application
and for that, to do the following:

Step 1: Go to “Login.cshtml” and add links for Register and Forgot Password, just above the “</form>” tag as below:
<div class="form-group">
New user? <a asp-action="Register">Click</a> to register? <br />
Forgot password? - <a asp-action="ForgotPassword">Click</a> to reset.
</div>

Step 2: Add a new Model class in Model’s folder, naming it as “ChangePasswordViewModel.cs” and write the below
code in the class:
using System.ComponentModel.DataAnnotations;
public class ChangePasswordViewModel
{
[Required]
[Display(Name = "User Name")]
[RegularExpression("[A-Za-z0-9-._@+]*")]
public string Name { get; set; }
}

Step 3: Go to “AccountController” class and write the below Action Methods in the class:
[HttpGet]
public IActionResult ForgotPassword()
{
return View();
}

351
[HttpPost]
public async Task<IActionResult> ForgotPassword(ChangePasswordViewModel model)
{
if(ModelState.IsValid)
{
var User = await userManager.FindByNameAsync(model.Name);
if (User != null && await userManager.IsEmailConfirmedAsync(User))
{
var token = await userManager.GeneratePasswordResetTokenAsync(User);
var confirmationUrlLink = Url.Action("ChangePassword", "Account", new { UserId = User.Id, Token = token },
Request.Scheme);
SendMail(User, confirmationUrlLink, "Change Password Link");
TempData["Title"] = "Change Password Link";
TempData["Message"] = "Change password link has been sent to your mail, click on it and change password.";
return View("DisplayMessages");
}
else
{
TempData["Title"] = "Change Password Mail Generation Failed.";
TempData["Message"] = "Either the Username you have entered is in-valid or your email is not confirmed.";
return View("DisplayMessages");
}
}
return View(model);
}
Now add a View to “ForgotPassword” action method and to do that, choose Razor View in Scaffold Page,
click “Add” button, under Template select “Create”, under Model Class select “ChangePasswordViewModel” and
click on “Add” button. Run the View; enter your “Username” to receive a reset password mail. After receiving the
mail, user can click on the link to change the password and to perform that we need to define “ResetPassword”
Action method.

Step 4: Add another Model class in Model’s folder, naming it as “ResetPasswordViewModel.cs” and write the below
code in it:

using System.ComponentModel.DataAnnotations;
public class ResetPasswordViewModel
{
[Required]
public string UserId { get; set; }

[Required]
public string Token { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

352
[Display(Name = "Confirm Password")]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "Confirm password should match with password.")]
public string ConfirmPassword { get; set; }
}

Step 5: Go to “AccountController” class and write the below Action Methods in that class:
public IActionResult ChangePassword()
{
return View();
}
[HttpPost]
public async Task<IActionResult> ChangePassword(ResetPasswordViewModel model)
{
if (ModelState.IsValid)
{
var User = await userManager.FindByIdAsync(model.UserId);
if (User != null)
{
var result = await userManager.ResetPasswordAsync(User, model.Token, model.Password);
if (result.Succeeded)
{
TempData["Title"] = "Reset Password Success";
TempData["Message"] = "Your password has been reset successfully.";
return View("DisplayMessages");
}
else {
{
foreach (var Error in result.Errors)
ModelState.AddModelError("", Error.Description);
}
}
else {
TempData["Title"] = "Invalid User";
TempData["Message"] = "No user exists with the given User Id.";
return View("DisplayMessages");
}
}
return View(model);
}

Now add a View to “ChangePassword” action method, choose Razor View in Scaffold Page, click “Add”,
under Template select “Create”, under Model Class select “ResetPasswordViewModel” and click on “Add” button.
This view gets launched when we user clicks on the “Reset Password Email Link” he has received, and that link
contains 2 “Query String” values “UserId & Token”, and we need to read the values of them into our page and to do
that modify the code on the top of the view as following:

353
Old Code:
@{
ViewData["Title"] = "ResetPassword";
}

New Code:
@{
ViewData["Title"] = "ResetPassword";
var UserId = Context.Request.Query["UserId"];
var Token = Context.Request.Query["Token"];
}

Note: In the current view, it will provide “Textbox’s” for entering “User Id & “Token” values, but we are not going to
enter those values because those values came to the View as “Query Strings”, when the user clicks on the link that
is sent to his email, so delete the 2 “<div>” tags containing controls for entering “User Id” and “Token”. Now we
need to bind “User Id & Token” values we have captured, to the Model in the form of “route-values” and to do those
change the code of “<form>” tag as following:

Old Code:
<form asp-action="ResetPassword">

New Code:
<form asp-action="ResetPassword" asp-route-userId="@UserId" asp-route-token="@Token">

Implementing Open Authentication: open authentication is a process of adding an option of authenticating a User
by using external login providers like Google, Facebook, Microsoft, and Twitter.

Implementing Google and Facebook Authentication: to implement Google and Facebook authentication in our
application do the following:

Step 1: Re-write the code in “Login.cshtml” as following:


@model MVCDHProject.Models.LoginModel
@{
ViewData["Title"] = "Login";
var returnUrl = @Context.Request.Query["ReturnUrl"];
}
<h1>Login With</h1>
<hr />
<div class="row">
<div class="col-md-6">
<h3>NIT Account</h3>
<hr />
<form asp-action="Login" asp-route-ReturnUrl="@returnUrl">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />

354
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="RememberMe" />
@Html.DisplayNameFor(model => model.RememberMe)
</label>
</div>
<div class="form-group">
<input type="submit" value="Login" class="btn btn-primary" />
<input type="reset" value="Reset" class="btn btn-primary" />
</div>
<div class="form-group">
New user? <a asp-action="Register">Click</a> to register?
<br />
Forgot password? - <a asp-action="ForgotPassword">Click</a> to reset.
</div>
</form>
</div>
<div class="col-md-6">
<h3>Google or Facebook</h3>
<hr />
<form asp-action="ExternalLogin" asp-route-returnUrl="@returnUrl">
<input type="submit" name="Provider" value="Google" class="btn btn-primary" />
<input type="submit" name="Provider" value="Facebook" class="btn btn-primary" />
</form>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Step 2: Register our application under Google => to work with Google, first we need to register our application with
Google and to do that open the site https://console.cloud.google.com and login with your credentials. Now click on
Create Project => in the window opened enter project name as “NIT Customer Management” and click on Create
button which creates a new project. Now go to “Navigation Menu” which is present in LHS, on the top and select
“APIs and Services” => “Library” => now in the window opened Search for “Google+ Api” which opens a new window,
in that click on “Google+ Api” and then click on Enable button.

Now in the LHS top we find “Google+ API” and above it we find “APIs and Services” click on it which displays
the options below, select “OAuth consent screen” in RHS and click on Get Started button => which will display a

355
screen and asks for “App Name”, enter the name as “NIT Customer Management”, click on Next Button and choose
External Radio Button, click on Next Button and enter an Email Id: “<enter your email id here>”, under Contact
Information, click on Next Button select the Check Box to accept the terms and click Continue & Create button’s.

Goto Navigation Menu again, under Api’s & Services choose “Credentials” and click on “Create Credentials”
on the top and select “OAuth Client Id” in the provided list, and then choose “Application Type” as “Web
Application”, give a name to it, for example: “NIT Client”, and then under “Authorized Java Script Origins”, click on
“+Add URI” option and specify the URI for the home page of our site: http://localhost:port. Now scroll down to
Authorized redirect URIs option click on “+Add URI” option and specify the redirect URI as shown:
“YourSiteURI/signin-google” for example: https://localhost:YourPortNo/signin-google and click on the Create button
which opens a window and in that it will display Client ID and Client Secret, copy and save them because we need to
use those values in our Web Application.

Note: to get URI of our site’s run the project and copy the URL from Address Bar. E.g.: https://localhost:PortNo

Step 3: Registering our application under Facebook => open the site https://developers.facebook.com and login with
your credentials. Now in the RHS top, click on MyApps Menu, which opens a window click on the button Create App,
which opens another window and in that enter App Name for, as “NIT Customer Management”, enter App Contact
Email, click Next and in the window opened Choose Other Radio Button, click Next and in the window opened Choose
Consumer Radio Button, click Next and click on Create App button which will create the app and opens App
Dashboard.

Now in the App Dashboard click on the Setup button under Facebook Login, which will ask to Select the
platform for this app., choose Web which will ask for site URL enter it as shown: “YourSiteURI/signin-facebook”, for
example: https://localhost:YourPortNo/signin-facebook and click on “Save”.

Now click on Facebook Login in LHS and under that choose Settings, now on the RHS select the option to
configure the client OAuth Login, which is already selected Yes, so leave the same and under Valid OAuth Redirect
URL’s enter the URL as “YourSiteURL/signin-facebook” and click on Save Changes Button. Now in the LHS on the top
we find App Settings option, expand it and under it choose Basic which will display “App Id” and “App Secret” in RHS,
copy and save because we need to use them in our application.

Now to take your app live we need to provide a privacy policy which should be generated at the following
site: https://www.termsfeed.com. Login into the site by creating an account, in the window opened select Private
Policy Generator which opens a window in that choose Website and click on Next Step button and fill in the following
details:
1. Website URL: https://localhost:YourPortNo/
2. Website Name: NIT Customer Management
3. Entity Type: Individual
4. Country: India
5. State: Telangana

Click on Next Step button and choose all the Check Box’s and click Next Step Button, choose By Email Check
Box and enter the contact Email Id click on Next Step Button, choose Yes Radio Button and select all the free option
Radio Buttons, click Next Step Button, and click Generate Button which displays an URL copy it. Now come back to
Facebook, under the “Basic” Settings paste the URL in “Privacy Policy URL” TextBox and click on Save Changes Button.

356
Step 4: come back to your project in Visual Studio and install the below 2 packages using NuGet Package Manager:
Microsoft.AspNetCore.Authentication.Google
Microsoft.AspNetCore.Authentication.Facebook

Step 5: Go to “Startup.cs” file upto ASP.NET Core 5.0 and “Program.cs” file from ASP.NET Core 6.0 and above write
the below code to register Google and Facebook authentication services in our application:

ASP.NET Core 5.0: under “ConfigureServices” method of Startup Class write the below code.

services.AddAuthentication()
.AddGoogle(options =>
{
options.ClientId = "<Specify Client Id>";
options.ClientSecret = "<Enter Client Secret>";
})
.AddFacebook(options =>
{
options.AppId = "<Specify App Id>";
options.AppSecret = "<Specify App Secret>";
});

ASP.NET Core 6.0 and above: in Program Class write the below code just above the statement => “var app =
builder.Build();”.

builder.Services.AddAuthentication()
.AddGoogle(options =>
{
options.ClientId = "<Specify Client Id>";
options.ClientSecret = "<Enter Client Secret>";
})
.AddFacebook(options =>
{
options.AppId = "<Specify App Id>";
options.AppSecret = "<Specify App Secret>";
});

Step 6: Now go to “AccountController” class and implement the below Action methods by importing the namespace
“System.Security.Claims”:

public IActionResult ExternalLogin(string returnUrl, string Provider)


{
var url = Url.Action("CallBack", "Account", new { ReturnUrl = returnUrl });
var properties = signInManager.ConfigureExternalAuthenticationProperties(Provider, url);
return new ChallengeResult(Provider, properties);
}

357
public async Task<IActionResult> CallBack(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = "~/";
}
var info = await signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
ModelState.AddModelError("", "Error loading external login information.");
return View("Login");
}
var signInResult = await signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false, true);
if (signInResult.Succeeded) {
return LocalRedirect(returnUrl);
}
else
{
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
if (email != null)
{
var user = await userManager.FindByEmailAsync(email);
if (user == null) {
user = new IdentityUser {
UserName = info.Principal.FindFirstValue(ClaimTypes.Email),
Email = info.Principal.FindFirstValue(ClaimTypes.Email),
PhoneNumber = info.Principal.FindFirstValue(ClaimTypes.MobilePhone),
};
var identityResult = await userManager.CreateAsync(user);
}
await userManager.AddLoginAsync(user, info);
await signInManager.SignInAsync(user, false);
return LocalRedirect(returnUrl);
}
TempData["Title"] = "Error";
TempData["Message"] = "Email claim not received from third party provided.";
return RedirectToAction("DisplayMessages");
}
}

358
Hosting MVC Core Application on Microsoft Azure
Open the site “portal.azure.com” and create an account to login into the site. Click on the Subscriptions
button on the home screen which opens another window and in that click on “+ Add” button which opens a new
window and, in that select, “Azure for Students” and click on “Select Offer” button which opens a new window, click
on “Activate” button and provide all the required details.

Now open our project “MVCDHProject” in Visual Studio, then go to Solution Explorer, right click on the
project and select the option “Publish” this opens the Publish Window and in that under “Target” choose “Azure”
and click next, now under the “Specific Target” choose “Azure App Service (Windows)” and click next, now under
the “App Service” we need to create an “App Service Instance” and to do that click on “+ (Create an Azure App
Service)” button which opens a window and in that provide the following details:

Name: nitcore
Subscription: “Choose your subscription plan here”
Resource Group: Click on New button beside and enter a name to it, for example “NITRG”.
Hosting Plan: Click on New button besides, which opens a window and in that enter the following details:
Hosting Plan: NITHP
Location: “Choose any location or leave the default”
Size: “Choose the size or leave the default”
=> Click on the Ok button
=> Un-check the CheckBox “Use unique default hostname (preview).
=> Click on the Create button
=> Click on the Finish button

Now in the publish window, it will recognize all the dependencies, and our application right now has a
“Database Dependency”, so it will display that in the bottom of the window under “Service Dependencies” option,
click on the “+ (Add new service dependency)” button and in the window opened, select “Azure SQL Database”
option and click “Next” button, now in the new window opened click on the “+ (Create a SQL Database)” button
which opens a new window, provide the following details in it:

Database name: Enter a name to the Database or leave the existing name
Subscription: Choose your subscription plan here
Resource Group: NITRG
Database Server: Click on the New button beside and enter the following details in the window opened:
Database server name: nitdbserver
Location: Choose any location or leave the default
Administrator username: NitAdmin
Administrator password: NIT2025pwd
=> Click on the Ok button
=> Click on the Create button
=> Click on the Next button which will ask for Connection String details, so enter the following in it:

Database connection string name: ConStr


Database connection username: NitAdmin
Database connection password: NIT2025pwd
=> Click on the Finish button which will finish the configuration, click on the Close button, and close.

359
Now in the Publish window we find “More actions” dropdown select “Edit” in it which opens a new window
and in that on the LHS choose “Settings” and do the following:

 Expand the “Databases” option and check the CheckBox “Use this connection string at runtime”.
 Expand the “Entity Framework Migrations” option and check the CheckBox “Apply this migration on publish”.

=> Click on the Save button which closes the window.

=> In the Publish window click on the Publish button which will upload the site to azure server, which we can now
access by using the URL: https://nitcore.azurewebsites.net

Entity Framework Core DB First


This was available in Entity Framework Core also but with a very limited support. To work with DB First,
create a new “ASP.NET Core Web App (Model-View-Controller)” Project, naming it as “MVCCoreDBF”, choose “.NET
9.0 (Standard Term Support)”, Select the Checkbox “Configure for HTTPS”, Select the Checkbox “Do not use top-level
statements” and click on “Create” button.

Note: in EF Core we don’t have any designer support for creating DB First project just like what we have in EF 6. So
here we need to use Scaffolding commands to generate Model and Context classes.

To generate Model and Context classes use the below Scaffold command:
Scaffold-DbContext [ConnectionString] [Provider] [-OutputDir <Name>] [-Tables <Name>]

Step 1: To use Scaffold Commands and Entity Framework Core for SQL Server first we need to install the below
packages using NuGet Package Manager:
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.SqlServer

Step 2: Open PMC (Package Manager Console) and write the below code at the “PM” command prompt.
PM>Scaffold-DbContext "Data Source=Server;User Id=Sa;Password=123;Database=MVCDB;
TrustServerCertificate=True" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables Student

Note: in the Scaffold Command if we don’t use “[-Tables] <Table_Name>” attribute it will generate Model classes
for all the Tables in the Database.

The above statement will generate the Model class with the name “Student” and also generates the Context
class with the name “MVCDBContext” as below:

public partial class Student


{
public int Sid { get; set; }
public string Name { get; set; }
public int? Class { get; set; }
public decimal? Fees { get; set; }
public string Photo { get; set; }
public bool? Status { get; set; }
}

360
public partial class MVCDBContext : DbContext
{
public MVCDBContext() {
}
public MVCDBContext(DbContextOptions<MVCDBContext> options) : base(options) {
}
public virtual DbSet<Student> Students { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of
source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from
configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing
connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
optionsBuilder.UseSqlServer("Data Source=Server;Database=MVCDB;User Id=Sa;Password=123");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
modelBuilder.Entity<Student>(entity =>
{
entity.HasKey(e => e.Sid).HasName("PK__Student__CA1E5D78E2EF83E9");
entity.ToTable("Student");
entity.Property(e => e.Sid).ValueGeneratedNever();
entity.Property(e => e.Fees).HasColumnType("money");
entity.Property(e => e.Name).HasMaxLength(50).IsUnicode(false);
entity.Property(e => e.Photo).HasMaxLength(100).IsUnicode(false);
entity.Property(e => e.Status).IsRequired().HasDefaultValueSql("((1))");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

Step 3: To define the Controller class, Action methods and Views also let us use Scaffolding and to do that, right click
on the Controllers folder, Select Add => Controller and in the window opened select “MVC Controller with views,
using Entity Framework” and click Add button, which will open a new window and in that select the “Model cls:” as
“Student” and “Data context class:” as “MVCDBContext (MVCCoreDBF.Models)” and click on the “Add” button which
will generate the Controller class with all the required action methods and corresponding Views, and the name of
the Controller will be “StudentsController”.

Step 4: Now go to “Startup” class in case of ASP.NET Core 5.0 and below or “Program” class in case of ASP.NET Core
6.0 or above and register the “DBContext” class by calling “AddDbContext” method and to do this first we need to
import the namespace “MVCCoreDBF.Models” and write the code.

361
ASP.NET Core 5.0: write the below statement under “ConfigureServices” method of “Startup” class:
services.AddDbContext<MVCDBContext>();

ASP.NET Core 6.0 and above: write the below statement under “Program” class just above the statement => “var
app = builder.Build();”:
builder.Services.AddDbContext<MVCDBContext>();

Now run the project and watch the output of all the Views, but the problem is with the image i.e., it will not
be displayed and in “Add” and “Edit” Views we will not find the option for selecting the image, so we need to now
make all the necessary changes for including the Image in Display, New, Edit and Delete Views.

Step 5: Create a folder with the name “images” under “wwwroot” folder and copy all the image files of Students into
that folder.

Step 6: Now make the changes in all the required Views and their corresponding Action methods as following:

Index View: go to “Index.cshtml” and replace the code of Photo property with new code as following:
Old Code: @Html.DisplayFor(modelItem => item.Photo)
New Code: <img src='/images/@item.Photo' width="30" height="30" alt="No Image" />

Details View: go to “Details.cshtml” and replace the code of Photo property with new code as following:
Old Code: @Html.DisplayFor(model => model.Photo)
New Code: <img src='/Images/@Model.Photo' width="200" height="200" alt="No Image" />

Create View: go to “Create.cshtml” and replace the code of Photo property with new code as following:
Old Code: <input asp-for="Photo" class="form-control" />
New Code: <input type="file" name="selectedFile" />

Edit View: go to “Edit.cshtml” and replace the code of Photo property with new code as following:
Old Code: <input asp-for="Photo" class="form-control" />
New Code: <img src='/images/@Model.Photo' width="100" height="100" alt="No Image" />
<input type="file" name="selectedFile" />

Note: in “Create.cshtml” and “Edit.cshtml”, add “enctype” attribute to “<form>” tag which should look as below:
Create.cshtml: <form asp-action="Create" enctype="multipart/form-data">
Edit.cshtml: <form asp-action="Edit" enctype="multipart/form-data">

Delete View: go to “Delete.cshtml” and replace the code of Photo property with new code as following:
Old Code: @Html.DisplayFor(model => model.Photo)
New Code: <img src='/images/@Model.Photo' width="100" height="100" alt="No Image" />

Now go to “StudentsController” class, import “Microsoft.AspNetCore.Mvc.ModelBinding” namespaces and


make the below changes:

Re-write the constructor in the class by declaring a new field as following:


private readonly IWebHostEnvironment _environment;

362
public StudentsController(MVCDBContext context, IWebHostEnvironment environment) {
_context = context;
_environment = environment;
}
Re-write the Post Action method of Create as following:
public async Task<IActionResult> Create([Bind("Sid,Name,Class,Fees,Photo,Status")] Student student,
IFormFile selectedFile)
{
if (ModelState.IsValid || (ModelState.ErrorCount == 1 && ModelState["selectedFile"].ValidationState ==
ModelValidationState.Invalid)) {
if (selectedFile != null) {
string FolderPath = _environment.WebRootPath + "\\images";
if (!Directory.Exists(FolderPath)) {
Directory.CreateDirectory(FolderPath);
}
string FilePath = FolderPath + "\\" + selectedFile.FileName;
FileStream fs = new FileStream(FilePath, FileMode.Create);
selectedFile.CopyTo(fs);
student.Photo = selectedFile.FileName;
}
student.Status = true;
_context.Add(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(student);
}
Re-write the Get Action method of Edit as following:
public async Task<IActionResult> Edit(int? id)
{
if (id == null || _context.Students == null) {
return NotFound();
}
var student = await _context.Students.FindAsync(id);
if (student == null) {
return NotFound();
}
else {
TempData["Photo"] = student.Photo;
}
return View(student);
}
Re-write the Post Action method of Edit as following:
public async Task<IActionResult> Edit(int id, [Bind("Sid,Name,Class,Fees,Photo,Status")] Student student,
IFormFile selectedFile)
{

363
if (id != student.Sid) {
return NotFound();
}
if (ModelState.IsValid || (ModelState.ErrorCount == 1 && ModelState["selectedFile"].ValidationState ==
ModelValidationState.Invalid)) {
try {
if (selectedFile != null) {
string FolderPath = Path.Combine(_environment.WebRootPath, "images");
if (!Directory.Exists(FolderPath)) {
Directory.CreateDirectory(FolderPath);
}
string ImagePath = Path.Combine(FolderPath, selectedFile.FileName);
FileStream fs = new FileStream(ImagePath, FileMode.Create);
selectedFile.CopyTo(fs);
student.Photo = selectedFile.FileName;
}
else if (TempData["Photo"] != null) {
student.Photo = TempData["Photo"].ToString();
}
student.Status = true;
_context.Update(student);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) {
if (!StudentExists(student.Sid)) {
return NotFound();
}
else {
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(student);
}
Re-write the Post Action method of Delete as following:
public async Task<IActionResult> DeleteConfirmed(int id) {
var student = await _context.Students.FindAsync(id);
if (student != null) {
student.Status = false;
_context.Update(student);
await _context.SaveChangesAsync();
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}

364
Web API Core
Create a new project of type “ASP.NET Core Web API”, name the project as “CoreWebApiService”, choose
Target Framework as “.NET 8.0 (Long-term support)” and check these Checkbox’s “Configure for HTTPS”, “Use
controllers”, “Enable Open API Support” and “Do not use top-level statements”.

Let’s create an API Service that uses XML as Data Source and to do that follow the below process:
Step 1: add an XML File in the project naming it as “Customer.xml” and write the below code in it:
<Customers>
<Customer>
<Custid>101</Custid>
<Name>Scott</Name>
<Balance>25000</Balance>
<City>Hyderabad</City>
<Status>True</Status>
</Customer>
<Customer>
<Custid>102</Custid>
<Name>Smith</Name>
<Balance>35000</Balance>
<City>Kolkata</City>
<Status>True</Status>
</Customer>
<Customer>
<Custid>103</Custid>
<Name>David</Name>
<Balance>45000</Balance>
<City>Bengaluru</City>
<Status>True</Status>
</Customer>
<Customer>
<Custid>104</Custid>
<Name>Sofia</Name>
<Balance>55000</Balance>
<City>Mumbai</City>
<Status>True</Status>
</Customer>
</Customers>

Step 2: Add a new folder under the project naming it as “Models” and then under the folder add a class naming it as
“Customer” and write the below code in it:

public class Customer


{
public int Custid { get; set; }
public string? Name { get; set; }
public decimal? Balance { get; set; }

365
public string? City { get; set; }
public bool Status { get; set; }
}

Step 3: Add an interface in the Models folder naming it as “ICustomerDAL” so that DAL Class implementation can
use Dependency Injection Pattern, and write the below code in the interface:

public interface ICustomerDAL


{
List<Customer> Customers_Select();
Customer Customer_Select(int Custid);
void Customer_Insert(Customer customer);
void Customer_Update(Customer customer);
void Customer_Delete(int Custid);
}

Step 4: Add a class in the Models folder naming it as “CustomerXmlDAL”, and right now we are implementing the
DAL class logic to work with XML Data Source, and to do that write the below code in the class:

using System.Data;
public class CustomerXmlDAL : ICustomerDAL
{
DataSet ds;
public CustomerXmlDAL()
{
ds = new DataSet();
ds.ReadXml("Customer.xml");
ds.Tables[0].PrimaryKey = new DataColumn[] { ds.Tables[0].Columns["Custid"] };
}
public List<Customer> Customers_Select()
{
List<Customer> Customers = new List<Customer>();
foreach (DataRow dr in ds.Tables[0].Rows)
{
Customer obj = new Customer
{
Custid = Convert.ToInt32(dr["Custid"]),
Name = (string)dr["Name"],
Balance = Convert.ToDecimal(dr["Balance"]),
City = (string)dr["City"],
Status = Convert.ToBoolean(dr["Status"])
};
Customers.Add(obj);
}
return Customers;
}

366
public Customer Customer_Select(int Custid)
{
DataRow dr = ds.Tables[0].Rows.Find(Custid);
if (dr != null)
{
Customer obj = new Customer
{
Custid = Convert.ToInt32(dr["Custid"]),
Name = (string)dr["Name"],
Balance = Convert.ToDecimal(dr["Balance"]),
City = (string)dr["City"],
Status = Convert.ToBoolean(dr["Status"])
};
return obj;
}
return null;
}
public void Customer_Insert(Customer customer)
{
DataRow dr = ds.Tables[0].NewRow();
dr[0] = customer.Custid;
dr[1] = customer.Name;
dr[2] = customer.Balance;
dr[3] = customer.City;
dr[4] = customer.Status;
ds.Tables[0].Rows.Add(dr);
ds.WriteXml("Customer.xml");
}
public void Customer_Update(Customer customer)
{
DataRow dr = ds.Tables[0].Rows.Find(customer.Custid);
int Index = ds.Tables[0].Rows.IndexOf(dr);
ds.Tables[0].Rows[Index]["Name"] = customer.Name;
ds.Tables[0].Rows[Index]["Balance"] = customer.Balance;
ds.Tables[0].Rows[Index]["City"] = customer.City;
ds.Tables[0].Rows[Index]["Status"] = customer.Status;
ds.WriteXml("Customer.xml");
}
public void Customer_Delete(int Custid)
{
DataRow dr = ds.Tables[0].Rows.Find(Custid);
int Index = ds.Tables[0].Rows.IndexOf(dr);
ds.Tables[0].Rows[Index].Delete();
ds.WriteXml("Customer.xml");
}
}

367
Step 5: Go to “Startup.cs” file in case ASP.Net Core 5.0 and Program.cs file in case of ASP.NET Core 6.0 and write the
below statement by importing “CoreWebApiService.Models” namespace:

ASP.NET Core 5.0 => go to ConfigureServices method in Startup class and write the below statement over there:
builder.Services.AddScoped(typeof(ICustomerDAL), typeof(CustomerXmlDAL));

ASP.NET Core 6.0 and above => go to Main method in Program class and write the below statement just above the
statement “var app = builder.Build();”:
builder.Services.AddScoped(typeof(ICustomerDAL), typeof(CustomerXmlDAL));

Step 6: Add an “ApiController” in the Controllers folder and to do that right click on the “Controllers” folder, select
Add => Controller, in the window opened select API in LHS and then on the RHS select “API Controller - Empty”, click
Add button, name the class as “CustomerController” and write the below code in the class:

using System.Net;
using System.Net.Http;
using CoreWebApiService.Models;

[Route("api/[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
private readonly ICustomerDAL dal;
public CustomerController(ICustomerDAL dal)
{
this.dal = dal;
}
[HttpGet]
public List<Customer> GetCustomers()
{
return dal.Customers_Select();
}
[HttpGet("{Custid}")]
public Customer GetCustomer(int Custid)
{
return dal.Customer_Select(Custid);
}
[HttpPost]
public HttpResponseMessage Post(Customer c)
{
dal.Customer_Insert(c);
return new HttpResponseMessage(HttpStatusCode.Created);
}
[HttpPut]
public HttpResponseMessage Put(Customer c)
{

368
Customer customer = dal.Customer_Select(c.Custid);
if (customer != null)
{
dal.Customer_Update(c);
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
}
[HttpDelete("{Custid}")]
public HttpResponseMessage Delete(int Custid)
{
Customer customer = dal.Customer_Select(Custid);
if (customer != null)
{
dal.Customer_Delete(Custid);
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
}
}

To test Web API Core, we are provided with a built-in tool known as “Swagger”, so we don’t require using
any web debugging tools like Postman or Fiddler etc. Run the “APIController” we have defined and test all the
functionalities by using Swagger.

Consuming our Core API Service in an MVC Controller using JQuery-Ajax with-in the Same Project: add a new
Controller in the current project and it should be an “MVC Controller”, naming it as “HomeController” and add a
View to the default Index action method and write the below code in it:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web Api Core</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous"></script>
<script>
$(document).ready(function () {
GetCustomers();
});

369
function GetCustomers() {
$.ajax({
url: 'http://localhost/CoreWebApiService/api/Customer',
type: 'GET',
dataType: 'json',
success: function (Customers) {
$("#tblCustomers tbody").empty();
$("#tblCustomers").append("<tr><td><input id='custid' type='text' style='width: 50px'/></td><td><input
id='name' type='text' /></td><td><input id='balance' type='text' /></td><td><input id='city' type='text' /></td><td
align='center'><input id='status' type='checkbox' /></td><td align='center'><input type='button' id='insert'
value='Insert' onclick='AddCustomer()' /></td></tr>");
$.each(Customers, function (index, Customer) {
$("#tblCustomers").append(BuildCustomerRow(Customer));
});
},
error: function (request) {
HandleException(request);
}
});
}
function BuildCustomerRow(Customer) {
var NewRow = "<tr>" + "<td align='center'>" + Customer.custid + "</td>" +
"<td><input type='text' class='input-name' value='" + Customer.name + "'/></td>" +
"<td><input type='text' class='input-balance' value='" + Customer.balance + "'/></td>" +
"<td><input type='text' class='input-city' value='" + Customer.city + "'/></td>";
if (Customer.status == true)
NewRow += "<td align='center'><input class='input-status' type = 'checkbox' checked /></td>";
else
NewRow += "<td align='center'><input class='input-status' type = 'checkbox' /></td>";

NewRow += "<td><button type='button' onclick='UpdateCustomer(this);' data-custid='" +


Customer.custid + "'>Update</button>";
NewRow += "<button type='button' onclick='DeleteCustomer(this);' data-custid='" +
Customer.custid + "'>Delete</button>";
NewRow += "</td></tr>";
return NewRow;
}
function HandleException(request) {
var msg = "";
msg += "Code: " + request.status + "\n";
msg += "Text: " + request.statusText + "\n";
if (request.responseJSON != null) {
msg += "Message" + request.responseJSON.Message + "\n";
}
alert(msg);
}

370
var Customer = {
custid: 0,
name: "",
balance: 0,
city: "",
status: false
}
function AddCustomer() {
var obj = Customer;
obj.custid = $("#custid").val();
obj.name = $("#name").val();
obj.balance = $("#balance").val();
obj.city = $("#city").val();
obj.status = $("#status").is(":checked");

var options = {};


options.url = "http://localhost/CoreWebApiService/api/Customer";
options.type = "POST";
options.contentType = "application/json";
options.dataType = "json";
options.data = JSON.stringify(obj);
options.success = function () {
GetCustomers();
$("#divMsgs").html("Insert operations is successful.");
}
options.error = function () {
$("#divMsgs").html("Error while performing insert operation!");
}
$.ajax(options);
}
function UpdateCustomer(button) {
var obj = Customer;
obj.custid = $(button).data("custid");
obj.name = $(".input-name", $(button).parent().parent()).val();
obj.balance = $(".input-balance", $(button).parent().parent()).val();
obj.city = $(".input-city", $(button).parent().parent()).val();
obj.status = $(".input-status", $(button).parent().parent()).is(":checked");

var options = {};


options.url = "http://localhost/CoreWebApiService/api/customer";
options.type = "PUT";
options.contentType = "application/json";
options.dataType = "json";
options.data = JSON.stringify(obj);
options.success = function () {
GetCustomers();

371
$("#divMsgs").html("Update operations is successful.");
}
options.error = function () {
$("#divMsgs").html("Error while performing update operation!");
}
$.ajax(options);
}
function DeleteCustomer(button) {
$.ajax({
url: 'http://localhost/CoreWebApiService/api/customer/' + $(button).data("custid"),
type: 'DELETE',
dataType: 'json',
success: function () {
GetCustomers();
$("#divMsgs").html("Delete operations is successful.");
},
error: function () {
$("#divMsgs").html("Error while performing delete operation!");
}
});
}
</script>
</head>
<body style="background-color:cornflowerblue">
<form>
<table align="center" id="tblCustomers" border="1">
<thead>
<tr>
<th>Custid</th>
<th>Name</th>
<th>Balance</th>
<th>City</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody></tbody>
</table>
<br />
<div id="divMsgs" style="color:red"></div>
</form>
</body>
</html>

Right now, our project is a “WebApiProject” so we can run only “ApiControllers” whereas if we want to run
our “MVCController” do the following:

372
Step 1: go to “Startup.cs” file upto ASP.NET Core 5.0 or “Program.cs” file from ASP.Net Core 6.0 and change the
method call “AddControllers” as “AddControllersWithViews” as below:

ASP.NET Core 5.0: go to ConfigureServices method in Startup class and do the below change:
Old Code => services.AddControllers();
New Code => services.AddControllersWithViews();

ASP.NET Core 6.0 and above: go to Program class and do the below change:
Old Code => builder.Services.AddControllers();
New Code => builder.Services.AddControllersWithViews();

Step 2: also change the “EndPoint” configuration code as below:

ASP.NET Core 5.0:


Old Code:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

New Code:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapControllers();
});

ASP.NET Core 6.0 and above: add this code just above the method call “app.MapControllers();”:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

Step 3: host the Web Api Core Project on IIS as explained earlier and this action adds “web.config” file in your project.

Step 4: Go to “web.config” file in the project and there we find a node “<system.webServer>” and under that we
find “<handlers>” node, write the below statement inside of that <handlers> node:
<remove name="WebDAV" />

 Now under “<system.webServer>” node if you find “<modules>” node, add the below statement inside of it:
<remove name="WebDAVModule" />

 If you don’t find “<modules>” node, then write the below statements:
<modules><remove name="WebDAVModule" /></modules>

Step 5: run the “HomeController’s - Index” action method and test all the functionalities.

373
Consuming our API Service in an MVC Controller using JQuery Ajax from Another Project: If we want to consume
an “API Service” from other projects first we need to enable “CORS” in our “API Service Project” and to do that make
the below changes:

ASP.NET Core 5.0 => go to “ConfigureServices” method of “Startup.cs” file and add “Cors Service” as below:
services.AddCors();

ASP.NET Core 6.0 and above => go to “Program.cs” file and add “Cors Service” just above the statement “var app =
builder.Build();”:
builder.Services.AddCors();

ASP.NET Core 5.0 => go to “Configure” method of “Startup.cs” file and add “Cors Middleware” as below (write this
statement after “app.UseRouting();”) statement:

app.UseCors(options =>
{
options.AllowAnyOrigin();
options.AllowAnyMethod();
options.AllowAnyHeader();
});

ASP.NET Core 6.0 and above => go to “Program.cs” file and add “Cors Middleware” just below the statement “var
app = builder.Build();”:

app.UseCors(options =>
{
options.AllowAnyOrigin();
options.AllowAnyMethod();
options.AllowAnyHeader();
});

Now create a new “ASP.NET Core Web App (Model-View-Controller)” project naming it as
“CoreWebApiConsumer1”. Add a Controller in the project naming it as “TestApiController”, add a View to the default
“Index” action method, copy the whole code of “Index View” present in “HomeController” of our previous project
i.e., “CoreWebApiService”, paste it in “Index View” of the current project and run it.

Consuming our API Service in an MVC Controller using C# Code from Another Project: In the above case we have
seen how to consume an API Service in an MVC Project using JQuery AJAX, whereas if we want to consume it from
Action Methods of an MVC Controller using C#, do the following.

Step 1: Create a “ASP.NET Core Web App (Model-View-Controller)” project naming it as “CoreWebApiConsumer2”,
add a new class in the Models folder naming it as “Customer” and write the below code in the class:

public class Customer


{
public int Custid { get; set; }

374
public string? Name { get; set; }
public decimal? Balance { get; set; }
public string? City { get; set; }
public bool Status { get; set; }
}

Step 2: Open “appsettings.json” file to store the Web Api URL. To do that, in the end of “AllowedHosts”: “*” put a
comma and write the below code over there:

"WebServiceUrl": "http://localhost/CoreWebApiService/api/"

Step 3: Install “Microsoft.AspNet.WebApi.Client” library using NuGet Package Manager.

Step 4: Add a Controller in the project naming it as “TestApiController”, delete all the existing code in the class and
write the below code in the class:

using Newtonsoft.Json;
using CoreWebApiConsumer2.Models;
public class TestApiController : Controller
{
HttpClient client = new HttpClient();
private readonly IConfiguration _config;
public TestApiController(IConfiguration config)
{
_config = config;
string? serviceUrl = _config.GetValue<string>("WebServiceUrl");
client.BaseAddress = new Uri(serviceUrl);
}
public async Task<IActionResult> DisplayCustomers()
{
List<Customer> customers = new List<Customer>();
HttpResponseMessage response = await client.GetAsync("Customer");
if (response.IsSuccessStatusCode)
{
string result = response.Content.ReadAsStringAsync().Result;
customers = JsonConvert.DeserializeObject<List<Customer>>(result);
}
return View(customers);
}
public async Task<IActionResult> DisplayCustomer(int Custid)
{
Customer customer = new Customer();
HttpResponseMessage response = await client.GetAsync("Customer/" + Custid);
if (response.IsSuccessStatusCode)
{
string result = response.Content.ReadAsStringAsync().Result;

375
customer = JsonConvert.DeserializeObject<Customer>(result);
}
return View(customer);
}
public IActionResult AddCustomer()
{
return View();
}
[HttpPost]
public async Task<IActionResult> AddCustomer(Customer customer)
{
HttpResponseMessage response = await client.PostAsJsonAsync("Customer", customer);
if (response.IsSuccessStatusCode)
return RedirectToAction("DisplayCustomers");
else
return View();
}

public async Task<IActionResult> EditCustomer(int Custid)


{
Customer customer = new Customer();
HttpResponseMessage response = await client.GetAsync("Customer/" + Custid);
if (response.IsSuccessStatusCode)
{
string result = response.Content.ReadAsStringAsync().Result;
customer = JsonConvert.DeserializeObject<Customer>(result);
}
return View(customer);
}
public async Task<IActionResult> UpdateCustomer(Customer customer)
{
HttpResponseMessage response = await client.PutAsJsonAsync("Customer", customer);
if (response.IsSuccessStatusCode)
return RedirectToAction("DisplayCustomers");
else
return View("EditCustomer");
}

public async Task<IActionResult> DeleteCustomer(int Custid)


{
HttpResponseMessage response = await client.DeleteAsync("Customer/" + Custid);
if (!response.IsSuccessStatusCode)
ModelState.AddModelError("", "Delete action resulted in an error");
return RedirectToAction("DisplayCustomers");
}
}

376
Step 5: Add Views to “DisplayCustomers”, “DisplayCustomer”, “AddCustomers” and “EditCustomer” actions
methods and write the below code over there:

DisplayCustomers.CShtml:
@model IEnumerable<Customer>
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<table border="1" align="center" class="table-condensed">
<tr>
<th>@Html.DisplayNameFor(C => C.Custid)</th>
<th>@Html.DisplayNameFor(C => C.Name)</th>
<th>@Html.DisplayNameFor(C => C.Balance)</th>
<th>@Html.DisplayNameFor(C => C.City)</th>
<th>@Html.DisplayNameFor(C => C.Status)</th>
<th>Actions</th>
</tr>
@foreach (Customer customer in Model)
{
<tr>
<td align="center">@Html.DisplayFor(C => customer.Custid)</td>
<td>@Html.DisplayFor(C => customer.Name)</td>
<td>@Html.DisplayFor(C => customer.Balance)</td>
<td>@Html.DisplayFor(C => customer.City)</td>
<td align="center">@Html.DisplayFor(C => customer.Status)</td>
<td>
<a asp-action="DisplayCustomer" asp-route-Custid="@customer.Custid">View</a> &nbsp;
<a asp-action="EditCustomer" asp-route-Custid="@customer.Custid">Edit</a> &nbsp;
<a asp-action="DeleteCustomer" asp-route-Custid="@customer.Custid"
onclick="return confirm('Are you sure of deleting the record?')">Delete</a>
</td>
</tr>
}
<tr>
<td colspan="6" align="center"><a asp-action="AddCustomer">Add New Customer</a></td>
</tr>
</table>

DisplayCustomer.cshtml:
@model Customer
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<table border="1" align="center">
<tr><td>Custid: </td><td>@Model.Custid</td></tr>
<tr><td>Name: </td><td>@Model.Name</td></tr>
<tr><td>Balance: </td><td>@Model.Balance</td></tr>
<tr><td>City: </td><td>@Model.City</td></tr>
<tr><td>Status: </td><td>@Model.Status</td></tr>
</table>

377
<div style="text-align:center">
<a asp-action="DisplayCustomers" align="center">Back to Customer Details</a>
</div>

AddCustomer.cshtml:
@model Customer
<form asp-controller="TestApi" asp-action="AddCustomer" method="post">
<div><label asp-for="Custid"></label><br /><input asp-for="Custid" /></div>
<div><label asp-for="Name"></label><br /><input asp-for="Name" /></div>
<div><label asp-for="Balance"></label><br /><input asp-for="Balance" /></div>
<div><label asp-for="City"></label><br /><input asp-for="City" /></div>
<div><label asp-for="Status"></label><br /><input asp-for="Status" /></div>
<div>
<input type="submit" value="Save" />
<input type="reset" value="Reset" />
</div>
</form>
<div>
<a asp-action="DisplayCustomers" align="center">Back to Customer Details</a>
</div>

EditCustomer.cshtml:
@model Customer
<form asp-controller="TestApi" asp-action="UpdateCustomer" method="post">
<div><label asp-for="Custid"></label><br /><input asp-for="Custid" readonly /></div>
<div><label asp-for="Name"></label><br /><input asp-for="Name" /></div>
<div><label asp-for="Balance"></label><br /><input asp-for="Balance" /></div>
<div><label asp-for="City"></label><br /><input asp-for="City" /></div>
<div><label asp-for="Status"></label><br /><input asp-for="Status" /></div>
<div>
<input type="submit" value="Update" />
<input type="reset" value="Reset" />
</div>
</form>
<div>
<a asp-action="DisplayCustomers" align="center">Back to Customer Details</a>
</div>

378
ASP.NET Razor Pages (Web Apps.)
The Razor Pages framework is lightweight and flexible framework which provides developers with full
control over rendered HTML. Razor Pages is the recommended framework for cross-platform server-side HTML
generation. Introduced as part of ASP.NET Core, is a server-side, page-focused framework that enables building
dynamic, data-driven web sites with clean separation of concerns. Part of the ASP.NET Core web development
framework from Microsoft, Razor Pages supports cross platform development and can be deployed to Windows,
UNIX and Mac operating systems. Razor Pages makes use of the popular C# programming language for server-side
programming, and the easy-to-learn Razor templating syntax for embedding C# in HTML mark-up to generate
content for browsers dynamically.

Razor Pages is suitable for all kinds of developers from beginners to enterprise level. It is based on a page-
centric development model, offering a familiarity to web developers with experience of other page-centric
frameworks such as PHP, Classic ASP, Java Server Pages, and ASP.NET Web Forms. It is also relatively easy for the
beginner to learn, and it includes all of the advanced features of ASP.NET Core (such as dependency injection) making
it just as suitable for large, scalable, team-based projects.

Razor Pages is included within .NET Core from version 2.0 onwards, which is available as a free download
as either an SDK (Software Development Kit) or a Runtime. The SDK includes the runtime and command line tools
for creating .NET Core applications. The SDK is installed for you when you install Visual Studio 2017 Update 3 or later.

If you want a dynamic web site, that is one where the content is regularly being added to, you have a
number of options available to you. You can use a Content Management System (CMS), of which there are many to
choose from including Word Press, Umbraco, Joomla!, Drupal, Orchard CMS and so on. Or you can hire someone to
build a suitable site for you. Or you can build your own if you have an interest in, and an aptitude for programming.

If you choose to build your own, you can choose from a wide range of programming languages and
frameworks. If you are a beginner, you will probably want to start with a framework and language that is easy to
learn, well supported and robust. If you are considering making a career as a programmer, you probably want to
know that the skills you acquire while learning your new framework will enhance your value to potential employers.
In both cases, learning C# as a language and ASP.NET Core as a framework will tick those boxes. If you are a seasoned
developer, the Razor Pages framework is likely to add to your skillset with the minimum amount of effort.

You can still choose to use ASP.NET Core MVC to build your ASP.NET Core web applications. If you are
porting an existing .NET Framework MVC application (MVC5 or earlier) to .NET Core, it may well be quicker or easier
to keep with the MVC framework. However, Razor Pages removes a lot of the unnecessary ceremony that comes
with the ASP.NET implementation of MVC and is a simpler, and therefore more maintainable development
experience. The key difference between Razor Pages implementation of the MVC pattern and ASP.NET Core MVC is
that Razor Pages uses the Page Controller pattern instead of the Front Controller pattern.

Creating a Razor Pages (Web App’s.) Project: Open Visual Studio for creating a new project and in the New Project
window select “ASP.NET Core Web App” project template, name it as “CoreRazorPagesDemo”, choose “.NET 9.0
(Standard Term Support)” as Framework, select the Checkbox’s “Configure for HTTPS” and “Do not use top-level
statements”, and click “Create” button.

If you now examine the project’s folder structure in Solution Explorer you will not find Controllers, Models
and Views folder but you will find Pages folder where all the Razor Pages are stored. Rest of all the other folders and
files will be same as ASP.NET Core MVC Project only:

379
Open “Program.cs” file and observe the code over there and we find the Razor Pages Service enabled here
and the code in the class Program will be as below:

public class Program


{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.


if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see
https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();
}
}

380
In the above code:
 AddRazorPages adds services for Razor Pages to the application.
 MapRazorPages adds endpoints for Razor Pages to the IEndpointRouteBuilder.

If we go to the Pages folder, we find a set of Razor Pages that are created by default, as below:

Basic code in a Razor Page will be as below:


@page
<h1>Hello, World!</h1>
<h2>The time on the server is @DateTime.Now</h2>

The above code looks a lot like a Razor View file used in an ASP.NET Core MVC application only. What makes
it different is the @page directive. @page makes the file into an MVC action, which means that it handles requests
directly, without going through a Controller. @page must be the first Razor directive on a page.

Every Razor Page will be having a Page Model class associated with it for implementing any business logic,
for example if you have Razor Page with the name Index then the associated Page Model class will be “IndexModel”
and this class inherits from the pre-defined class “PageModel” defined in Microsoft.AspNetCore.Mvc.RazorPages
namespace. So, every Razor Page is associated with 2 files: “Index.cshtml” and “Index.cshtml.cs”. Currently our
project has a Razor Page with the name “Index” and the code present in associated 2 files will be as below:

Index.cshtml:
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about
<a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core </a>.
</p>
</div>

Index.cshtml.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace CoreRazorPagesDemo.Pages
{

381
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.
In the above code page name is “Index”, so Page Model class name is “IndexModel”. The PageModel class allows
separation of the logic of a page from its presentation. It defines page handlers for requests sent to the page and
the data used to render the page. The page has an OnGet handler method, which runs on Get requests and an
OnPost or OnPostAsync handler method, which runs on POST requests (when a user posts the form). Handler
methods for any HTTP verb can be added. The most common handlers are:

 OnGet to initialize state needed for the page. The OnGet method displays the Index.cshtml Razor Page.
 OnPost or OnPostAsync to handle form submissions. The Async naming suffix is optional but is often used by
convention for asynchronous functions.

Note: If you’re familiar with ASP.NET MVC apps, The OnPost or OnPostAsync code looks similar to typical controller
action method code. Most of the MVC primitives like model binding, validation, and action results work the same
with MVC and Razor Pages.

Now let’s design the above application to perform CRUD Operations on our Customer table is MVCDB Database:
Step 1: To use Scaffold Commands and Entity Framework Core for SQL Server first we need to install the below
packages using NuGet Package Manager:
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.SqlServer

Step 2: Open PMC (Package Manager Console) and write the below code at the “PM” command prompt.

PM>Scaffold-DbContext "Data Source=Server;User Id=Sa;Password=123;Database=MVCDB;


TrustServerCertificate=True" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables Customer

The above statement will add Models folder in the project and generate a Model class with the name
“Customer” and also a Context class with the name “MvcdbContext”.

Step 3: Now go to “Startup” class in case of ASP.NET Core 5.0 or “Program” class in case of ASP.NET Core 6.0 and
above to register the “DBContext” class by calling “AddDbContext” method and to do this first we need to import
the namespace “CoreRazorPagesDemo.Models” and write the below code.

ASP.NET Core 5.0: write the below statement under “ConfigureServices” method of “Startup” class:
services.AddDbContext<MvcdbContext>();

382
ASP.NET Core 6.0 and above: write the below statement under “Program” class just above the statement => “var
app = builder.Build();”:
builder.Services.AddDbContext<MvcdbContext>();

Step 4: Create the required Pages for performing CRUD operations.

Display All Customers: Open the existing “Index.cshtml.cs” file, delete all the existing code inside of the
“IndexModel” class and write the below code over there, by importing “CoreRazorPagesDemo.Models” namespace:

public class IndexModel : PageModel


{
private readonly MvcdbContext context;
public IndexModel(MvcdbContext context)
{
this.context = context;
}
public List<Customer>? Customers { get; set; }
public void OnGet()
{
Customers = context.Customers.Where(C => C.Status == true).ToList();
}
}

Now go to Index.cshtml and write the below code, by deleting the whole code in the page:
@page
@model IndexModel
@{
ViewData["Title"] = "Display Customers";
}
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<table border="1" class="table table-bordered">
<tr>
<th>Custid</th>
<th>Name</th>
<th>Balance</th>
<th>City</th>
<th>Status</th>
<th>Actions</th>
</tr>
@foreach (var customer in Model.Customers)
{
<tr>
<td align="center">@customer.Custid</td>
<td>@customer.Name</td>
<td>@customer.Balance</td>
<td>@customer.City</td>

383
<td align="center"><input type="checkbox" asp-for="@customer.Status" disabled/></td>
<td>
<a asp-page="DisplayCustomer" asp-route-Custid="@customer.Custid">View</a> &nbsp;
<a asp-page="EditCustomer" asp-route-Custid="@customer.Custid">Edit</a> &nbsp;
<a asp-page="DeleteCustomer" asp-route-Custid="@customer.Custid">Delete</a>
</td>
</tr>
}
<tr>
<td colspan="6" align="center">
<a asp-page="AddCustomer">Add New Customer</a>
</td>
</tr>
</table>

Display Customer Page: Add a new - empty razor page under pages folder, name it as “DisplayCustomer.cshtml”.
Go to “DisplayCustomer.cshtml.cs” view, import the namespace “CoreRazorPagesDemo.Models” and write the
below code under the class by delete the existing code in the class:

public class DisplayCustomerModel : PageModel


{
public Customer Customer { get; set; }
private readonly MvcdbContext context;
public DisplayCustomerModel(MvcdbContext context)
{
this.context = context;
}
public void OnGet(int Custid)
{
Customer = context.Customers.Find(Custid);
}
}

Now go to DisplayCustomer.cshtml and write the below code, by deleting the whole code in the page:
@page "{Custid}"
@model CoreRazorPagesDemo.Pages.DisplayCustomerModel
@{
ViewData["Title"] = "Display Customer";
}
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<table border="1" align="center" class="table-condensed">
<tr>
<td>Cusid:</td>
<td>@Model.Customer.Custid</td>
</tr>
<tr>

384
<td>Name:</td>
<td>@Model.Customer.Name</td>
</tr>
<tr>
<td>Balance:</td>
<td>@Model.Customer.Balance</td>
</tr>
<tr>
<td>City:</td>
<td>@Model.Customer.City</td>
</tr>
<tr>
<td>Status:</td>
<td><input type="checkbox" asp-for="@Model.Customer.Status" disabled/></td>
</tr>
<tr>
<td colspan="2" align="center">
<a asp-page="Index">Back to Customer Details</a>
</td>
</tr>
</table>

Add Customer Page: Add a new - empty razor page under pages folder, name it as “AddCustomer.cshtml”. Go to
“AddCustomer.cshtml.cs” view, import the namespace “CoreRazorPagesDemo.Models” and write the below code
under the class by delete the existing code in the class:

public class AddCustomerModel : PageModel


{
public Customer Customer { get; set; }
private readonly MvcdbContext context;
public AddCustomerModel(MvcdbContext context)
{
this.context = context;
}
public RedirectResult OnPost(Customer customer)
{
context.Customers.Add(customer);
context.SaveChanges();
return Redirect("Index");
}
}

Now go to AddCustomer.cshtml and write the below code, by deleting the whole code in the page:
@page
@model CoreRazorPagesDemo.Pages.AddCustomerModel
@{
ViewData["Title"] = "Add Customer";
}

385
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<form method="post">
<div>
<label>Custid:</label><br /><input asp-for="@Model.Customer.Custid" />
</div>
<div>
<label>Name:</label><br /><input asp-for="@Model.Customer.Name" />
</div>
<div>
<label>Balance:</label><br /><input asp-for="@Model.Customer.Balance" />
</div>
<div>
<label>City:</label><br /><input asp-for="@Model.Customer.City" />
</div>
<div>
<label>Status:</label><br /><input asp-for="@Model.Customer.Status" />
</div>
<div><input type="submit" value="Save" /><input type="reset" value="Reset" /></div>
<div><a asp-page="Index" align="center">Back to Customer Details</a></div>
</form>

Edit Customer Page: Add a new - empty razor page under pages folder, name it as “EditCustomer.cshtml”. Go to
“EditCustomer.cshtml.cs” view, import the namespace “CoreRazorPagesDemo.Models” and write the below code
under the class by delete the existing code in the class:

public class EditCustomerModel : PageModel


{
public Customer Customer { get; set; }
private readonly MvcdbContext context;
public EditCustomerModel(MvcdbContext context)
{
this.context = context;
}
public void OnGet(int Custid)
{
Customer = context.Customers.Find(Custid);
}
public RedirectResult OnPost(Customer customer)
{
customer.Status = true;
context.Customers.Update(customer);
context.SaveChanges();
return Redirect("Index");
}
}

386
Now go to EditCustomer.cshtml and write the below code, by deleting the whole code in the page:
@page "{Custid}"
@model CoreRazorPagesDemo.Pages.EditCustomerModel
@{
ViewData["Title"] = "Edit Customer";
}
<h2 style="text-align:center;background-color:yellowgreen;color:red">Customer Details</h2>
<form method="post">
<div>
<label>Custid:</label><br /><input asp-for="@Model.Customer.Custid" readonly />
</div>
<div>
<label>Name:</label><br /><input asp-for="@Model.Customer.Name" />
</div>
<div>
<label>Balance:</label><br /><input asp-for="@Model.Customer.Balance" />
</div>
<div>
<label>City:</label><br /><input asp-for="@Model.Customer.City" />
</div>
<div>
<label>Status:</label><br /><input asp-for="@Model.Customer.Status" disabled />
</div>
<div>
<input type="submit" value="Update" />
<a asp-page="Index" align="center">Cancel</a>
</div>
</form>

Delete Customer Page: Add a new - empty razor page under pages folder, name it as “DeleteCustomer.cshtml”. Go
to “DeleteCustomer.cshtml.cs” view, import the namespace “CoreRazorPagesDemo.Models” and write the below
code under the class by delete the existing code in the class:

public class DeleteCustomerModel : PageModel


{
public Customer Customer { get; set; }
private readonly MvcdbContext context;
public DeleteCustomerModel(MvcdbContext context)
{
this.context = context;
}
public void OnGet(int Custid)
{
Customer = context.Customers.Find(Custid);
}

387
public RedirectResult OnPost(Customer customer)
{
context.Customers.Update(customer);
context.SaveChanges();
return Redirect("Index");
}
}

Now go to DeleteCustomer.cshtml and write the below code, by deleting the whole code in the page:
@page "{Custid}"
@model CoreRazorPagesDemo.Pages.DeleteCustomerModel
@{
ViewData["Title"] = "Delete Customer";
}
<form method="post">
<div>
<label>Custid:</label><br />
<input asp-for="@Model.Customer.Custid" readonly />
</div>
<div>
<label>Name:</label><br />
<input asp-for="@Model.Customer.Name" readonly />
</div>
<div>
<label>Balance:</label><br />
<input asp-for="@Model.Customer.Balance" readonly />
</div>
<div>
<label>City:</label><br />
<input asp-for="@Model.Customer.City" readonly />
</div>
<div>
<label>Status:</label><br />
<input asp-for="@Model.Customer.Status" disabled />
</div>
<div>
<input type="submit" value="Delete" />
<a asp-page="Index" align="center">Cancel</a>
</div>
</form>

The End

388

You might also like