Starting with this lab we will begin the process of creating a fully functional Fortune Teller application which uses several of the Steeltoe components. You have two paths you can follow when doing the rest of the labs for the workshop:
For each lab, open up and work with finished code. With this path you won’t be writing any new code, instead, you will just be reviewing and running already completed lab code.
Open the FortuneTeller.sln solution as your starting point. You will stick with this throughout the workshop, and you will be writing new code and debugging what you write.
If you start with #2 above, you will find the app in its current state is not very useful:
The
Fortune Teller Service
only serves up a single Fortune.The
Fortune Teller UI
doesn’t know how to communicate with theFortune Teller Service
so it always returns the sameHello world
Fortune.The goals for Lab 6 are to understand ASP.NET Core programming and to use our skills to hook up two areas of the code:
In
Fortune Teller Service
:
Hook up the
IFortuneRepository
to theFortuneController
Add the
IFortuneRepository
and theFortuneContext
to the ASP.NET Core service container.Initialize the
FortuneContext
with some Fortunes.In
Fortune Teller UI
:
Hook up the
IFortuneService
to theFortuneController
Add the
IFortuneService
to the ASP.NET Core service container.For some background information on ASP.NET Core programming, have a look at this documentation.
-
Start VS2015 and open the solution you wish to start from:
-
Workshop/Session-02/Lab06.sln if you want to start with finished code.
-
Workshop/FortuneTeller/FortuneTeller.sln if you will be writing code from scratch.
-
-
Expand the
Fortune-Teller-Service
project -
Open and examine
Program.cs
, as everything starts in here.-
Examine the usage of
WebHostBuilder
,UseKestrel
,UseUrls
,UseStartup<Startup>
.
-
-
Open and examine
Startup.cs
as this is where the app is configured.-
Examine the
Startup
constructor, where the apps configuration is read and created. -
Examine the
ConfigureService()
method, where the services are added to the ASP.NET Core service container. -
Examine the
Configure()
method, where ASP.NET Core middleware is added to the request processing pipeline.
-
-
Open the
Models
folder which holds the code for theIFortuneRepository
-
Examine
IFortuneRepository
-
Examine
FortuneRepository
, the implementation class and notice it uses aFortuneContext
-
Examine
FortuneContext
, notice it is aDbContext
based onEntityFrameworkCore
-
Notice it has a
DbSet
ofFortuneEntity
-
-
Examine
SampleData
and noticeInitializeFortunesAsync
method which adds sample data to theFortuneContext
-
-
Open the
Controllers
folder which holds the MVC Controller code-
Open the
FortunesController
, the implementation class for the REST API exposed by this microservice -
Notice it implments the
IFortuneService
which provides the two REST endpoints-
AllFortunesAsync() → GET: api/fortunes/all
-
RandomFortuneAsync() → GET api/fortunes/random
-
-
Notice the controller methods return hard-coded
Fortunes
, notFortuneEntitys
.
-
-
Expand the
Fortune-Teller-UI
project -
Open and examine
Program.cs
, as everything starts in here.-
Examine the usage of
WebHostBuilder
,UseKestrel
,UseUrls
,UseStartup<Startup>
.
-
-
Open and examine
Startup.cs
as this is where the app is configured.-
Examine the
Startup
constructor, where the apps configuration is read and created. -
Examine the
ConfigureService()
method, where the services are added to the ASP.NET Core service container. -
Examine the
Configure()
method, where ASP.NET Core middleware is added to the request processing pipeline.
-
-
Open the
Common/Services
folder which holds the code for theIFortuneService
-
Examine
IFortuneService
-
Examine
FortuneServiceClient
, the implementation and notice it returns hard-codedFortunes
-
-
Open the
Controllers
folder which holds the MVC Controller code-
Open the
FortunesController
, the implementation for the UI -
Notice the
RandomFortune
action, it returns aFortune
to the View
-
-
Open the
Views/Fortunes
folder which holds the Views for the FortuneController-
Open
RandomFortune
, the View used by theRandomFortune
action-
Notice how it uses the
Fortune
returned from the action
-
-
We will be using ASP.NET Core Dependency Injection
for much of the next set of exercises. For some background information on it, have a look at this documentation
Also, later on we make use of Entity Framework Core
. For some background information on it, have a look at this documentation.
-
To get the
IFortuneRepository
into the controller we need to modify the constructor of theFortuneController
:private IFortuneRepository _fortunes; public FortunesController(ILogger<FortunesController> logger, IFortuneRepository fortunes) { _logger = logger; _fortunes = fortunes; }
-
Then to get
FortuneController
to use theIFortuneRepository
we have to modify both contoller actions. Something like below should work, but feel free to write your own code:// GET: api/fortunes/all [HttpGet("all")] public async Task<List<Fortune>> AllFortunesAsync() { _logger?.LogDebug("AllFortunesAsync"); var entities = await _fortunes.GetAllAsync(); var result = new List<Fortune>(); foreach(var entity in entities) { result.Add(new Fortune() { Id = entity.Id, Text = entity.Text }); } return result; } // GET api/fortunes/random [HttpGet("random")] public async Task<Fortune> RandomFortuneAsync() { _logger?.LogDebug("RandomFortuneAsync"); var entity = await _fortunes.RandomFortuneAsync(); return new Fortune() { Id = entity.Id, Text = entity.Text }; }
-
To get the
IFortuneRepository
into the service container we need to modify theStartup
class methodConfigureServices
and addIFortuneRepository
to the service container collection. We will add it as a Singleton and when its created, it will come from its implementation classFortuneRepository
.public void ConfigureServices(IServiceCollection services) { ..... services.AddSingleton<IFortuneRepository, FortuneRepository>(); // Add framework services. services.AddMvc(); }
Notice that theFortuneRepository
takes aFortuneContext
as a argument to its constructor. So we also need to add aFortuneContext
to the container. ButFortuneContext
is built on the EntityFrameworkCore library, so we also need to add that to the container as well. We do that with theAddEntityFramework()
method below. Once both are added to the container (i.e.AddEntityFramework()
&AddDbContext<FortuneContext>()
), then we also need to configure theFortuneContext
to use some backend database for its storage. At this point in the workshop, we will just configure it to use an in-memory database. Clearly, if this context was being updated, this in-memory database would be a bad choice as it would prohibit us from scaling this micro-service horizontally. So in an upcoming Lab on scaling, we will show you how to use Steeltoe connectors to connect theDbContext
to a real backend database.public void ConfigureServices(IServiceCollection services) { ..... services.AddEntityFramework() .AddDbContext<FortuneContext>(options => options.UseInMemoryDatabase()); services.AddSingleton<IFortuneRepository, FortuneRepository>(); // Add framework services. services.AddMvc(); }
-
To add some Fortunes to the
FortuneContext
we have already written the code to do that for you. You can make use of the static methodSampleData.InitializeFortunesAsync()
to do this. The question is, where do you add this? Have a look at the method and notice that the code asks the container for an instance of theFortuneContext
in order to initialize it with samples. As a result, the container needs to be built before we call this method and also before we start handling any requests. So the best place to add this call is in theConfigure
method in theStartup
class.public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); app.UseMvc(); SampleData.InitializeFortunesAsync(app.ApplicationServices).Wait(); }
-
Using the skills you picked up from Lab05, run the app from VS2015 and from the command line.
-
CTRL-F5 or F5
-
dotnet run --server.urls http://*:5000
-
-
Using the skills you picked up from Lab05, publish and push the app to a Linux cell on Cloud Foundry.
If you are using the finished lab code on Windows:
-
cd Workshop/Session-02/Lab06/Fortune-Teller-Service
-
dotnet restore
-
dotnet build
-
dotnet publish -o %CD%\publish -f netcoreapp1.1 -r ubuntu.14.04-x64
-
cf push -f manifest.yml -p .\publish
If you are using the finished lab code on Mac/Linux:
-
cd Workshop/Session-02/Lab06/Fortune-Teller-Service
-
dotnet restore
-
dotnet build
-
dotnet publish -f netcoreapp1.1 -r ubuntu.14.04-x64 -o $cd\publish
-
cf push -f manifest.yml -p publish
-
To get the
IFortuneService
into the controller we need to modify a constructor in theFortuneController
:private IFortuneService _fortunes; public FortunesController(ILogger<FortunesController> logger, IFortuneService fortunes) { _logger = logger; _fortunes = fortunes; }
-
Then to get
FortuneController
to use theIFortuneService
we have to modify the contoller action:public async Task<IActionResult> RandomFortune() { _logger?.LogDebug("RandomFortune"); var fortune = await _fortunes.RandomFortuneAsync(); return View(fortune); }
-
To get the
IFortuneService
into the service container we need to modify theStartup
class methodConfigureServices
and addIFortuneService
to the service container collection. We will add it as a Singleton and when its created it will be created using its implementation classFortuneServiceClient
.public void ConfigureServices(IServiceCollection services) { ..... services.AddSingleton<IFortuneService, FortuneServiceClient>(); .... }
-
Using the skills you learned from Lab05, run the app from VS2015 and from the command line.
-
CTRL-F5 or F5
-
dotnet run --server.urls http://*:5555
-
-
Using the skills you learned from Lab05, publish and push the app to a Linux cell on Cloud Foundry.
If you are using the finished lab code on Windows:
-
cd Workshop/Session-02/Lab06/Fortune-Teller-UI
-
dotnet restore
-
dotnet build
-
dotnet publish -o %CD%\publish -f netcoreapp1.1 -r ubuntu.14.04-x64
-
cf push -f manifest.yml -p .\publish
If you are using the finished lab code on Mac/Linux:
-
cd Workshop/Session-02/Lab06/Fortune-Teller-UI
-
dotnet restore
-
dotnet build
-
dotnet publish -f netcoreapp1.1 -r ubuntu.14.04-x64 -o $cd\publish
-
cf push -f manifest.yml -p publish