razor pages can make it even
simpler to create web apps using dotnet core. Brueggen Patel is an
experienced instructor and he will teach you how to create web apps
using dotnet core and razor pages. Hi, guys, and welcome to dotnet Mastery, my name
is broken and in this course we will explore the basic foundation of dotnet core web applications
with razor pages, we will be using dotnet six and Visual Studio 2022. For the short course dotnet
core has been a buzzword for a while. And most of the new development in dotnet is built on dotnet
core and the current version is dotnet six dotnet core comes with great features and advantages
as compared to the previous versions of dotnet. But for starters, let's take a brief overview
at topics we will cover in this course, whenever we learn any programming language,
the first thing is basic foundation. So, we will start with the fundamentals of ASP dotnet
core application. Then we will take a look at what is new on what are the changes in dotnet six as
compared to the previous version. Once we have a solid foundation in dotnet core files and folder
structure, then we will take a look at Entity Framework core that is what we will be using to
interact or create our database project. Using Entity Framework core and dotnet core, we will
perform CRUD operations on a particular model. When we do that, we will understand the client
side and server side validations in dotnet core. And we will display alerts using temp data that
will give you a good foundation in dotnet core. But the main thing that I will also include this
error solving, I will display you common errors and how to resolve them. That way you will gain
more confidence in what you will learn. Lastly, the application that we will build, we will deploy
that to Azure along with the SQL Server. So with all of that you will have a good starting
foundation in dotnet core using razor pages. In this video, let's take a look at what we
will build in this course. From the URL here you can see that the application is live on
Azure, we will host our application on Azure along with SQL Server. Then in the top navigation,
we have a homepage and a categories page. If you click on categories, we do not have any
categories right now. So we can first click on Create a Category button. And on this page, if
you click the Create button without populating any fields, we get error messages. These are
client side validations right out of the box, we also have a button to go back to the list. Then
if we go back on Create Page and FA populate the details in the category with just the name,
we still have validation with display order. We also have a custom validation that if name
and display order are same, then we will also display a custom error message. The error that
you see this time is a server side validation. Then if we have values that passes all the
validation, and if we hit the create button, we have nice alert to display the confirmation.
We will be using toaster js for these alerts. Then we have all the categories that we
will be displaying in the table here, we can edit them. And once we update them,
we again have our alerts confirmation. Lastly, we also have the Delete
functionality with the alerts. And then for the theme that we are using
for styling, we are using boots watch theme, and we will deploy our application to Azure. So
you can see there are quite a few things to learn in this small project. Let's get started with
all of them from the next video. Let's take a look at all the tools that we will use in
this course. We will be using dotnet six for our application. So make sure to install
the latest version after unsex. For the IDE we will be using Visual Studio. The version
that I will be using is Visual Studio 2022. There are lots of advanced features in 2022
as compared to 2019. So you can always install the free version of Visual Studio 2022 For
our database We will be using SQL Server. So first you will have to install SQL Server. And
then you should install SSMS, which has SQL Server Management Studio. If you have older version
of SSMS, that's completely okay. As long as you're able to connect to SQL Server on your local
machine, we will be using that connection string, and everything will work. So once you've
installed all three of these software's, let's continue from the next video. This video,
I want to walk you through the journey of dotnet core dotnet core is probably the biggest
change that the dotnet language has encountered. In 2002, Microsoft introduced webforms,
which was a revolution at that time webforms has its drawbacks, and there
was a need to overcome I love them. Because of that the dotnet team came up with
a new architecture, which was dotnet MVC. Now, even though I love MVC, and I have built
many applications in MVC, it had its flaws, like it was created on top of the components for
web forms. Because of that, it was tied to IIS, and ultimately, Windows operating system. But with
the evolution of app development, Microsoft had to keep up with the changing technology. Finally, in
June of 2016, Microsoft released ASP. NET Core, and it was the first version dotnet core is built
on top of the new dotnet core framework, it is completely rewritten and it is a cross platform
version. Hence it is not tied with Windows. Also dotnet core was built with cloud in
mind. So it is extremely robust with that. Then in August of 2018, Microsoft released dotnet
core two, and the team has been active with releasing new versions, there was a big change
from dotnet 2.1 to 2.2, because we had to update quite a few class libraries. And there were a few
challenges. But since then, dotnet core team has been releasing new versions with three point one
and dotnet five, which was released in November of 2020. After that, that is done at six which
will be released in November of 2021. We will be using the Preview version, but whatever we learned
will be the same once dotnet six is released. So this is a small overview of all the dotnet
frameworks and their evolution. That being said, why should when you start NET Core as compared
to the classic dotnet dotnet core comes with many advantages. First one is ASP dotnet core
is fast and open source. If you compare that to the traditional dotnet applications, that have
been quite a few benchmarks, and it is very fast. When you compare that to web forms, or even
dotnet MVC dotnet core is also cross platform, the classic dotnet was tied to IIS and Windows.
But since the dotnet core is rewritten, it has removed that dependency with dotnet core. We also
have a built in support for dependency injection, which saves a lot of time and it is extremely
helpful. Once you get used with using dependency injection, you cannot imagine your application
without that. With any programming language, it is critical that the new updates or the
new version that are released, they should be easily upgradeable and that is one of the feature
with dotnet core when a new version is released, updating to that new version does not have
groundbreaking changes. Because of that you can always keep up with the new versions. dotnet core
is also cloud friendly. When the dotnet core was being written cloud architecture was kept in mind.
And because of that it is completely compatible with all of the cloud components. And lastly,
when it comes to performance dotnet core exceeds all of the previous versions, and even the new
versions in dotnet code that are being released. They supersede the previous version. The code
actually gets more optimized that results into improved performance. The ASP dotnet core
compiler will eventually optimize the entire code whenever the code is recomposed using
dotnet core framework dotnet course actual performance is multiple times than any
of the frameworks previous implementation. because after that it is clear that Microsoft
has a long term plan with dotnet code technology. So with that brief overview, let's
continue our learning in the next video. In this video, before we take a look at the other
files, I will introduce you to a new concept, which is dependency injection. ASP dotnet core
implements a simple built in dependency injection. Container Dependency injection is an integral
part of the ASP dotnet core architecture. dotnet core injects objects of dependency
classes through constructor by using the built in IOC container. Before I show you
what advantages dependency injection brings, let's see a scenario where there is no
dependency injection. In a typical application, let's say we have three pages right now. And we
have some common functionality that we want to use across all the three pages. Like let's say we want
to send emails, and we want to access our database in all the three pages that we have. Now,
let's imagine that on these three pages, we need to access the database first. So
what we will do is we will create the object for database classes on all the three pages, we
will have to open that connection, we will have to do the database operation. And then we will
have to close the connection in all the places to do the same and create object for email
implementation that we have in all the three pages. So you can see this is a lot of duplicate
code. On top of that, what happens in future, if you change the implementation of
how you access the database, or email, based on the current configuration, you might have
to make that change in all of the three pages, which is a big mess, because right now it's three
pages down the line, it could be 30, or 300 pages. Another issue here is that on each page,
you will deal with creating the object, managing them as well as disposing them. And
that will be a time consuming effort when we have to do that in all the pages. So that
being said, what is the solution to avoid all of this and get an optimal architecture. The
answer to all of that is dependency injection. First, let me show how this scenario would look
like. Again, we will have the three pages. And we will have email and database functionality. These
are the common things that we had before as well. But now we will have something special, which
is dependency injection container. So as you can see, we have got our dependency injection
container that will have an ID email and an IDE interface and its implementation. So inside our
container, we have the implementation of the eye email interface and the IDB interface. When any
page will need access to these functionalities, it will just ask the dependency injection container
to create an object of this functionality and directly give page an object to use. So inside
the page, we will actually be using an interface. And then dependency injection does audits magic of
passing the object when the website needs it, that we do not have to deal with creating the object
disposing or managing that object inside our pages or pages will look very clean with just the
interface all the instance and implementation will be done by dependency injection container. Now in
future if you want to change or replace the email class, you do not have to make any changes in
the pages, all you have to do is just change the implementation inside the email class. And since
we are registering that in the container, next time when we build the project, it will take the
new implementation. So you can see we only have to change in one place. Now. That is one of the main
advantage that comes with dependency injection. Now in order to use dependency injection, you
can use many third party tools. But with dotnet core we have a built in dependency injection
container and that has its own advantages. So I hope that you have a short overview
of how Dependency injection is helpful. First thing that we have to do is we need
to create a new project. So I have opened up Visual Studio 2022 which will be the editor
for this cores. Here. On the left hand side, I have my previous projects. And on the right
hand side, we have the options to get started, we will click on create a new project. And
we have lots of templates that are available. We want to create a web application. So we can
select that. And we want to go back with razor pages. So that is the first option that is being
selected. But if the first option in your case is something different, scroll down and look for ESP
dotnet core web app. It should only be web app, and not the web app with models view and
controller that you see down here. We are working with only razor page application. So
select that, and we will hit the next button. Next thing that we can give our project is a
meaningful name, we will call that as Abby. Now here you'll notice there is a project name and
a solution name. A solution can have multiple project. Let's say we are working on Abby work
project. So we can call that Abby web. And then we can just change the solution to be happy. So
all the projects that are related to Abby will be inside the same solution. Next, let me change
the location to where I want to save the project. And we will hit the next button. Here we will get
some more options on what is the dotnet framework that we want to use. I will select dotnet six
here. And next we have the authentication type. Now if we want, we can select the prebuilt
templates that are available with authentication. But we want to start from scratch, we will
select none here, I do not want any darker. And let's hit the create a button that will
create our project. And we will see all the files and folder structures on the left hand
side inside the window of Solution Explorer in Visual Studio. Now by chance, if
you close the window, do not panic. You can reload that by going to views. And
the first one here is Solution Explorer. So now that our project is created,
let's continue in the next video. Now that the project has been created, you can see
there are quite a few files and folder structure on the right hand side. If you expand
the Pages folder that will display all the pages in our application. Before I
dive into all the files and folder here, let me run the application by clicking on this
play icon with the project name, which is epi web that will build your project and it will open up
the browser with our website. So perfect on the default page. Here you can see in the navigation,
we have home and privacy page. On the home page, we have a welcome text and the link that takes
us to the dotnet core website. Let's go back to our application. And inside the Pages folder,
we have a page with the name of index.cs. HTML. This is the home page of our application. You
can see we have the same welcome text here and paragraph that is displaying inside the default
page. Now do not worry about the linking routing files and folders or this page model or anything
on top right here. We will walk through all of them as we proceed with the course. But before
anything, I want to walk you through one example, inside the welcome here. Let's see if you
change some text here, save this file and go back. You do not see that change right here.
To see that you will have to refresh the page. And then you see that change. But after that if
you make any change in the files here, and if you save it go back, you can see we do not have
to refresh. Let me show that once again. So if I make a change, and as soon as I save it, you will
see the website reloads and display the change. That is because with dotnet six, we
have something called as hot reload. And that is a great functionality. Because now
if you're designing something you make change, it is automatically reflected in the view.
So if this feature is not a neighbor, you can see the red icon here if you take your
mouse there it displays hot reload, you click on the arrow icon and make sure hot reload on File
Save is enabled. As long as that is enabled, only first time you will have to refresh the
application. After that if you save the changes, it will automatically reload the page. And
again this feature has been added to dotnet sex. So if you're working with previous version,
this will not work. for previous versions, what you have to do is if you right click on
the project, select Manage NuGet packages. Inside the Browse tab, we had to install a new get
package. So if I search for runtime compilation, we have a package for Microsoft dot ASP NET
Core dot MVC dot razor dot runtime compilation, we had to install this package.
And once you install that package, we had to make a change inside the program.cs
class file. So once that package has been installed, if you go to program.cs class file,
where we are adding the razor pages here, we also had to add the razor runtime compilation.
Now do not worry about this file. I will explain everything here. But if you're working with a
version before dotnet FFI, this is the change that was needed. Now even though I recorded this
course, in dotnet, six, when I was recording, this feature was not available. So in the later
videos on the razor pages, I will be adding the Add razor runtime compilation. But you do not
have to do that, because now we have hot reload. And that takes care of the runtime compilation. So
that being said, let me close all the tabs here. Let's not save anything. And let's analyze all
the files and folder structure in our project. I just wanted to give you a
quick sneak peek on hot reload. This video, I want to give you a brief overview of
razor pages. Razor pages have been introduced in ASP dotnet core from the version 2.0. Razor
pages is a new feature of ASP dotnet core that makes coding page focused scenarios easier
and more productive. In MVC we have models, views and controllers. But inside razor pages, we have
page and page model. So everything for that page is isolated and condensed in one single location.
That being said razor pages is not just for simple scenarios. Everything that you can do with MVC
you can do by using razor pages, like routing models, action result, tag helpers, and so on.
That is just a brief overview about razor pages. But we will explore everything with razor pages
in the future videos. Now that our application has been created, let's take a look at the first
file which will be the Project File Project file, you won't be able to see that directly inside the
files here, you will have to right click and we have added project file. When we click here,
you will see few options that are configured. The first one here is the Property Group. And that
denotes what is the dotnet framework that we are using using dotnet six here and it is displayed
there. Next what we have is the item group, item group will have all of the new get
packages that we will be adding in our course. Right now we just added the Razer runtime
compilation when we created the project, but in future we will be adding more packages for using
SQL Server Entity Framework core and much more. Once we add that a new entry will
be made inside the item group. So that looks good for our project file.
With that, let's continue in the next video. style that we want to take a look
is inside the properties folder. We have launch settings dot JSON. This is the file
that confidence how the application will be run. And you can see there are multiple profiles that
are added by default. We have an IIS settings on the top which says that if you are using IIS
express to run the application, that application URL will be this and the SSL port will be 44317.
If we expand the profiles here, we have to profile epi ramp and IAS Express. These are the same
profiles that you can see if you hover on the down arrow icon right here. We have add the ramp
and IAS Express. In order to run the website, we can just hit this play button after selecting
the profile. If we select IIS Express here and run our website, it will launch the default
application inside the Windows directly with the 44317 vote number. Great, you can see that
it's working. Now we're finished up this and change our profile to happy Web. Let's
expand that. You can see here it is command name, which is project dotnet run messages, and we have
application URL. So this will run our application from command prompt. And from that
command prompt, it launches the processor. This time it is running on port 5001. So these
are two different ways of running the dotnet core application. Inside the profiles, we can have
environment variable, and other configuration. These are just two ways to run your application.
And we can modify them inside the launch settings dot JSON. The next thing that we
have here is www root folder. And in there, we have CSS, js, and lib folders. www root folder
will be the root directory of your application. That will be the directory that contains all of
your static files. So if you have CSS, JavaScript, images, PDF, files, libraries, all of them will
go inside the www root folder. Inside this www root folder, there will not be any code behind
file with the C sharp code. It will only have static files that will be used from the pages.
So make sure whenever you add any static files, it will go inside this www root folder. Next,
what we have here is the Pages folder. And that contains all the coding pages that are there in
the application. We will come back to that in the upcoming video. But the last file that I want to
discuss in this video is the app settings dot JSON file. Now what happens is in an application,
you are using many third party API's, and then you have to store some secrets. You can also have
connection strings that connects to the database, and so on. So all of those secret keys are
connection that you have, you will add them inside this app settings dot JSON file. As the name
suggests, it is a JSON file, which will have key value pairs. If you expand this, you will notice
that it's app settings dot development dot JSON. So you can have different app settings for
different environment. For production, you will have app setting start production dot JSON,
and so on, then based on the environment variable, it will automatically configure and
use that particular app settings file. This is really helpful because devlopment can
have a different connection string to database, as compared to preview, production
or staging. So it is already built in. And we will be adding our connection
string in this file in the upcoming videos. So with that, we have a brief overview of all the
files other than the Pages folder, and program.cs. Let's continue in the next video. Next we
have program.cs. This is the file that will be responsible for running the application. Once
we open program.cs You can see we have a variable builder where the web application dot create
builder is passed with the built in arguments. When you run with the dotnet command, you
can pass custom arguments here if you want. With that it will configure the application and
it will create the Web Application Builder object. Now in the previous video, we saw that we can
use dependency injection with dotnet core. When we want to register anything with our dependency
injection container. We will be doing that right here. So let's say if we want to register our
database or email or anything else, we will have to do that between the builder. And before we call
build on that builder object. So right here we are just adding one service to the container. We're
just builder dot services dot add razor pages. We are adding the razor pages to our container
because we are building the website here with razor pages. So we have to add that if you were
using MVC, then this would be add controllers with views. Now in the future videos when
we configure database in our project, and we add that to dependency injection We will
be adding a new service here in our container, our DB context. If you are working with any
version prior to dotnet, six, or even some of the initial preview versions of dotnet, six,
then this file was divided into a separate startup.cs class file. And the services that we
add to Container were inside a method configured services. And everything from line nine onwards
was inside a configure method. So what we have on the top is we will be adding services
to our container, then we need to configure request pipeline. And that pipeline will be
configured from the highlighted section of you might be wondering, what is this pipeline, the
pipeline specifies how application should respond to a web request. When your application
receives a request from the browser, that request goes back and forth through the
pipeline. Let me switch to the presentation here. We have different browsers here. And then we have
a pipeline. The pipeline specifies how application should respond to a request that is received.
When your application receives a request from the browser, that request goes through the pipeline.
In the pipeline, you can add items that you want, pipeline is made up of different middlewares
razor pages is a type of middleware itself. So if we want to build our website to be
built with razor pages, we will have to add the map razor pages to our middleware at the
example could be authentication, middleware, authorization, middleware, and so on. What exactly
happens is when your request will go through each of the middleware, it gets modified by them, and
eventually it is passed to the next middleware. If that is the last middleware in the pipeline,
the response is returned back to the server. Let's take a look at the few middlewares that we
have in our application. Let me switch back to the code here. And you can see in the pipeline, first
we are checking if it is development or not in the environment. If it is, then we are adding the
use developer exception page that will show you user friendly exceptions, so that you can debug
and solve them. But if it is not development, then we are just redirecting them to an error
page. The next middleware is HTTPS redirection. And then we have a middleware to use our static
files that are defined in www root folder. We also have a routing middleware, and we
have authorization middleware. And we add authentication to our project, we will have to add
a new middleware inside the program.cs as well. Then we have app dot map razor pages, this
will configure the routing of razor pages, and how the mapping will work in the
application. Based on this routing, it will be able to map the URL request to the
corresponding pages inside our Pages folder, then you should always keep in mind that
order of pipeline is extremely important. The way you write middlewares in the pipeline,
that is exactly how the request will be passed. So first of all thing will be done, then it checks
for authorization, and so on. So in this scenario, if you want to use authentication to
your pipeline, we have a middleware, which is app dot use authentication.
But if you do this, then it won't work. Because authentication middleware should always
come before you authorize a user. Because you only authorized a user that is authenticated.
That is the basic fundamentals of authentication and authorization. So if you place the pipeline
in some different order, that will break things. So with that brief overview of program.cs
class file, let's continue in the next video. One of the top level considerations for the tablet
part of a server side web application framework is how to match the URLs to the resources on the
server so that the correct one processes that request. The most straightforward approach is
that you map the URL to the physical files on the disk. And this approach has been implemented
by the ASP dotnet team for razor page framework. So the routing in ASP dotnet razor pages, maps
URL browse to the physical file on the disk. Now there are some rules on how razor page
framework matches the URLs to the files, and how it can be customized to give different
results if needed. The first rule is that razor pages needs a root folder. By default, the folder
has been named pages, and its location is inside the root folder of the web application. Also in
that folder, we will have a default document, which will be index.cs. HTML. So let's
go back to our application and see this in action. So the root folder is the Pages folder
that you can see here. And if we expand that, we have index dot CSS, HTML. Let
me run the application here and see what happens. Inside here, we are navigated to
the homepage. The home page that loads here is the default index dot css html inside the
Pages folder. If we click on privacy here, you can see the URL changes to privacy. And that
page is present directly inside the Pages folder. So the mapping of the URL is directly with
the location inside the Pages folder. Now, if we stop the application, and let's say we add a
new folder here, I will call that as test. And let me move privacy inside test. Let's click OK here.
And let's run the application one more time. This time, if you click on privacy, nothing happens.
The reason is the URL that has been configured inside the master page, which is underscored
layout, let me show that. Here the ASB page is defined that you have to look for a page,
which is privacy directly inside the folder. But that does not exist, because now we have
moved that to a test folder. So if we go back in order to navigate to the new location, it is
simple, we just need to find out the exact path from the Pages folder. So inside pages, we have a
folder of test. Inside there we have privacy. If we press enter, you can see it loads the privacy
page correctly. So you can see routing has direct mapping on how the files are exactly stored inside
the Pages folder. Let me stop the application, close everything. And let me move the
privacy page back to the Pages folder. I will also delete the test folder that we added.
Let's go back to our presentation. And here I have given some examples of how the mapping
works. So if the URL is just www.domain.com, it will map to the Pages folder and
the default page index.cs. HTML. If the URL is domain.com forward slash index, then
it will map to pages forward slash index.cs. HTML. And if it is domain.com forward slash account,
then by default, it will first look inside the Pages folder for a page with the name of
account.cs. HTML. And if that does not find it, then it will look into the Pages folder for
an account folder. And in there, it will see if there is index dot css html, which is the
default page. So routing in razor pages is pretty straightforward, as compared to MVC routing,
where we have models, views and controllers. Here in razor pages, it is direct
mapping to how the files are stored in the physical disk. So with that brief overview
of routing, let's continue in the next video. In the last video, we saw how routing works
in razor pages. In this video, let me walk you through all of the default pages that we have.
Inside our Pages folder, we have one shared folder that has underscored layout, which is the
default master page of the application. Here we have a header, we have a body where
we will be rendering all of the other pages. So they will have a header as well as a footer.
We will also have all the CSS and JavaScript that we want to include throughout all the pages.
We can include them in the master page directly. So what happens is inside render body we will
actually render any code that we have. Inside the other pages. Like we have index and privacy
pages, you can see we are displaying some text of welcome. And inside the privacy, we have the
header here that we are displaying with privacy policy. So if we run the application, again, let's
examine what is the homepage. So inside homepage, you see we have the header, we have the footer,
and whatever text we are displaying right here, inside the index page is displayed between the
header and footer, as we have defined inside the underscore layout. So all of the code that we have
here will actually go inside the render body right here. That's how master pages work. So that is our
underscored layout page. Next, we have underscore validation scripts partial. When a name starts
with underscore, that is usually a partial view on a partial page. Partial pages are like user
components. They cannot be accessed via a URL, but they are being called inside some other pages.
So it's like a table that you want in 10 pages, you just add that table in a partial
view. And then you call this partial view in all of these 10 files. And that table will
automatically be populated. In this partial view, we just have to script for validation. So in
future, in whichever page we want validation, we will be including this partial view. Also,
it is a good habit to name your partial views with an underscore and inside the shared folder.
So it's easy to find them when we have to. The next page that we have is underscore view
imports. Here you can define the common namespace that you have in your website. So let's say in
any of the pages if you have to add the USING statement many times you can define them in this
file and that will be like a global declaration. So once it is declared here, it is automatically
available in all the other files. One thing that you see here is we have added tag helpers. So
because of that, we will be able to use the built in tag helpers that the dotnet core team
has provided. If we go to the shared folder, underscored layout. And if we expand headers for
navigation, we are using the ASP page tag helpers. You can see we are not using the h ref tag here.
To navigate within razor pages, we have something called as a JSP page. The tag helpers for
ESP. We'll start with ESP, and then hyphen, and then the name of the tag helper. We can
obviously create custom tag helpers if we want. But the dotnet core team has provided
all of the default tag helpers to make programming super simple. We will
take a look at more tag helpers as we proceed with the course. But here we have added that
globally in our application in view inputs, that's why it will be available whenever we want
to use them. The next file is view start.cs. HTML. In this file, we will define what is
the master page of our application, you saw that underscore layout is being used as
the master page. But that is because we have that defined here. That underscore layout should be
the master page. Now what you can do is globally, you can have underscore layout as a master
page. But on the individual razor page, you can still use the same razor syntax and define
a new master page. If you want, you can define a different master page. But we will leave that
with underscored layout. The next view our page that we have is an error page. And this is the
page that is used to display the error messages when you face them in production application.
Next, what we have is the index page right here where we are displaying the text. Now you might
be wondering if you're coming from web forms, that with the files there was a code behind
file. If you are coming from an MVC background, you will be thinking where is the
controller? Where does the C sharp code goes with razor pages. We have a.cs file if you expand
that right here. Now this is not a code behind file. It is just the naming convention. Inside
here you will notice we have the index model and it inherits or implements the page model. Here
we have an on cat handler. And we will have an on post handler that we can add if needed. So here,
what we have to do is when this page is being called on cat, if we want to do something, we will
update that inside the on cat handlers. In MVC, we had action methods, but inside razor pages, we
call them as handlers. So we have on get handler, and on post handler, all of the code resides in
these two pages itself. cshtml has the page or UI code on what we have to display and.cs will have
the backend code, where if you want to retrieve some data, and pass that to the view, or page, we
can do that, when we are working with razor pages, that will be accurate page directive
at the top. And that will be a model that will be added here. This model you can see
it is indexed model. And if you go to the.cs html, that is the exact class name, it is indexed
model. Based on that it automatically binds both of this file. And it knows that this index.cs
html.cs is the page model on the index razor page. If this seems too much complicated, do not worry.
When we start coding the application, everything which start making much more sense. And similar to
index, we have a privacy page and a privacy page model. So those are all of the default pages that
are available inside the Pages folder. With that, let me close all of these tabs. And let's
take a look@program.cs file in the next video. With that, let me close all of the tabs
here. And let's continue in the next video. In this video, let's take a look at tag helpers.
Tag helpers are brand new to ASP. NET Core. Microsoft looked at the success around libraries
like Angular, React, and decided that implementing an Angular directive like experience in the new
ASP dotnet was so important to the adoption of dotnet core that they decided to create tag
helpers from crowns up. Even though there are similarities between Angular directives and tag
helpers, there is a major difference. Tag helpers are for server side rendering, while the Angular
JS directives are all about client side rendering. If you have worked with older versions of dotnet
core, we had something called as HTML helpers. They are still around a tag helpers are being
modern with the tag like approach. So it's much user friendly. Tag helpers are very focused around
the HTML element and are much more natural to us as compared to HTML helpers. We will be working
with Tag helpers many times in the application. But to just give you a brief overview, you can see
in the first tab here we have HTML helpers, and tag helpers simplifies all of them, because we can
use the existing label tag. And we will just add a Tag Helper as before. And we will find that to a
model. We have same Tag Helper right here as well. Then in the last example, here I am displaying tag
helpers where previously we were using HTML dot begin form. And now within the same form tag, we
have the tag helpers of where it should be posted. So you can see things are getting much more
simpler when we are using Tag helpers. That being said, if you're coming to dotnet, brand
new, and you have never worked with HTML helpers, this is even better. You do not have to worry
about the old syntax and what is different. We will be working with Tag
helpers in the upcoming videos. But I just wanted to give you a brief snippet
of what tag helpers are and how they look like when we are using the same tags, which is to use
the ASP hyphen, and then the Tag Helper name. That being said, we will explore all of this
in much more details in the upcoming videos. When you will be working with a dotnet
core application, you will see the return type of action result. And it does not
matter if you're using an MVC application or a razor page application. In both the cases
you can see we have eye Action Result In MVC, we are returning back view in this
example. And in razor PAGE PAGE handler, we are returning back to the page. But
the return type is I action result. I action result is a generic type that implements
all of the other return types. Now, if you want to be explicit about the return type in both of these
cases, then that would look something like this. If the return type is view, you can write View
Result. But in razor pages, when we return back to page, you can write page result. So now what
is the advantage of action result? So first, let's understand some theory. So, action result
is a pattern class for many of the derived classes that have associated helpers. The I action
result return type is appropriate when multiple action results return type are possible in
an action. Let's take a look at some of the helpers and action wizard. So first, let's
take a look at what is there in razor pages. A razor page can return content file, not
found page a partial result, and redirect to different pages. For all of them, we have returned
types like content result, file content result, not found result, page result, partial result, and
so on. If you are working with an MVC application, we can return back views, partial views, we can
redirect to action, return JSON and so on. So if you are returning any one of these, then you
can use the individual return types for a result based on the helper method. But what if
you were returning something like this? Right here in MVC, you can see we are returning if
true, let's imagine that was some condition here. Based on that if that condition is
true, you want to redirect to action, else you want to return to view this time you
cannot have two different return types. If you use View Result here, return view is working,
but redirect to action will throw an error. Similarly, if you use redirect to action result,
then redirect to action works. But return view will give you better if you are working on
razor pages and you have the same situation. If you use page result, and return page will
work. But redirect to page will fail. And if you use redirect to page result, then return page
will fail. So what is the solution to all of this, the solution is to use I Action Result input
the places because this is a parent class. So it does not care which of its implementation
has been returned, it will be able to handle all of them. So that is a brief overview on how
action result will help us with the return type from action method in MVC application or
page handlers in a razor page application. When we are working with any
project, we first need a database and that is the heart of the application. In
this case, also we will have to add a database and we will be doing that using SQL Server. But
for database I will be using Entity Framework core code first. And in that we create a model. And
based on that model, we create a database table. So first, we will have to create a model in
our project. So we will create a new folder, call it as model inside there, we will create
our first class file, which will be category. Inside this class, we will have to create all
the properties for all the columns that we want. In the table. Let's say we want three columns,
we want name of the category we want to display order. And the last one will actually be the most
important one. All the tables require a primary key. So we will be adding an ID column which will
be identity column in SQL Server. What I mean by that is when we create any record, we do not have
to pass that ID, it will automatically increment by one every time a new record is created. And
that will be unique. So for all the three columns, we will have to create three properties.
The first one should be the primary key so far that we will type drop here, which
is a snippet to create properties inside Visual Studio. So we type prop And we press tab
two times, it creates an integer by default, that's fine, we want to call that as ID. The next
property that we want is name of the category, which will be a string. And we will call
that as name. The last one will be an integer of display order. So with this, we have created
a class, which will be our table in the database, and it will have three properties, all three
columns. Now, before we magically create the table, we need to do some more configuration.
Let's take a look at that in the next video. We will be using Entity Framework core to create
the table and populate details inside there. But when we create a table, we
need to tell Entity Framework core that this column will be an identity column, and
it will be a primary key. Let's say we also want to add a validation that this name should be
required and not null property inside database. So how can we add all of those validations and
requirements, we have many attributes that are available to define all of the requirements. And
all of them are defined inside data annotations. So before the property here, we can give that
an attribute inside a square bracket. The attribute to make this column a primary key is key
itself, you will have to press Control dot here to add the USING statement. And you will press
enter. Now by default, if a property name is ID, Entity Framework core automatically makes it a
primary key. So this is optional. But if your name was something different, like let's say
you wanted to make display order a primary key, then you will have to explicitly
say that, but if it is an ID, and if you have not defined any primary key, then
it will automatically set that as a primary key. That is good to know. But I always like to
explicitly define so that when someone opens up that model, they can directly say which one is the
primary key. Next, we want name to be required. And for that we have an attribute which is
required. That will make sure that name is a required property when the SQL statement is
created to actually create this category table, which we will see in the upcoming videos. Right
now things are pretty simple. We created a class file, it has few properties, and be added some
easy looking data annotations for our requirement. How will we actually create this table and
database that is the main question that we will have to do some configuration, like adding
a connection string to our SQL Server, adding some new get packages. So that we can use Entity
Framework core and SQL server without project. Don't be overwhelmed. Let's get started by
adding the connection string in the next video. In this video, we have to add a connection
string. So before we do that, let me open up SQL Server Management Studio. Here the first
thing that you require is a server name. Now many times a dot will work for
localhost. But if that does not work, you can try local DB MSSQL local DB, whichever
server name works for you where you can connect, that is the one that you will use. I'm going
to use just a tad because that is working. And that's how I have configured SQL Server. I don't
want the long one. So I will just use the dunk. Once you are able to connect here to SQL Server,
we will go back to our project. And we will add our connection string. Now where exactly will be
at that connection string. All of the settings like secrets that you have in the application,
you should add that inside app settings dot JSON. If you examine we also have development here. So
if you have more versions like production staging preview, for each one of them, we might have
different settings. So you can add different settings inside the individual file. And based
on the environment name, it will automatically use the correct settings. For at localhost,
we will use App Settings dot JSON. So inside app settings dot JSON if you examine we
have some key value configuration. We have a blog. Inside that we have another blog. And finally
we have key value settings. When we are Working with connection string, we can directly
create a key value pair right here. But connection string is something that is common across
all the application. That's why dotnet core team has provided a special plug that you
can use for connection strings if you want. Using that will make things a little simple.
But if you want to go with a custom blog, that will also work, you will just have to put some
extra effort to retrieve the connection string, we will use the default connection string blog
that is provided with dotnet core. And that is connection strings. Once you press enter,
then you will notice the curly brackets, this means it is a block in there,
we can write our connection string, you can give that any key name that you want,
I'm going to call this default connection. And after a colon in the double quotes,
you will write your connection string. The first parameter here will be the server name
you will write equal to and then whatever server you are able to connect in SQL Server,
copy that and write that here. I'm using a.so That is what I will use, then we will add
a semicolon, and we will add the database name. You can call your database whatever you want,
I'm going to use abi. Finally, we will have the security, which is trusted connection is
equal to drill. That's all that we need for connection string. That Crusher connection
is because I'm using Windows authentication to connect to my SQL Server. So with that we
have added connection string in our project. Back we need to configure our DB context. So
we can use this connection string and configure Entity Framework core in our application. It might
seem daunting in the beginning, but do not worry. Once we set everything up, it will all make
sense. Let's continue in the next video. We have our connection string,
we have our category model, how do we add this model to database. In order
to do that, we will require Entity Framework core in our project. So you will right click on your
project and you can select Manage nougat packages. Once you go there, we will have to install the
package inside the Browse. We will search for Entity Framework core, we have the first package
here and I have enabled the include pre release, because right now dot 10 Six is in preview. So
we will install that package in our project. Now while we are here, I know we will be using SQL
Server and that requires its own package as well. So make sure you search for SQL and we
have Microsoft dot Entity Framework core dot SQL Server. Now when you install nougat
packages, if you are using the Preview version, or even if you are using the older version, always
make sure that all the packages in your project must be of the same version. If you install one
package in Preview seven and other in previous six, it might not work or if you installed one
package in dotnet five and other in dotnet six, it still might not work so it has to be the same
version or else you might face issues later on. That being said I will install both the nougat
packages, so that we can add the configuration of Entity Framework core in our project perfect
we will close the nougat package manager and now we need to create a DB context so that we can
interact with Entity Framework core for database. So, inside the project, we will
right click add a new folder for data inside there we will have to create our
class file for accessing the DB context you can call this anything you want. I like to
call that application DB context. Now this file will implement the DB context or it will be like
a data layer that will connect our application with the database. So it must implement the DB
context class inside Entity Framework core. So we will add a colon here and we will write DB
context. Now you will see the red squiggly lines because it does not find or does not know what is
this DB context. If you press Control dot here, you will see the USING statement inside
Microsoft dot Entity Framework core and DB context is defined inside the Entity
Framework core to access and manage the database. When we are creating a DB context, we need to
get the connection string As options, then once you have configured this, inside this class, we
will be creating DB set for all the tables that we found in our database. So the first table that
we want is the category model that we created. So in order to create that table, you will have
to create a DB set. So we will say public DB set, we will write the model name, which is category,
you will have to press control.to Add the USING statement. And then here, whatever name you give
will be the name of the actual database. I will call it the same category. And we will have getter
and setter. So here, if you named it category one, your table name will be category one. So this
is actually the name of the table that you want inside your database, or application DB context
looks good. But we need to do one thing, we have a DB context in our project. And
we have connection string inside our app settings dot JSON, we need to configure this DB
context to use our connection string. That way it will know how it can connect to the database.
Let's see how we can do that in the next video. Now we need to add the connecting bridge
between our DB context and connection string. So we need to tell our application that, hey,
you need to use this application DB context to interact as a DB context. And you have to use
the SQL Server with connection string that is inside app settings dot JSON. So all of that
mapping will be done inside program.cs where we are adding services to the container. The reason
we are adding that as a service here is once we add it here, we can extract that and use it with
dependency injection throughout the application. So we will be adding DB context as a service in
our application. Previously, in dotnet, five, all of this was done inside startup.cs class file.
But starting with dotnet, six, they have combined with the startup and program.cs into one single
file. So here we are adding all the services to the container. And then we are configuring
the request pipeline. So now we no longer need multiple files, everything is much cleaner.
So in order to add service to our container, we will say builder dot services. And the
service that we want to add is dB context. So we want to configure the DB context, which
expects a class name. So here we have to tell that which class in our application is implementing
DB context. That is application DB context. Once you write that, you will press control.to
Add the USING statement for ABI web dot data. Then here, we have to pass the options.
So we'll say options here goes to. And we will say options.we have used SQL Server
inside the Entity Framework core namespace. That way, we are saying that for this DB context for
database, we want to use SQL Server. And inside here, we have to give the connection string.
Now how can we extract our connection string from App Settings dot JSON. I said before that
connection string is a special block that is given by the dotnet core team. So that's why they
have given a special method to access all the key values inside that special block. You
can do that by using builder dot configuration dot they have given a method get connection
string that will look for a key name inside app settings dot JSON. So inside connection
strings, what is the key name we should look for? We should look for a key with the name of default
connection and we want its value. So we will copy default connection and paste that in the key
name. When we use get connection string that will actually retrieve the connection
string and configure our DB context. Now here you can see that application DB context
we are passing the options. So inside our class where we have the application DB context, we
should retrieve that options and pass that to the base class of DB context. So here we will
have constructor using the snippet CT or our TAB TAB. And with this class, we will receive DB
context options on application DB context. We will call that as options. And all we want
to do is pass that on to the base class of DB context. Pretty simple and straightforward. But
this line of code is very critical. If you do not do that your connection will not work. Now, right
now, it might seem that we are doing lots of magic things with setting up application DB context,
some code in program.cs. And we are retrieving our connection string from the app settings. But
this is very basic connection that you have to do with all dotnet core applications, when you
want to use and configure Entity Framework core. So this can be treated as basic steps that you
should remember and memorize. But what we are doing inside program.cs, we are just adding
items to the container, so that we can extract and use with the help of dependency injection. As
we proceed with the course dependency injection will make much more sense. And you will
see how easy it is by adding things to dependency injection to extract when we want
to use them. So with that basic configuration, we are almost there. Next thing we have to
do is we just need to create our database, we have all the configuration that is ready. Let's
see how we can accomplish that in the next video. Now we need to add the connecting bridge between
our DB context and connection string. So we need to tell our application that, hey, you need
to use this application DB context to interact as a DB context. And you have to use the
SQL Server with connection string that is inside app settings dot JSON. So all of
that mapping will be done inside program.cs, where we are adding services to the container.
The reason we are adding that as a service here is once we add it here, we can extract that
and use it with dependency injection throughout the application. So we will be adding
DB context as a service in our application. Now previously, in dotnet, five, all of this was
done inside startup.cs class file. But starting with dotnet, six, they have combined both startup
and program.cs into one single file. So here we are adding all the services to the container.
And then we are requesting or configuring. And then we are configuring the request pipeline.
So now we no longer need multiple files, everything is much cleaner. So in
order to add service to our container, we will say builder dot services. And the
service that we want to add is dB context. So we want to configure the DB context, which
expects a class name. So here we have to tell that which class in our application is implementing
DB context. That is application DB context. So you will press control. Once you write that, you
will press control.to Add the USING statements for add the web dot data, then here, we have to pass
the options. So we'll set options here goes to and we will say options.we have used SQL
Server inside the Entity Framework core namespace. That way, we are saying
that for this DB context for database, we want to use SQL Server. And inside here, we
have to give the connection string. Now how can we extract our connection string from App
Settings dot JSON. I said before that connection string is a special block that
is given by the dotnet core team. So that's why they have given a special method to access
all the key values inside that special block. You can do that by using builder dot configuration
dot they have given a method get connection string that will retrieve all the that will look
for a key name inside app settings dot JSON. So inside connection strings, what is the key
name we should look for? We should look for a key with the name of default connection and
we want its value. So we will copy default connection and paste that in the key name. When
we use get connection string. That will actually that will actually that will actually retrieve the
connection string and configure our DB context. Now here you can see that application DB context,
we are passing the options. So inside our class, where we have the application DB context, we
should retrieve that options, and pass that to the base class of DB context. So here, we will have
constructor using the snippet CT or our cap tab. And with this class, we will receive DB
context options on application DB context. We'll call that as options. And all we want to do
is pass that on to the base class of DB context. Pretty simple and straightforward. But this line
of code is very critical. If you do not do that your connection will not work. Now, right now, it
might seem that we are doing lots of magic things with setting up application DB context, some
code in program.cs. And we are retrieving our connection string with apps from the App settings.
But this is very basic connection that you have to do with all dotnet core applications, when you
want to use when you want to use and configure Entity Framework core. So this can be treated as
basic steps that you should remember and memorize. But what we are doing inside program.cs,
we are just adding items to the container, so that we can extract and use with
the help of dependency injection. As we proceed with the course dependency injection
will make much more sense. And you will see how easy it is by adding things to dependency
injection to extract when we want to use them. So with that basic configuration, we are
almost there. Next thing we have to do is we just need to create our database, we have all the
configuration that is ready. Let's see how we can accomplish that from the next video. In the next
video that all the configuration is done, let's finally create our database. Let me switch back to
SQL Server. And here if you examine the database, we do not have any ABI database. So we have
connection string and everything in place. In order to make connection with Entity Framework
and actually create SQL, we will be adding migrations, what migrations will do is it
will see that inside application DB context, we have a DB set on category. So it will write a
script to actually generate SQL that will create this table it is pretty fancy and everything
is optimized. Let me show you how we can run migration first, and then it will make sense
there are two commands that you should remember. In order to run migration, we will go to Tools
NuGet package manager and Package Manager console. Inside here, we will have to write a
command to actually create migration and that command is add migration and we have
to give our migration a meaningful name. So we will call this Add category to dB that is what
we are doing, we added just category inside our application DB context. So let me press
Enter. And let me show you what error we get. We get the error the term add migration is
not recognized. Now you remember we added NuGet packages of Entity Framework core and SQL
server one more NuGet package is needed for this, I want you to search this error and
find out what is the nougat package. Okay, I hope you were able to
do that. If you just copy this, go to Google paste that the first one here if
you scroll down, there should be the package name right here. So, these are small things that
you will run into when you are developing. And you should always take Google as your
first help station because it is possible that someone else has faced this error and
that will help you. So you will search for that new get package. Make sure the version
is same and you will install that for a fact that is done. Let me close that. We will
go to package manager console and run the same command one more time. This time it will create a
new folder of migration in your solution explorer and load the migrations. Great You can see a
new migration has been created. And there is a new folder with the name of migration. So let's
analyze on what we are doing inside the migration. You can see we have an up method and a down
method. Down method is basically rolling back the changes that we are doing if something
fails. So let's ignore that. Insert the up method, we have migration builder, and we are saying
that create a table with the name of category. In that table, we want columns, the first
column will be ID column of type integer nullable is false. And make sure that it is a SQL
Server identity column. You can see with the key attribute, it is configuring everything for us.
And the next column name it is saying that make sure that is not a nullable column. That is what
we added as required. The last column is display order, that is also nullable. False, but the
reason behind that is it is of type integer. And then in the constraint, you can see we have a
primary key on the ID column with the name of PK underscore category. So here you can see it is
doing everything that we wanted, you won't be able to see the raw SQL that is being executed, but it
is optimized. But in order to run this migration, and see the table in database, we need to add
one more command. So tools NuGet Package Manager console, and the command is update database. Let's
press enter. What it does first is it will check at that connection string does that database
exist. If it does, then it will just push the migration that we added. If it does not, then
it will create that database. And then it will run the migration. So now the database should be
created. And in there, we will have two tables. We have our category table, which will
have the three columns that we created. Perfect. And we have a table which keeps track
of all the migrations that have been applied. So let's examine the EF migrations history.
And you can see it has the migration ID, which is name of the migration that you
can see here, and the product version. That way Entity framework code knows that this
migration has already been applied. So next time, when you run the command update database, it
will not reapply this migration, pretty smart to track everything that has been done with Entity
Framework. So great with that our database has been created successfully. Let me close everything
here. And let's continue from the next video. Now we have our category table that has been
created inside the database. So what we want to do is we want to create a new page where
we can display all the categories. When we are working with razor pages, it will be
inside the Pages folder as compared to views in MVC. So inside pages, we have the homepage,
which is index.cs. HTML. We want to create pages for listing all the categories, creating
category, editing category and deleting category. Rather than cluttering everything in one
place, we will create a new folder inside pages. I will name the folder as categories.
And in there, we will create a new razor page. The first page that we want to create will be
used to display a list of all the categories. So we can name that as index, we will select
the razor page empty here, because we want to start with a clean and empty page. Rather
than working with a template. So select Empty, and we will hit Add Button name of the razor
page, we will keep that as index.cs html. Let's add them. As soon as you add that you will
notice two files were added. One is the CS file. And we have the CS HTML the.cs file will
be the file where we have page model for our index page. You can see the model that
is being referenced here is inside ABI web pages, categories index model. And this particular
namespace will be the namespace that you see on top here. So that is how it is binding everything
together. And we have our class index model. Now we use Entity framework code to add
migrations to create our category table, which was inside model and our DB
context. was application DB context, inside program.cs. We've registered that service
in our container. Since we have registered the service, whenever we have to access database, we
do not have to create a new object of application DB context. What happens here is the service
is already available in the container. So we just need to tell our container that, hey, I
need to use the DB context to access database. So give me an implementation of this class. How do
you do that, that will be done using constructor inside the CS file, we need to create a read
only application DB context. And we'll add the USING statement. I will call that underscore
TB. Now we want an implementation of this class using dependency injection. That will be
done inside constructor. So we'll type C to our class tap twice. This is a snippet to
create constructor quickly in Visual Studio. Now, if you have registered anything inside
the container and you want its implementation, you simply tell here the implementation that
you want. So we will write that we want an implementation of application DB context and give
that to us in a variable with the name of dB, we will assign our private variable which is
underscore dB, the value of dB. So now our underscore DB will have an implementation
that already connects to the database. And we can use that inside the onCreate method,
we need to retrieve list of all the categories. In order to retrieve that, we need to create a
property that will hold all the category list. So on top here, we can create an IEnumerable on
category. And let's call that categories. Next thing that we have to do is we need to populate
this Categories list. So this we need to populate from the database. So we'll say underscore dB.
And with Entity Framework core, when you write dot here, it will display all of the tables or DB
sets that we added. So if you scroll down here, you should see the category DB set that we
added. So we want to retrieve underscore DB dot categories. This will retrieve all the list
of categories. We did not have to write any fancy SQL like select star from Categories table, we
did not have to open a connection, we did not have to close connection, no cleanup was needed.
Entity framework code takes care of everything. And we just access DB context. And then on
category, we have multiple methods to create, update, delete, and much more. But if
you just say underscore DB dot category, it will automatically retrieve all of the
categories and store that in this way the table I get method looks good inside the
index page model for categories. Now what I want to do is inside shared, we have
underscored layout, we can navigate to two pages, we have index and privacy. Rather than privacy,
I want to navigate inside the categories folder, we have the index page. Since we want to
go in folder, we will not use the forward slash we can directly say categories. And
then forward slash what is the page name that is index. So here we have to use the
exact graph that we have in folder structure. If you were using MVC, you have controllers
and action method. But with razor pages, everything is simple. The actual way in which the
folders are organized will be the exact route. So routing is pretty simple in razor pages, we
will change the link here to display categories. And let me save this run the application. Right now it is running things using the ABI web
profile. But we will change that to IIS express in just a second. But if we go back, we have the
Categories tab here. And you can see the URL in the bottom left. It displays the categories.
Let's hit this button and see what happens. We see an index page here, but no data is
displayed. We don't want to work with data right now. Let's go to our code behind
here. And let me add a debugging point. Let's go back and let me just refresh the
page. We hit our breakpoint. If I press F 10 It will take us to the next line. And then if
we examine what got populated in our categories, it will be empty, because we do not have
any records. So it yielded no result. Let me add a breakpoint on this line, remove the
one before. And let me switch to SQL Server, we can keep our application running. Actually,
I can hit the Continue button to go back. inside SQL Server, let me expand the database
tables. Let's directly edit the top 200 rows. Let me create a name, test and display order to.
So we have one record in our database. Now, if we go back to the application, and hit categories
one more time, it hits our breakpoint again, this time, we should see one record
that is being retrieved. And perfect, we see all the details populated. So with that,
you can see we are successfully able to retrieve all of the records four categories from database.
In the next video, let's work on displaying these categories inside the index page right here. Now
that we have seen how to retrieve the categories inside the get handler, we need to
actually display that in the razor page. So if we go back to index.cs, HTML, this is the
index of categories and not off the main page. So inside the index of categories, we want to
display all of the categories. If you have only worked with web forms, and never work with razor
pages, inside razor pages, you can have HTML code as well as C sharp code. So you can have if else
you can create variables, assign them values, as well as HTML directly at one place. So let
me add a div here give it a class of container and I will give it padding three. These are just
bootstrap classes to creating a container. And inside there we will create a row. So we will give
it bootstrap class of row padding top of four. This will be one row on the complete screen. Now
that one row we want to divide into pieces. First, on the left hand side, I want to display a title.
Since bootstrap divides that row in 12 parts, if we want to divide those 12 parts into two
pieces. For the left hand side, we will have six PS, and right hand side we will have six PS. So we
will have div here, give it a class of column six. To combine the first six pieces in one single
element. Here we will display an h2 heading, and we will give it a bootstrap class of text primary.
We want to display here the heading which is category list. That looks good. Here we will have
the later part, which is div of class column sex. And we will add buttons inside this div later on.
This looks good. Let me add some space. So two br tags. And then we want to add a table to display
our categories. So we will use a table tag. Inside this table, we will have a T head for
header. Inside the head, we will have TR n th tags. This is just HTML tags that we are
working with. Inside the first heading, we want to display the category name and
inside the next year we want to display the display order. Now that is good for
the headings, we want to have a body where we will be displaying the actual values.
Now if we have 10 entries inside category, inside T body, we will have a TR tag and TD
just like we have the edge inside the heading. Here we want to display the actual value of
category name. And then we will have another TD which will have value off display order. Now
if we have 10 categories inside database, we want this TR to repeat 10 times because we want to
display all the category name and display order. So if you were working with C sharp you would
be using for each loop. We will do the same right here. In order to use a C sharp code we
need to add sign and then we can just write for each statement. With for each we need an object to
iterate. So we will say variable obj in and what we want to iterate on will be inside our index
model. This index model represents what we have in the CS file. In order to show you if you right
click here. And if you click go to definition, it takes us here and you can see in here
we have the variable four categories. So we can access this cat categories. Since it
is an IEnumerable, we will iterate through that. Because inside the cat, we are already populating
that categories. So we should be good. So back to the UI, we want to iterate over that I enumerable
of category. To access this model that we have right here, inside the lowercase m, we will have
to use a key word, which is model, but this time, the M will be capital. So whatever we
have inside the smaller case model here, anywhere inside the view, or page, if you want
to access that, you will use the capital M model. So if you press model dot, you can see all the
models that are available inside the CS file. So we want to iterate over the model dot categories.
And we will have a curly bracket here. So each categories inside the model categories will have a
temporary name of Obj. This is how for each works. So for each one of the object, we want to display
a TR tag, and we want to display the values to display value, we need to access the obj variable
right here. So again, we will use the Add sign obj dot, and we will see all the properties that
are available. We want to select name from there. The next one that we have is display order.
So we can say obj dot display order, we will add some width on both the td tags. With that in
place. Let me save this and run the application. If we go to our categories, we
have the category list heading. And we have a table here. But I want
to give it some bootstrap classes. So we can go back and on the table tag right
here, we can add class is equal to I will add three bootstrap classes of Table Table bordered
and table striped. Also, I will give it a style of word 100%. Now when we are making changes
inside CSS, or even anything inside the UI side of cshtml, once we save it, we can go back and
actually refresh, and it should make those changes visible. But right now it is not working. We
already added the razor runtime compilation for this particular package. But the reason
that is not working is right now there is a bug, and you have to manually add a statement. So for
that, we will have to go to program.cs where it is adding the razor pages, you also have to add
a command here, add razor runtime compilation, they should have been done automatically, because
we selected the razor pages. But I believe since dotnet six is in preview, they will fix this down
the road. But if this is not present, at that end, let's run the project one more time. If you go
to categories, now, you will see a nice table. With this, you can see how we are able to display
all of the categories inside our razor page that we created. If you examine the URL, here it is
only categories and not index. Because index is there by default. If you write index manually and
press enter, it will load the same page. Perfect. With that, let's continue in the next
video. But before that, let me change the setting here to use IIS Express. That way,
we don't have the command prompt every time. Our index page is working as expected
for categories. And inside the CSS file, we have the get handler. Before I proceed
on the next test to create a category, let me switch back to database here. And we will
write a query. So select top 1000. And let me just delete the record. So we'll delete the category
that was present. And now there is no categories. And once we make that change, if we go back
and run the application, perfect, everything is clean. Now I want to add a button here to create
a category. We have not added that page right now that we do that. Let's go back to one index here.
And we'll have to space inside the right hand side of the category list. So we want an anchor
tag. Now we want to go to a new page that we will create inside the categories folder with
the name of create so far that that tag helpers, the tag helpers that we want to use here
is ASP page. If you were working with MVC, then you will use actually and controllers. But
with Razer pages, everything will be ASP page, we want to navigate to a new page with the
name of create. Since this is inside the same folder of categories, we do not have
to explicitly mentioned here the categories before create page, it will understand that by
default, so we want to go to a new page of create. And we want to give it a class of btn btn
primary inside the anchor tag, we want to display create row category. Now the application
is running and we enable the laser runtime. So if you do AVX, five at your display the button
if you click here, nothing happens. This does not mean that your link is broken. Nothing is
happening here because that page does not exist. If this was an MVC application, it will take you
to a page not found. But with razor pages it has different if the link is broken, it does not
display or not found, it will just stay there. So in the next video, let's create the
new razor page to create a new category. Just like we added the index page to list all
the categories, we need to add a new razor page inside the categories folder to create
category. So with an add new razor page, empty looks good. This time, you have to call this
ask create. You can see here we are creating a razor page and not a razor view. Razor views
are used in MVC application and they do not have a page model. We will create a razor page and
let's hit the Add button. This time the model you can see it is create model. And if you examine
the.cs You will see the class is create model. So that is how it links both of the file. Now
right now we have the on get handler. Inside the on get handler of index we are retrieving all
of the categories to display inside the page. When we are creating a category, we do not have to
populate any information. Inside the Create Page, we will just have an empty text box for user to
enter the display order and name of the category so that will be empty. Since we do not have to
do anything inside the on cat. Let's work on the view itself. Inside view we will have a form
in which user will enter name and display order and they will hit the submit button. So we will
have a form tag here. This will be a method post. Then we will add some bootstrap classes, we will add a div give it a class of
border padding three margin top of four. Inside there, I will add another div give it a
class of row and padding bottom of two. And I will just add a heading h2 that will display
create category and an HR for a horizontal line. After this div, I will add another
div give it a class of margin bottom three. And in here we want to display the label which
is name. And then we want an input field of type text. I will copy this and paste it one more
time. Next property that I want is display order and type will be text. Of course in HTML,
you remember we give that some named like display order. The first one here, we
can give it a name of category name. After that, we will have a button of type submit.
And we can give it some bootstrap classes of btn btn primary and a constant width of 150 pixels.
Let's call this button as create. So perfect. Now we have a form to create our category.
Let's run the project and take a look at that. Click on categories and now if
we select create new category, we see our new form. Let's continue
with the form in the next video. Now in a typical web form, what happens so we have
a name for this input field and display order. So when we post that inside there, we will try to
extract that based on the name and we will see what value was appended. But with razor pages, we
have something special we can bind this input text directly to a category model and then we can use
that model or rather have those values available inside the post handler. So we will be binding
this to a model In order to find a UI to a model, we have to create that property or model inside
the model of the UI, which is create model that is inside the cshtml.cs. So just like inside
index, we created an IEnumerable of category, and then be binded. That right here to extract
using model dot categories, we can do something similar inside create.cs. HTML, we do not want an
AI enumerable, we just want one single category. So we will create a category property. And we
can access this property inside our UI right here. Inside the index dot css html, we saw the
Tag Helper ASP page that is used to redirect. Similarly, we have a Tag Helper that binds a
property. And that is ASP four, here, we have to write the name inside our model. To extract that
we will need the Add sign we will say model dot and that is inside category. Inside category, this
is for name. And with that, we also do not have to define any type or name, everything will be done
automatically and all the bindings will be done, we will just add some bootstrap classes for
styling. Now this will create an input field. Similarly, we have something for label.
So if we have a label here, and if we use ASP for, we can use accurate model here. But
if you do not want to use the activate model, when you are using ASP for, it is smart enough to
automatically bind the models. So you can directly say category if you want and dot name. That is
pretty simple. But if you don't see that option, you can always use at the model to access
everything inside the model that is defined right here. So we are just adding a label
here with the Tag Helper off category name. Let me copy these two lines and paste them or
display order as well, we will just have to change the property name to display order. With that,
let me save the changes, go back and refresh. And we see this error because we also modified the.cs
file, we will actually have to rerun the project. If it was just the cshtml or the UI,
then we do not have to rerun our project. So let's go to categories here. And
if we hit create new categories, we have name and display order. Let me
press F 12. Here and inspect element. You can see on this element, it automatically
populates the ID and Name. And you can see name is category dot name. So it does all of the binding
along with the type equals to text automatically. So you can see how life gets easy with Tag
helpers. Now once we enter any of the details here, and we hit the submit button, we want to
fetch those details inside the post handler. We only have a cat handler right now. So let's add
a post handler and continue from the next video. Now we need to create an on post handler.
By default only cat handlers are created. If you were working in an MVC and woman,
then you would create an own post action method. But in razor pages, we create handlers. So
creating handlers is simple. We will call public and then the return type, I want to make this an
async method. So I will add async. And task of I action result. I action result I'm using because
I want to return to some page or redirect to a view. So that will be the return type. And we will
call this on post. When we have to name handlers, it will always start with the keyword on and then
we have the HTTP verb that this handler will do. This handler will support the post action method.
That's why we will call on post handler. Now if you have multiple post handlers that you want
in a razor page, you can give this a handler name after the post. Like you can say on Post
Create. And then you can have on post edit, that can be to post handlers. But right now
we just want to create one post handler to fetch the details that user entered and
create that category inside the database. So here on post, we will receive a category
object. Let me call that as category. And let's create that inside our database. In order
to work with database, we need dependency injection with the application DB context. So
first, let me create an application DB context, we will do control.on The USING statement. And I
will require a constructor. So C, D or R. And I will get grief that from dependency injection
and assign that to my local variable. Then we want to create the category that we
received right here. So far that we will be using underscore dB. And we have to define our model
which has category on there we have more methods, we have methods to add, remove, update, and much
more. The first thing that we want to do is add. Now, you can use this ADD, but we have added
the async method. So, let's use the async implementation add a sink in that it expects a
category entity that we have fetched with our on post. So, we will add that now, when you are
using a sink method, we will have to populate that before we proceed further. When you write this
one line, it is telling Entity Framework that hey, this is the category object that you
have to add inside the category table. But it does not tell Entity Framework
to go and do that right now. In order to tell that there is a different
statement, we will say await underscore DB dot behalf SAVE CHANGES A sink. When you write the
SAVE CHANGES async. At that time, it gets all of the items that it has to change inside database
and makes all of those changes. So if you forget to write save changes, it knows that it has to do
that. But it will not save them to the database and when it redirects or something that will be
lost. So always make sure to save the changes. Once the changes are saved, we want to return
back to the Index page. You see it displays redirect to action. But that is not valid in our
application. Because we are using razor pages. So with razor pages, we have redirect to page.
And we want to redirect to the Index page. With that, let me save this at a debugging
point. And let me restart the application. Since we've made changes to the code
behind. Let's go to our categories here. We have create category, let me enter test
and to display order, hit the Create button. Now as soon as you do that, if you examine the
category, you can see they are populated. Let's hit continue here. And great that is created.
So with this, we are able to create categories inside our application. But I want to show you
one more thing. Let me close the application. And here we are fetching the category
object. And we are adding that we already have a model here for category.
So it is something that is redundant. To avoid that dotnet core team has provided
a special attribute, which is bind property. When you use bind property, you no longer have to
write it here, it automatically does the binding with the UI that we have on the screen.
And that will be populated inside the same object. So then we can use this category
and add that like this. This will make things much simpler. Let's run the application
and try to create one more category. So let's create test one this time.
And great. It is working as expected. Now this is not needed right now. But
I'd like to show you something else. Let's say you had three properties that you are
binding here and inside the post. In that case, you will have to write Pyne property on each one
of them from dotnet core 2.1, they have added a special property that you can apply directly
at the class level that is bind properties. What that will do is all the properties that
you have here and you're using inside the UI, it will bind all of them automatically so that you
do not have to individually add bind property. So with that, if we run the application or create
should still work the same way. Even though we just have one category, it's good to know that we
have that option available if needed. Let's try to create a new category attached to here.
And great it's working So with this create functionality is working as expected. Let's add
some styling here and continue. On the next video. I want to change the themes that we are using
in our application. So if we go to Google, and if we search for boots watch.com. This provides
free themes for Bootstrap. If you scroll down, there are other themes that are available. I
will go with the sidebar theme for this course, you can download the minified version or
the bootstrap dot css. Let me download the bootstrap dot css. I will copy everything
that we have open here. Let me minimize this. And we'll stop the application. Let me add a
new CSS right here. This will be style sheet. I will call this boot swatch sidebar. Let's add
that. And I will paste it here. Let me close this. And if you open site dot css, they have added
some different color for btn primary, I will remove those two. That looks good. Now if we go
to underscored layout, we can modify the bootstrap reference that we have here to the new CSS. So
inside the CSS folder, we have bootsplash cyborg. Let me scroll down where we are using the
bootstrap je s bundle. Let's go back here to bootstrap.com. And let's scroll down. We have
the CDN for J S with popper. Let me copy this, and we'll paste that right here. This will make
sure that we are using the latest one for our course. Lastly, if I go back with Bootstrap,
we also have icons that are available to us, you can see there are quite a few icons that
we can use in our application. To get started, let's go to the install tab. And we have the CDN
that we can copy. Let me paste that with the style sheets. So perfect. With that we'll be able to use
icons that are available with Bootstrap. Now that the CSS is updated, let's run the project
and see what happens with the new theme. Things will be a little different. Perfect,
that looks good. But I want to change the navigation here to be dark as well. So if you
go back, and if you examine the theme details, you will notice we have a dark navigation.
Let's use that. In order to do that, we will go back to underscored layout. Rather
than nav bar light, this will be nav bar dark, and the BG will also be dark. Let's go back
and refresh. And this looks much better. So you can see how easy it was to switch themes.
Now I do not like the header and background both the same color. So if we go back to boot
swatch, let me find out some other themes. We can use this darkly theme. And you can see
the navigation is a little gray. Let me switch that. I will download the bootstrap dot css, cut
everything here. Let's go back to the application. We can remove that and paste the new code. If we
go back and refresh here. Great. This looks much better. Let me remove the two borders here. And
in underscored layout, we will search for border, we will remove the border bottom. We have one
more, right here. And perfect. Let's go back and refresh. Great, the UI looks good. Inside
the footer, I will say BG dark to get the little gray shade. Great. This looks much better. The
only thing that is missing is our headings here are in black. So we'll have to go back there and
remove the textile to give them the white color. Let me save this and refresh. And great.
Now the Create category looks much better. Let me also align this on the right
hand side. So we will go to what index and while we have the button here, we can give
it the class of text and with Bootstrap five. Great. Now while we are here, let's also use
the icons of Bootstrap. So inside the icons if we go to the top, let me search for pencil.
We have this pencil square. We can copy this, go back to the Create New Category. Before
that, let me add the icon and a space. With that you can see adding icons is super easy. So with that the design looks good. Now
what I want to do is inside create category, if you try to hit Create button, you will run into
an exception. It says the SQL exception cannot insert null values in name. That is because the
column doesn't allow nodes, or Entity Framework core was smart enough in migrations to add the
NOT NULL based on the required property. But here we need validations so that we do not see this
ugly exception. Let's do that in the next video. Now we want to add validations on the Create
window. If we go back to our project, and if we examine our model category, you can see for
name, we added a required validation. So we want to make sure that this basic validations that
we have defined here should be applied when a user is inputting those values. Checking for those
validations is super easy with dotnet core. First, let's take a look at server side validation.
So that will be done inside the.cs file. When a user is actually creating the category, we are
using a model here to insert inside the database. So we have something known as model state, that
model state will get the bindings and it state and in there we have an invalid flag. This will check
if the model state dictionary is valid or not. Model state dictionary will have a key value
pair for each entity that is there in our model. So inside category, it will have better than name
is valid, or the display name is valid or not. Because we are entering both of them inside the
Create UI. So let's examine model state.is valid. If that is valid only then we want to create.
If that is not valid, we want to return back to the page. And that is how it should
be. But let's add a debugging point here. And let's examine what actually happens, that may
restart the application because we made a change inside the page model. So with that, let's
go to categories and try to create an empty category, we do not hit our breakpoint. That is
because the breakpoint will only be hit if the model state is valid. Let me add a debugging
point right there and hit the Create button. If you hover on model state, you can examine
all of the properties in there that is valid is set to false, which means the model state
is not valid. Now, why is it not valid, that you can examine by going to the result view
you can see there are two properties that it is monitoring. And both of them are not worried the
name is not valid because it is a required field. And the display order is also not valid because
it is an integer field. If you enter now in there, that is not valid as well. That may hit
continue here. And this time you don't see the ugly screen. Because if the model state is
not valid, we are returning back to the page. This time, let me enter name and then hit create.
The model state will still be not valid because of our display order. This time the error count
is one. And if you expand the result view, you can see name property is now valid,
but the display order is invalid. So with that, we can easily check our model
state and only if the model state is valid, then we create elsewhere return back
to the view. But that is not helpful, we should display an error message saying what
actually is invalid so that user can fix that. Doing that is super simple with dotnet core.
If you go to create.cs HTML, we have a special tag helper to display the validation errors. So
right after the property or wherever you want to display, we will have to add a span tag and
there is a Tag Helper ESP validation for here we have to write the name of model property
that we want to bind with this validation. We want to check for validation category dot name.
So if there are any errors with category dot name that will be displayed in the span right here.
And we will also add a class of text danger for the red color. Let me copy this and paste it
for display order so we can monitor both of them. Once you save that, let me go back and refresh
the page. Let me try to hit the create button, it hits our breakpoint. And we get an
error that may just stop the application. I get that from time to time, even though
I did not edit anything while the project was running. So let me restart the application.
And this time, we should see the error messages. So let's hit the Create button. And great,
you can see it displays a default message, the name field is required, and the value empty
is invalid. So with that, you can see how easy it was to display validations from server side.
Now, the way you can tell this a server side is if you examine the tab here, every time we hit the
button, it reloads. So it goes to the server, and then it finds out that something is invalid, it
returns back, and it displays the error message. With that, let's continue in the next
video. These are the default validations that we have at the model level. But
what if we want a custom validation? Let's say we want a validation that the name and
display order cannot be seen. How can we implement that custom validation and display that message
right here. So let me close the application. And we will have to implement that validation at the
server side. And we can see if category dot name is equal equal to category dot display order,
we will have to convert that to a string. If these are the same, then we want to add an
error message. So to manually add an error, we can access the model state. And in
there, we have a method ad model error. Now this method requires two parameters. First
is a key name. And next is the error message. So you can name this key, anything that you
want, you can even keep that string dot empty, because we don't want to put anything in the key.
But if you are adding more than one model errors, then you cannot have string dot empty for both of
them. Because this is a key value. So you can use distinct key name, and then the error message, let
me say that display order cannot exactly match the name. So now we have added a custom error right
here in our model state. As soon as you add this, the model state even if it was valid before
this execution will now no longer be valid. And I will show that. But where will this error be
displayed. Because if you go to create.cs, HTML, we have the validation for individual properties
that are displayed right here. But we have something where we can display the summary of
all the validation. So let's say right here, we want to do that, then that will be inserted div,
and we have a Tag Helper ASP Validation Summary, we can keep that as all. In that case, it will
display all the validation summary at the top, as well as at the individual level. Let
me save this and run the application. If you go to categories here, and try to create
an empty category, let me remove the debugger and continue and great. You can see here we see
the Validation Summary. And sim properties are displayed right here. Now this time, let me enter
a test and it is play order. I will actually add the debug endpoint again on post. And let me hit
the pattern. If you examine the model state right now, you will notice that it is valid, we will
add a debugging point and let's continue. It seems like it went through. And of course it did because
the name and display order were not the same. Let's keep them same again continue continue again
it is adding the model state error. Let me add another debugging point, hit continue. And if you
examine this time it is not valid because we added a custom model error based on our requirement. So
if we remove all debugging point and hit continue, we see the custom error that display
order cannot exactly match the name. So this is how you can add custom validations now I want to show you one more thing. You can
see we have used the Tag Helper to display label. If we go back we have to label
for display order and name. It is using the exact same name as property. But
what if we want to display something else? What if we want to display a space between display
order, because inside the error messages also, it displays the same format. To do that, we have
lots of data annotations that are available to help things. Let me go back to category and stop
the application. Here, we have the required data annotation. Similarly, we have a data annotation,
which is display. And then we can provide a name or whatever we wanted to display. So let's call
that display space order. Once you do that, if you save and run the application, now, wherever
it has to display the name of the property, it will use this display attribute and whatever
name we have given. So if you go to categories create new category, you see the space between
display order. And if you right, same thing, you have that in the custom validations. And
my back, this will not change because we are adding the custom string. So if you want
that, you can always change that here. I thought for a second it was retrieved from the
property name, but that's not the case. But you can see we can change the display attribute to
display label wherever it is being displayed. Next, we also have custom data annotations
other than required display and key. If you go back to the Microsoft documentation, you
can see all of the annotations that are up level, and there's quite a few of them. We have
one here, that is range that checks if the specified number is between a range of
values. If you scroll up, we have the mainland four number key attribute that is the one that
we used. And we should have a display as well. Let's see how we can use the range
attribute. When we have the display order. Let's say we want to make sure that display order
should always be between one and 100. So here, we can use the range attribute. And it expects
two parameters. One is the minimum value, and maximum will be 100. Along with that if you want
to specify what error message should be displayed, if that condition is not true, you can customize
that if you do not like the default message. So we will display our custom error
message. And let's see this in action. If we try to hit the create button, we have
the invalid. But if we enter, let's say 222, hit Create. Now we see our custom error message.
So there are lots of data annotations that are available that you can check out on
the documentation. But we saw the use of display as well as range data annotation.
With that, let's continue from the next video. The validations that we have seen
so far are server side validation. On each request, it goes back to the server and
then displays the validation. What if you want to use client side validation, the custom validations
like name and display order should not be same will be server side. In order to validate
things on client side with the dotnet core application. Inside the shared folder, we have
a script, which is validation scripts partial. Here we have the jQuery to do some validations
on the client side. But this is not included by default in all the pages. So in pages where you
want to do client side validation, all you have to do is include this partial view, partial views are
meant for that purpose itself. They are created to be used inside some other view. So let's go to
our create. And how do we add a partial view? Partial views are like user components if you
come from the traditional dotnet application. Since inside there, we only have script tags. So
if you have to add any script tag, inside your view, you have to create a new section. So we will
create a section for scripts. And inside there, we will use the razor code, we want to add a partial
view. So for that we have a partial Tag Helper. And we have named there where we need to write the
exact name. Make sure you do not make any spelling mistake there or else it won't work. So with
that our partial view is added. If this partial view did not have just a script, it had some code
then you could have added that within your HTML like this. But since it is scripts, we will add
that inside the section of scripts if you have any JavaScript code that you want that will also
be added within this section itself. So on razor page, you can add a section to handle all of the
JavaScript. Once you do that, you do not need any other changes, we just need to run the application
and see client side validation in action. So let's go to categories here. And let's hit the
Create button. This time the page will not reload, you can see all the validations are done on
the client side. If you go to the page model, and add a debug endpoint, and you hit Create,
it does not hit the debugging point anymore. But the custom validation that we have here
is still done on server side. So if we add one and one, hit Create button, it goes to the
on post, and then it displays the validation. So if you want to be fancy, you can do that
validation in JavaScript as well. But by default, the dotnet core does not display the custom
validations on client side. And that also makes sense. Now, before I end this video, what if we
want to display this validation inside the name. So basically, when we are doing this, you can see
we have validation, that name field is required, I want to display that validation for the
name property. Doing that is super simple. We stop the application. And the key here,
we will have to change that to be category dot name. Let's run this and see what happens.
Let's hit continue. And great. You can see now we are binding that directly. So if you want to
bind some custom model state errors to a property, you just need to provide that key name, and it
will automatically do the binding. So with that, let me remove the debugging point.
And let's continue from the next video that are created category is working as expected.
Let's work on editing a category. So for that, we will have to go back to the categories
page. And when we click here, the navigation doesn't seem to work. Let me go to underscore
layout where we have the navigation here, we will have to add a forward slash that may save
that refresh. And perfect. That's much better, we will always need a forward slash and
then the complete path because we have the pages as the root directory. So after that,
how do you navigate to index so after pages change the directory to categories. In there we
have index. Now in the index page, we want to add two buttons have edit and delete. Let me go back
while the application is running. Inside index, we have two th tags, I will add another th
here. And inside the table row we will add a TD. Inside this TD we want to add two links. The
first one should take you to an ASP page using Tag helpers, it should take us to edit page. And we
will give some bootstrap classes btn btn primary and margin x of two. Inside the anchor
tag, we want to display an icon to edit so we can go back set the bootstrap icons we used
pencil, we can copy that and paste it for edit. Next we want a link for delete. So let me copy
this. Paste it one more time for delete. That will be btn danger. Let's go back, we will search for
a crash icon. Let's copy that and paste it here. If we scroll up, we are using pencil for create
deal. So let me change that to something else like a plus sign. So we have
the plus square. Let's use that. Let me save this, go back to our application
and refresh. Perfect. So we have all the icons. Let me go back and add some styling. So right
inside the TD, let me add a div give it a class of width 75% btn group and row and we will close
that. Let's refresh and this looks much better. So if we go back, we will have to add two
pages, one for edit and one for delete. Now when we are editing any of the category here,
we need to know that which category user selected so we need to pass the ID, when a
user clicks on any of these buttons, we have a special tag helper for that. When
a user clicks this link, we want to pass something to the route. So we have ASB route,
and then after hyphen, we can give it any name, let's count that as ID. And then the value that we
have to pass is inside this Obj. So we'll use the razor@obj.id. That will pass a variable
with the name of ID to the get handler of this particular page. So let's create
that page and work on that in the next video. Now that we are passing the ASP route ID with
the actual category ID to this edit page. Let's create that page. If you want, you
can create a new page inside categories. What if we want to copy this create and reuse that
the reason to reuse is because the view or the UI will be exactly the same. It's just rather than
displaying an empty page, we will have to display all of the items that are loaded. So let me
copy this create and paste it one more time. Then to edit we will have to stop the application.
Let's press f2 and change the name to edit. If we expand this, we have added done cshtml.
You think that is sufficient, right. But once you make this change, let's try to run our
application, we will have some error messages. What is the reason behind that? I want you guys to
pause the video and try to see if you can find out what is the reason we just copied the Create. And
we modified the name to edit, but it is failing. I hope you guys were able to figure out the actual
reason. Let's take a look at edit dot CSS, HTML and create dot css html. If I toggle between them,
you can see that the Create model is being used for both of the pages that cannot happen.
Each page will have its own unique model. So what actually happened is when we copied and
pasted inside the CSS, HTML, it is using the same model for both create and edit, we have to change
the name of this model. You can name it anything that you want, I'll call this procaine model,
we will have that constructor and inside it, we will have to use the same with that if you run
the application, everything will work as expected. So that was the main culprit over there. But
we should name this as meaningful as possible. So let's call this as edit model. And we
will change that in all the places. When you were copying and pasting things
inside MVC, this was not an issue, because it would rename the class and everything
would work when you're working with controller. With view, they don't have a tight
bind, because there is no.cs in MVC. But when you work with razor pages, if you are
copying and pasting, make sure to change the model in both the page model as well as the UI page.
So with that, we have added the added razor page. Now one thing that will be different inside edit
razor page is inside the arm cat, we will actually have to retrieve the category. And we will have to
pass that to the view or the UI that we have here. Inside the view, it is already binding that
to category dot name and display order. So we just need to populate the category
object right here. In order to find that we will be receiving ID in the parameters here.
So let's write that. As I said before, insert the index dot css html and passing the route with
the name of ID. So inside edit dot CSS html.cs, we can fetch that directly here. And based on that
ID, we will retrieve the category from database. So underscore DB dot category dot now
we want to find a category based on ID that could be done in many ways. The first one
here is find in find if you write it, it will automatically find that and assign the category
find will work on primary key of the table. So the ID that you pass here must be the primary
key of Category table and that is the case. Because of that it will automatically find
that record and assign that to our category. Now similar to find I have few more
methods that I want to show you. The next method that we have is first our default.
We have First, as well as first our default, what will happen with first is we need a lambda
expression here. And we will say you.id is equal equal to the ID that is past year. Here
we are saying that from category table, find me the first record that matches the ID,
which is equal to the ID that we are passing here. Straightforward. Now the difference between first
and first or default is that if it does not find any record with that ID, first will throw an
exception, first or default will just return now, that is the difference between first and first
our default. Another way of finding that is using single and single or default, you can use single
when you expect only one entity to be returned. Because in single if more than one entities are
returned, that will throw an exception as well. Whereas in first, if more than one entities are
returned, it will just ignore everything else, and send you the first one. So single is more strict.
When it comes to returning values. Inside single or default. If nothing is found, it will return
null inside single, that will throw an exception. So similar to first and default. And then here
again, you will need lambda expression. So you.id is equal equal to the ID. Last but not the least,
is not the favorite approach when we are working with one entity. Here, you will have a rare
condition, and you will say value goes to you.id is equal equal to id. So it will retrieve
all of the records where the ID matches. With this statement, it can return 10
records, it can return 20 records, wherever the ID matches. So on that once you retrieve
that, you will have to call first or default. These are just multiple ways of doing the same
thing. I prefer either find or first or default. I'll just comment this out, so that you can play
around with them. But that will retrieve the category and assign that to our category object.
And inside the post action method, what we are doing is we are adding the category, we do not add
the category. This time, we just want to update. So on DB set of category, we have an update
method. And since that is not a sink, we will have to remove the await keyword. With that it
will automatically update the properties that are different based on the primary key. So you can
see how easy it is to update any of the category. Let's run our application and give this a try. Now
before I run this, we'll just go back to the edit view, I'll have to change this create to edit and
where we have created button, we will just have to change the text to update because it is anyways
submitting back. So the form on post handler will be triggered automatically. Let's go back to our
application. And let's try to update a category. Let's hit update. Now you might
think here that update is working. But actually it's not. Let's try to update this
category and change the display order to five. You can see it is not actually updating it is
creating a new record with the updated entities. And why is that? I want you guys to pause the
video and analyze on why this is happening. You guys were able to figure out the reason edit
is not working, but it is rather creating a new object. Let me show you how I debug to find out
what is the issue. Let's try to add it this change the display order to six year and we will switch
back to the application where we have the edit.cs html.cs we will add a debugging point on the on
post. Let's go back and hit the update button. This time let me examine the category and you will
notice that ID is zero. Now if you pass an object to update with an ID of zero, Entity Framework
core will think that this is a new object. I need to create that because of that it is
creating a new category rather than updating. But the main question here is why is it zero? Now
the reason ID is zero is inside edit.cs. HTML, we have find it the category name and
display order, but we have not binded the ID. So that's why there is no ID field right here.
So if you want to do that, you can have an input field which is hidden and we will use the ESP
for tax helper, this will go to category.id. With that hidden field, when the form is
posted, it will have the ID populated. Let's hit continue here, we get this error,
we'll have to stop and restart the application. And let me also remove the debugging point. Let's
go back and try to edit any of the category now. So we have this five, we will try to edit that
and change that to six. And perfect this time, it did not create a new category. So these are
very small things that you have to debug in the application. The best way is to add a debugging
point and analyze what is the value that will give you the exact idea of why that is not working.
So with that, our added functionality is also working as expected. Now for your assignment, I
want you to implement the Delete functionality. When you hit delete, it should open up the same
page as edit, it should say delete category, and this field should not be editable, so they should
be disabled. And you will have the delete button here. But before you do that, I'm going to add a
button here to go back to the category lynched. Also, inside create, let me add that button. So
let me go back to the project. We'll open up the Create, we will add an anchor tag with ASP page
of index, some bootstrap classes. And within the anchor tag, we will have back to list. Let me also
copy this and we will paste that inside edit. Let me save them go back and refresh. And perfect we
have back to a vest that is working as expected. Now here, we just wrote the page of index. So
what happens is within the same directory, it will try to find the page with the name of index.
We already have that. So it automatically takes us back there. But you might be thinking that
what if I want to redirect to some other page, let's say we want to redirect to this index
page, which is the root page of the application that is super simple. Before index, you will add
double down and forward slash. So then it will take you back to one level. And inside that
folder, it will try to find the index page. Let me show that we will save this inside edit.
Let's go there. Back to list, we get back to the home page and not the category list page. We
will roll back, bring things back to normal. Perfect if you have to route to some other
folder inside pages, how to navigate there. So perfect. Now in the next video, you
have to implement the Delete functionality of deleting a category. So good luck with
that. And I'll show you that in the next video. You guys were able to implement the Delete
functionality, we will switch back to our application. First we will open up the index
page here. And we need to pass the ID to delete. So we will paste that here. And then we can stop
the application, copy what we have for edit and paste it one more time, we will rename that
to delete and we need to change the page model make sure you're working on delete here, we'll
change this to delete model copy that go back to the cshtml and we will rename that as well.
Now, when we are deleting on cat we will have to find the category that we have to delete
but inside post we can do something different we will have the ID that will be populated
inside the category. So we will have to find the category object from database we do not need
this if condition if the model state is valid, we can create a variable category from db is equal
to underscore DB dot category dot find find that based on category.id So that will find the
complete category object and populated right here. Next we can check here if category from DB is
not no. In that case, we will say underscore DB dot category and we have the remove method
which expects a category entity it does not expect an IT it expects a category entity. So
we will pass category from db to be deleted. We will remove this and we will paste the
save a sink inside the if condition. If the model state is valid, we redirect back
to index else, we go back to the page. So the page model looks good. Let's make changes
to the view. This will be delete category, everything will be disabled,
we do not need validations. Let me add the disabled field. And we have to
hit an ID that looks good. Change this to danger, and delete. Or in fact, let's run
the application and try this out. Let's go to our categories and try to delete
test and three, soon as we try to delete, we get this validation the Validation Summary we
should remove that, but something is not right. The reason behind that is if we go back, it is
returning back to the page. So the model state is not valid. Now, obviously the model state will
not be valid, because it will not have the name and display order since they are disabled.
So we do not want to add model state there. Because we are just finding the ID based on that
we are retrieving that from database and deleting that, we will move to a redirect inside the if
condition. With that we will have to restart our project model state does not get populated for
disabled field. So that is something that you should keep in mind. Let's delete and perfect.
You can see delete is also working as expected. With that create, update and delete are
working for our category. Let's continue in the next video. I want to display an
alert on the index page that shows that what functionality has been done. And those
alerts should go away if you refresh the page, so they should not stay on the page once they have
been displayed. For such special functionality, we have something called as temp data with
dotnet core. Temp data has one main feature, it remains for only one request.
And if you refresh the page, it goes away. So that will work perfectly
when we have to display a little notification. So let's see how we can add something to our temp
data. Let's go back to the application. And let's work with create. Let's open up the.cs file inside
the our post before we retire it. We want to set something in temp data. So we have temp data that
we will write here. And we need a key name. You can call this anything that you want. I will call
that success, because that is the success message. So inside the key of success, we want to store a
string, which is category created successfully. We can copy this temp data. And we can add that
in delete as well. Before we redirect, we can say category deleted successfully. Inside edit
before a redirect, we can say category updated successfully. So we are setting our temp data
on create, edit and delete. Now if you notice, once we create them, it is redirecting to the
Index page in all the places inside delete also, that goes to the Index page. So what we will
do is on index dot css html, inside the view or the UI side, we need to retrieve that temp data
and see if there is any string value inside there. So right here on top of the page, we will use
razor syntax. And we'll have the if statement. We will say if temp data, you will have to use
the exact key name. If you use something else, it won't work. So if temp data of success
is not now, what we want to do is an h2 tag, I want to display the value. So in
order to get the value from temp data, it is pretty straightforward. We just write
test temp data success. Let me save all of that. And we will have to restart our application.
This time, let's try to create a category. As soon as we create, you see we got a
notification in h2 tag. And if you refresh the page that goes away, so that is perfect.
This way it only stays there for one request. If you delete a category, you can see we have our
alert, which is category deleted successfully. So this is great news and everything is working
as expected. Now rather than displaying a string on top, it's best if we use something See
JavaScript code. Let's do that in the next video. Right now we are just displaying an h2 tag.
But we can add something fancy in our project. And that is toaster J S notification. If you go
to the toaster j s get repo, you will have a demo where we can see how toaster notifications look.
And these are much fancy. If we go back to the GitHub, we have the CSS and JS files. Let me
copy the CSS. Let's go back to our application. Inside the underscore layout, we will add that the
top here, Link, Arielle is equal to stylesheet. And h ref will paste the URL. Next, what we have
is the GS. So let me copy the GS file. And then GS, we do not want to include an underscore layout
here. Let me do that too badly in index.cs. HTML, where we have temp data. One way I showed you
how to use script is at the end, we can use the script section. Another way is right here,
we can use the script tag. And within here, we will say type is equal to text, JavaScript. And
we can use some custom GS right here. Before that, we just want to include a script. So we'll say
script src is equal to let me paste the URL. Now when we are working with toaster at the
same place, we will also need jQuery. So if you go to underscore layout, we have jQuery script
right here that is included with our project, we can go back to the Index and paste that
right here, we will remove the h2 element here. And Perfect, let's clean this up. Now within the
script tag, we want to call toaster and on there, we have method of success. Let me go back and
show that we will have the user ID someplace. You see we have toaster dot success, we can copy
that and paste it here. And inside the parameters, we want to pass the temp data that should
be done inside single quotes. Now we need to access the result code. So we will use the
Add sign temp data of success. That in place, let me save this, go back. And let me refresh the
application. Let's try to edit a category here. Now we see the fancy toaster notification. If
we delete a category, everything is working as expected. But now we have a fancy notification.
So similar to success, you can also implement an if block here, that will be for error temp
data. And if you set something inside error, we will display that this will be error. So
that way we can use toaster with our project. I've added alerts to our project.
And if we go back to the application, this is some code that is common for alerts.
If you want to display alerts in other pages, you will have to copy this code every time. And
what if in future, you change something here, then you will have to go to all the files and
update the same code. That is a bad approach. And for that particular scenarios, we have partial
views, we can move this code inside a partial view. And then we can directly call that partial
view here. That way In future, if you have to change something, you will only change that in one
places. And wherever that partial view is called, you don't have to change anything in those files.
So far that we will stop the application partial views, we will always add inside the shared
folder, we will right click add new razor page, we will go with the razor page empty. And
so far we have been selecting razor page. But that creates a page with a page model. Partial
views do not have a page model that you can see inside underscored layout and the validation
scripts partial. So that will be a razor view. Razor view does not have a page model. And
naming of partial view I always do with an underscore that way by taking a look at the name
itself. I can say that that is a partial view name we want to give here this notification. Let's
add this razor view. You can see there is no page model with the partial views. Now here it says
for enabling me See projects, just ignore that, we will be using this as a partial view in the
razor page. And that is completely normal. Let's go back to our index. And that may cut the
cord or toaster, go back to notification, and we will paste it right here. We will
save this, then we will go back to our index. And we need to call our partial view
with the name of underscore Notification. Now when you have to use notification in some
other page, you will just have to add this one line of code. And also in future when you have
to change something, you will just change that directly in partial view. And you don't have
to make that change across all the other files. Let's run the project and make sure
everything is still working the same. Let's go to our categories. And we have an
error. I believe there is some spelling mistake, I'd forgotten I here. Let
me save that. And refresh. Let's try to delete this time. And perfect.
Since these are magic strings, make sure that the name is exactly the same audio will run into
the error messages like we saw. So this is great. But what if in your functionality, you wanted this
partial view to be across all of the pages in your application. If that is the requirement, indeed,
then it doesn't make sense to add this one line in all the pages. The alternative for that
is we can cut that partial tag from here and add it inside the underscored layout directly.
Because this is rendered in all the pages. So here just before render body, we can paste
the partial tag and run the project. If we try the categories one more time, it should work
as expected. Perfect. But you should be careful with this approach. Because you are adding a
piece of code that will be present in all the pages of your application. If that is something
that your requirement demands, then for sure, go ahead and do that. But do not add a bulky code
here that is not used, it will just increase your application overhead. So with that all of our
CRUD functionalities are working as expected. Now we have seen how we can add pages
to our application, and how to modify everything else so far. Let me show you one
more thing here. Let me create a new folder inside pages and call this category 10. In there,
if we right click Add razor pages, you can see we have options here to directly create razor pages
using Entity Framework for all the crud operation. What exactly will this do? Let me show you that.
If you hit the Add button, first thing that you have to do is you have to select a model, it
will create all the pages for CRUD operations, which stands for create, read, update and delete.
So we have to select a model there. And we need to select the DB context, because that way it
can access the database and modify everything for the CRUD operations. Once you add those two,
this won't be a partial view, we want to use our master page and record layout. So we will set
that as blank. And let's add this. This will take a while to scaffold everything. And then it will
add all the pages inside the category temp folder. Now that it's done, if you expand that,
you can see it has added pages for create delete details added an index everything by
itself. Let's run the application and take a look at them. In order to navigate there, we have
to do the manual navigation. So here the name of the folder is category temp. We can write index.
But if we don't, it will find that by default. And great. You can see there is the index page
and we had one category, it is automatically displaying that we can create a new category here.
That's working. If we hit Create new, it also has validations we have go back here, we can edit the
category that's working, we can view the details and we can delete the category. So all of the
functionalities of a basic CRUD application are done for us if we go with that route, but I
did not want to go with that because I wanted to teach you how to write all of this on your
own. But if you examine In the code here, it is doing the same things that we have done,
nothing fancy. So that's just something for you guys to play around. Let me remove that,
because I do not want multiple code. So with that our project is done. And in the next video,
let me show you how we can deploy this to Azure. And the final task is to deploy an application
to Azure. So for that, you will have to create an account on portal.azure.com, I already have an
account, if you are signing up for the first time, you will get $200 of Free credit that you can
use. The first thing that we have to do in here is we need to create a SQL Server and a database
inside that. So we can create or search for SQL databases. And let's hit the Add button. Usually,
I like creating everything from Visual Studio, but SQL Server I like to create here. That
way, I can easily see all the configuration, you will select the subscription that you have.
And in there, we can create a resource group. I will call this resource group as taught at
mesh tree underscore course. And then let's enter a database name, we will contact dotnet
mastery underscore dB, we do not have a server. So let's create a server. The server name will
be unique. So I will use start at mastery server. And then we need an admin login. We cannot use
admin here, that won't work. So I will just use admin SQL for password, you can use something
secure, select your location, and hit OK. Now next option is to be one to use elastic
pool, we will say no there, and then the server location that's not available. So let me select
some other location HDLs too. And let's hit OK. Then you need to select the compute plus
storage, we will select Configure database there. And I will use the lowest option which is basic
here. And that is five usd per month. Let's apply. I do not want to pay more for the subscription.
So I'm going with the lowest option for redundancy backup, that is perfectly fine with me. Let
me hit review plus create. We're going to hit Create here. And it will take a while to
configure our database and set everything up. And perfect our database has been created. If
we click go to resource, it will take us to SQL database. Now one thing that you will have
to do is if you want to access this database, from your local SQL Server, you will have to
select the Set firewall settings and add your client IP that will enable your client IP and
you can access the database from SQL Server. Let's hit the Save button to add your client IP
there. Once that is done, let's go back to SQL Server. And we need to connect to that server.
So we will hit OK here. Go back to the resource. And we have connection string.
Let me copy the server name here. Go back and paste it. And we will use SQL
server authentication. We have admin SQL and password. Let's press Connect. Great,
we are able to connect to our SQL Server. So with that in place, let's continue from the
next video. Let me close the other tabs here. Now that we have created our database in Azure,
we can go back to Visual Studio, and let's publish our application, we will have to create an
app service plan and we will have to publish we can do that directly from Visual Studio as
well. So here we will right click on project and select Publish. We will be selecting
Azure and hit next here. And then for now, we will be publishing to Windows App Service.
Let's select Next. Then you will have to log into the account where you want to publish.
Once you sign in with the account, you will select the subscription name here on the top and
we will have to create an app service instance. I will call that as as the web. So the final
website or rather the temporary website will be abi pap.as, your website's dotnet it is
a free domain that is provided by Azure. So we have subscription name. Next is the resource
group, you can create a new resource group, but I already have one after at mastery underscore
course, that is what I will use resource group are basically tax that you can add to combine things
under one umbrella. Nothing fancy, just like a folder structure. Next we have the hosting plan.
My default an S one tier hosting plan is selected. But I want to use the free hosting plan
that Azure provides. So we will select that and press OK. Let's hit the Create
button to create our app service. That creates our AP service. And we will hit the
Finish button. The final step that we have is we need to configure our SQL database. So you can see
in the service dependencies, we can hit configure here, and we can add an Azure SQL database, it is
already displaying the database that we created on our account. So we will select that and hit
the next button. The Connection String name inside our application, if you remember, inside the
connection strings, that was default connection, we just need to write our user ID, which is
admin sequel and the password. Once you do that, it automatically populates that in the connection
string, then we do not want to save connection strings in app settings or key word right
now. But we can just copy the connection string. Let me open up a notepad and paste it
there. Let's go back and hit the Finish button. Now that we have the connection string, let me
click on any one of the settings that we have here. Inside the database, we need to paste the
connection string. So let's expand that. And our connection string is valid, we will just select
the Use this connection string at runtime. Then inside the Entity Framework migration. Right now,
there are no migrations that have been applied. We already have the migrations in the folder. So we
can select Apply this migrations on Publish, and that will create the tables inside the database.
Now right now we are working with dotnet six, and it is not available in the App Service. So far
that we will change the deployment mode to self contained, and that should work with that chain.
Let me save this and publish our application. You can see the site name I said before will be
Abbey web.as. your website's dotnet. And this is a free subdomain that is provided by Azure it is
retrying the add operation but that is failing. Inside the logs here, you can see
we have issue with the client IP. Let me copy this error, paste that in Notepad.
I believe we added the IP, we will copy this, go back to Azure. In overview set firewall, we
will add a new client IP. Let's save that. That is the IP from the server. With that change. Let
me publish it one more time, and it should work. Once the deployment is complete, it will
automatically load the website URL in a browser. It is loading our website. Let's take a look. And create. You can see everything is working.
There will be a new category stable with no category right now. We can add categories. We have
our alerts. And we can edit, update, and delete. So everything is working as expected.
And our website is live on Azure. Congratulations on completing the course.
With this course you have a basic foundation on razor pages, and how to perform CRUD
operations using Entity Framework core. This is just getting started with razor pages
in dotnet core. There are many more topics that I cover in my advanced course. Let me just give
you some highlights of the topics that I cover in that course. The project that we have
built so far, we will define that project in an anterior architecture, where we will
have a separate data access layer. In that data access layer. We will be using repository
pattern and unit of four to access our database. We have already seen temp Data In Action, so we
will use that and we will see how we can add API controllers with our razor pages project. That way
we can use the API's that we build In data tables, and we will see sweet alerts, as well as rich text
editor. These are just some basic functionalities in a typical application. Also in any real
world application, we have authentication and authorization. So for that, we will scaffold
the built in identity razor class library that the dotnet team provides. With authentication
using identity class library. We will also see roles and authorization in action. Once we add
authentication and authorization to our project, then we will use stripe for payment collection and
we will also see how to issue refunds using Stripe API's. We also have sessions in dotnet core.
So we will see how to configure our application and send emails using SMTP and SendGrid will also
show how to use Facebook for social login. We also have some advanced concepts like view component,
and how to see database with the initial data using a DB initializer class. Once we
cover all of these advanced topics, we will deploy our application to Azure and
we will see how everything comes together. So this will be a pretty lengthy course
and we will go into building a real world project with real requirements. So if you
want you can check out this course and other courses on dotnet mastery. And if you like this
video, please like and subscribe to the channel. So I hope to see you guys in some
other course. Till then Happy Coding