>> Hello, I'm Steve Smith AKA Ardalis.
I'm a Microsoft MVP.
In this short video, I'm going to introduce you to
the eShopOnWeb reference application that
I help maintain for Microsoft which you'll find on GitHub.
To get started, the first thing you'll want to
do is download the code from
the GitHub repository,
navigate to github.com/dotnet-architecture/eShopOnWeb.
Then click the green button here to
either clone or download a zip file of the source.
I'm going to go ahead and clone this to my local computer.
If you download the zip,
just extract it to a folder.
If you click this icon,
it will copy the URL you need.
Now, we're ready to clone the repository using
the built-in tooling in Visual Studio for Mac.
Open Visual Studio for Mac and click on
"Version Control" and then "Check Out."
Now, go to the URL field and paste in the URL that we copied.
Now, click "Checkout." The convert repository
will be cloned down to your local machine.
Then the default solution loads,
and after a couple of moments it's ready to go.
Now, the first thing that you'll probably want to do is run
the application and verify
that it's working on your local machine.
Click the "Play" icon and once the project finishes building,
the browser will launch automatically.
Now, you can see the application runs as expected.
In development mode, the application uses an in-memory database
for its collection of products
and all of its other persistence needs.
The eShopOnWeb is a fully functional online store that you can
use to purchase.NET branded apparel and other items.
The main page features a catalog of
different products that you can add to your basket or view
more information about and it supports both paging and filtering.
The system also supports authentication,
you can login using
a demo user account that's specified on the page.
Once you're logged in, you'll see
some additional options at the top of the screen.
You can view your orders.
You can adjust your account or you can log out.
There's also a shopping basket icon here at the top right.
As we add items to our basket,
you can see that it continues to get
updated with the number of items in it.
On the basket page itself,
we can change quantities of items or remove them,
and then we can check out to complete our order.
Checking out does not involve any form
of payment because this is just a demo app.
Once we've placed a couple of orders,
we can go and view our collection of orders
here and see the details of each one of these orders.
The application also includes a variety
of different tests including unit tests,
integration tests, and functional tests.
We can run these tests from within
Visual Studio for Mac to verify
that the application behaves as it should.
As you can see, all the tests ran successfully.
Now, let's explore the solution structure for this application,
and then see how a typical request is handled.
The application is composed of
three different projects that run it in production.
These are the Web Project,
which is the user interface and front-end project.
Then, the Infrastructure Project and
the Application Core are used behind the scenes
to provide the low-level plumbing code and
high-level business rules for the application.
The Application Core is the core of the entire app.
All the other dependencies in the system depend on it.
So if you look at its dependencies,
you'll see that it only has dependencies on a few NuGet packages
and the.NET SDK itself but not on the other projects.
If you examine infrastructure,
you'll see it depends on core.
Likewise, web has dependencies on both core and infrastructure.
We'll talk more about what goes in
each of these projects in just a moment.
For now, let's quickly review how
a request gets served by the web application.
This application takes advantage of both controllers
and Razor pages to serve different parts of the application.
The homepage is a Razor page, Index.cshtml.
The first thing that happens when a request is made to
the web application's homepage is
the handler on Git will be called.
We're going to add a break point,
so that we can see what happens as
this request is processed and we'll start the debugger.
This Razor page uses dependency injection to get
a catalog ViewModel service which
it then uses to fetch the catalog items.
The catalog ViewModel service is defined inside of
the web application because it's
an application level service and it returns a ViewModel type.
The system uses caching and so the first thing that
gets hit is the cache catalog ViewModel service.
It will use a cache key that it creates
based on the contents of the query string for this page,
that include the page it's on,
the number of items per page,
the brand, and the type that
are used as filters on this application.
When the item is not in the cache,
it will call into another instance
of this catalog ViewModel service.
This one actually will perform the work of fetching the data.
Now, we've drilled down into
the catalog ViewModel service inside of the cached wrapper.
This will use what's called the specification pattern to determine
how it's going to query for
the data that it needs from a repository.
Once the specifications have been created,
they're used in calls to the item repository to get
the list of items and the total number of items.
Once the data has been fetched,
it is placed inside of a new instance of the catalog index
ViewModel which once it's completely
configured is returned back to the page.
Once the OnGet Method has completed,
it will return the actual Razor view
with the catalog ViewModel attached to it.
The razor side of the razor page is simply
razor data just like you would use inside of an MVC view,
and it includes a few different controls for displaying the data.
Here you can see that we're using
tag helpers for the select drop-down lists for the filters,
and then we're also taking advantage of
similar partials to use for the pagination controls.
The product details for
each individual product are also a partial.
The partials are defined inside of the shared folder here.
So there you can see pagination and product partials.
Just like with MVC or Razor pages.
There's also shared components for the view layout.
In this case, the shared layout is coming
from the Views folder in its Shared folder,
and that is where the header and
footer and other parts of the page are coming from.
If you need to make a change to this application,
you just need to figure out where the entry point is for the app,
and this is usually pretty straightforward based on the URL.
If it's a razor page,
it's URL is going to correspond to
the path under the page's folder.
So if it's the Homepage it'll be the index.cshtml,
if it's the privacy page it'll be this privacy.cshtml etc.
Inside of the basket you'll see that
there are methods for checkout and index.
So if you go to /basket,
you'll hit the index page,
or /baskets/checkout will hit the checkout page.
Now, because the sample application is meant to show
both MVC and Razor page's styles of development,
there is also a controller that's used for the orders.
So when the user navigates to the My Orders page,
that's going to correspond to
the My Orders action on the order controller.
This in turn will have a View
and the Views folder called My Orders.
We'll see in a later video how we can modify some of
this information as part of an update to the system.
That provides a good overview of the web project.
Let's quickly look at what goes into
the Application Core and Infrastructure Projects.
The Application Core project defines the abstractions
and entities or business objects
that we're going to use for this application.
The entities may be grouped into things called aggregates,
which should be saved or retrieved from persistence as a unit.
This means that when we fetch a basket,
we don't just grab the basket itself,
the header essentially, but we also grab all of its children.
All the basket items that are inside of that basket.
Likewise, looking at an order,
an order has a collection of order items with it
along with related things like an address to which it was sent.
Not everything needs to be inside of an aggregate,
there are also smaller entities like catalog brand and
catalog item that are
just simple lookup data that can stand alone.
Application Core is also where we're going to define
our abstractions that other parts
of our application will implement.
These are interfaces such as the IAsync Repository,
iBasket Service, iOrder Service etc.
We may define certain services inside of Application Core.
The way that you can determine whether or not
a service belongs here is primarily
whether it has to do with direct knowledge
of infrastructure like the database or web services,
or direct knowledge of how
the user interface works, like a view model.
If it doesn't need either of those things,
then it's probably a good candidate to
go in the Application Core project.
However, if it needs to know about view related stuff,
it should probably go in the Web Project,
and if it needs to know about
infrastructure concerns like persistence,
it should probably go in the Infrastructure Project.
We also have a collection of specifications.
These specifications are query objects.
They basically define how a query
is going to get executed in persistence.
So when we go to fetch a basket with its items,
instead of having to put those query details
inside of the user interface project our web project,
we can define those inside of
its own class which we're going to call specification.
Then we can write tests for these class independent
of the rest of the system to verify that it's correct.
Now let's move on to the Infrastructure Project.
Inside of the Infrastructure Project,
you'll find that there are several folders for Data,
Identity, Logging, and Services.
Inside the Data folder is where we
define our Entity Framework, DbContext.
We have a catalog contexts that has
DbSets for Baskets and Orders and related things.
These are configured by
individual configuration classes inside of the Config folder.
So if you want to see how address is mapped to
the database or what type of column widths it's expecting,
you can look at the address configuration class to find that.
This project supports Migrations that will update
the database as we change the properties of our entities.
So these Migrations live inside this folder as well.
This is also where we define our EF Repository.
This is an Async repository implementation that
uses a DbContext to fetch the items.
This particular implementation of a repository,
leverages the specification pattern for doing it's querying.
So you'll find that the list and count
methods each take a specification to perform their work.
There's a specification evaluator
that's used to perform this logic.
So inside of the specification evaluator,
it will pull the criteria from the specification
and use that as a where clause on the query.
Likewise it will use aggregation
from the specification on the query,
as well as ordering and in turn grouping and paging.
The benefit of this approach
is that your repository doesn't need to
continue to grow as you add additional query methods to it.
Instead, the repository should be fairly fix.
What you'll change is you'll add
additional specifications inside of your Application Core.
That's the bulk of the logic inside of this project,
there are also simple classes inside of
logging for performing the logging.
There's an e-mail sender that sends e-mails in a fake manner,
and then under identity we have the necessary classes
including a separate DbContext for
supporting the identity part of the application.
That's it for this walkthrough of the eShopOnWeb.
I hope you found it useful.
Please go ahead and download it if you haven't
already and walk through it yourself,
and see if you can get it to run and verify that it works for you.
If you have a problem, please open up
an issue with any question that you might have,
and we'll be sure to help you out and get
you running as soon as we can. Thanks.