12.3 Lab

Overview

12.3 Lab

In this lab we will create our own API using C# in Visual Studio. This API will allow different clients and browsers to retrieve information from our database. After creating our API application, we will test our calls to our API in Postman to verify that our application runs successfully.

Work through the stories in order. Use the acceptance criteria to check each feature, and complete the nested tasks using the specified names, values, and scenarios.

Checkpoint reference
Operation Checkpoint response
GET 200 OK with the requested data.
POST 200 OK with the created result, as required here.
PUT (12.4 onward) 200 OK after the update.
DELETE (12.5) 204 No Content after deletion.
Prepare the Netflix Titles database and API
Acceptance Criteria
Acceptance criteria
  • The Netflix Titles database is created using the supplied data and instructions.
  • The Web API project uses the required name and initial authentication setting.
Instructions
1.Create a database named Netflix Titles that we will configure our API Application to connect to.
A Download the below script to create a new database named Netflix Titles

NetflixTitles.sql

NetflixTitles.sql

Hint: You may have to alter your database file path.

B Connect to your local host in SQL Server Management Studio.
C In SQL Server Management Studio, open the downloaded script and execute the query. This should create a database named…

In SQL Server Management Studio, open the downloaded script and execute the query. This should create a database named Netflix Titles with 5 tables. Select the top 1000 rows of each table to ensure that there is data in each table.

2.In Visual Studio, create a new ASP.NET Core Web Application (C#) named 12.3LabNetflixTitlesYourLastName. Select the Web API…

In Visual Studio, create a new ASP.NET Core Web Application (C#) named 12.3LabNetflixTitlesYourLastName. Select the Web API template. Make sure Authentication is set to No Authentication.

We will add authentication when we configure the connection to the database.

A Delete the WeatherForecast.cs file.
B In the launchsettings.json file change the launchURL from "weatherforecast" to "api" in both profile objects as shown below.
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"12.3NetflixTitles": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
Map and query the stored titles
Acceptance Criteria
Acceptance criteria
  • Title, Category, TitleCategory, and EntertainmentType match the reference relationships.
  • DataContext maps the entities, keys, and relationships.
  • The configured connection and DataService provide the required database access.
Instructions
3.Create the Models that will be used to represent the data in the application's database, these Model classes should be…

Create the Models that will be used to represent the data in the application's database, these Model classes should be stored in a new Models folder.

A Create a new class named Category as shown in the code below.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace _12._3LabLocke.Models
{
/// <summary>
/// The class that is used to represent a Netflix category.
/// </summary>
/// <summary>
/// The class that is used to represent a Netflix category.
/// </summary>
[Table("Category")]
public class Category
{
/// <summary>
/// Gets or sets the category id.
/// </summary>
/// <summary>
/// Gets or sets the category id.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Gets or sets the category name.
/// </summary>
/// <summary>
/// Gets or sets the category name.
/// </summary>
[Column("Category")]
public string Name { get; set; }
}
}

Note the Table and Column attributes. These attribute specifies the database table and column that the entity and entity property should map to when the entity and entity's property name and database table and database column name differ. It uses the System.ComponentModel.DataAnnotations.Schema namespace.

B Create the rest of the model classes as shown in the class diagram below.
12.3 Class Models Class Diagram; Members and relationships are shown in the editable reference; unrelated members may be omitted.
12.3 Class Models Class Diagram
  • New
  • Changed
  • Removed

Be sure to add the TitleCategory property to the Category class.

1 Add a column attribute named "Title" to the Name property of the Title class, and a table attribute named "Title" at the class level.
2 Add a table attribute named "EntertainmentType" to the EntertainmentType class.
3 Add a table attribute named "TitleCategory" to the TitleCategory class.
4.Create the DataContext class. This will be used as the source to map all entities over a database connection.
A In the Data folder, create a new class named DataContext, that implements the DBContext class.

You will need to install the Microsoft.EntityFrameworkCore package.

B Paste the following code for the DataContext's constructor. This initializes a new instance of the DataContext class by…

Paste the following code for the DataContext's constructor. This initializes a new instance of the DataContext class by referencing the connection and mapping source.

/// <summary>
/// Initializes a new instance of the data context class.
/// </summary>
/// <param name="options">The data context connnection options.</param>
/// <summary>
/// Initializes a new instance of the data context class.
/// </summary>
/// <param name="options">The data context connnection options.</param>
public DataContext(DbContextOptions<DataContext> options)
: : base(options)
{ }
C Add properties of type DBSet for each of the models in the Models folder as shown below.
public DbSet<Category> Categories { get; set; }
D Override the OnModelCreating method to configure the models to the data context.
1 Add this method to the DataContext class.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
2 Create a one to one relationship between title and entertainment type as shown below.
// 1 to 1 relationship between title and entertainment type.
modelBuilder.Entity<Title>()
.HasOne(t => t.Type);
3 Create a one to many relationship between title and title category as shown below.
// 1 to many relationship between title and title category.
modelBuilder.Entity<TitleCategory>()
.HasOne(tc => tc.Title)
.WithMany(t => t.TitleCategory);
..HasForeignKey(tc => tc.TitleId)
4 Create a one to many relationship between category and title category as done in the previous step.
5.Create a connection with SQL Server and the NetflixTitles database.

You will need to install the Microsoft.EntityFrameworkCore.SqlServer package

A In your appsettings.json file, after AllowedHosts, add a ConnectionString object containing the SQL connection string as…

In your appsettings.json file, after AllowedHosts, add a ConnectionString object containing the SQL connection string as shown below. You will need to replace the Server property value with your local machine's SQL Server host name.

"ConnectionStrings":
{ "SQL": "Server=YourServerNameHere; Database=NetflixTitles; Trusted_Connection=TRUE" }

You can find your server name when connecting to your SQL Server Management Studio, as shown in the image below.

Server Name for 12.3 Lab. Use the adjacent task instructions to identify the required controls, output, or debugger values.
Server Name

The Trusted_Connetion property when set to TRUE, enables Window's authentication. If you would use SQL Server Authentication, you would need to provide user and password properties, and remove the TrustedConnection property.

B Add the DataContext to the application services.
1 In Program.cs, either at the end of the ConfigureServices method or in the body of a .Net Core Program.cs script, add the…

In Program.cs, either at the end of the ConfigureServices method or in the body of a .Net Core Program.cs script, add the following code to add the context to the services.

_ = services.AddDbContext<DataContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("SQL"))
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
6.Create the DataService class to define the basic CRUD operations.
A Create a new folder named services, in the folder, add a new class named DataService.
B Create a private readonly field of type DataContext named _dataContext.
C Create a constructor to initialize the instance of the DataService class. Give it a parameter named dataContext of type DataContext.
1 In the constructor set the dataContext parameter to the _dataContext field.
Return titles, categories, and types
Acceptance Criteria
Acceptance criteria
  • ApiResponse includes Status and Payload with the documented success convention.
  • The controller inherits Controller and exposes the specified routes.
  • GET calls for titles, categories, and types return verified responses in Postman.
Instructions
7.Create a new API Response class to configure the responses from the API, as shown in the below class diagram.
ApiResponse class; Members and relationships are shown in the editable reference; unrelated members may be omitted.
ApiResponse class
  • New
  • Changed
  • Removed
A In the ApiResponse constructor set Status = 1
8.Create a new class named ApiController in the Controllers folder. Have it implement the Controller class. Add a Route…

Create a new class named ApiController in the Controllers folder. Have it implement the Controller class. Add a Route attribute to the ApiController class as shown below.

[Route("api/[controller]")]

The Route attribute will help configure the URL for our API calls.

A Create a private readonly field named _dataService of type DataService.
B Create a constructor that takes a parameter of type DataContext named dataContext.
1 In the constructor, create a new instance of the DataService class, passing in the dataContext parameter. Set the results…

In the constructor, create a new instance of the DataService class, passing in the dataContext parameter. Set the results equal to the _dataService field.

9.Create data transfer objects that will be used to display the data to the client.
DTOs class revised diagram; Members and relationships are shown in the editable reference; unrelated members may be omitted.
DTOs class revised diagram
  • New
  • Changed
  • Removed
A Create data transfer objects that will be used to display the data to the client.
10.Configure the GET requests.
A In the DataService class, create the methods to return the database entities.
1 Create a new method named GetTitles that returns a list of Title. In the method, retrieve the titles from the database,…

Create a new method named GetTitles that returns a list of Title. In the method, retrieve the titles from the database, including the title's type, title category, and title category's category as shown in the below code.

return this._dataContext.Titles
.Include(t => t.Type)
.Include(t => t.TitleCategory)
.ThenInclude(tc => tc.Category)
.ToList();
2 Create a new method named GetCategories that returns a list of Category. In the method return the _dataContext's Categories…

Create a new method named GetCategories that returns a list of Category. In the method return the _dataContext's Categories property as a list using the .ToList() method.

3 Create a new method named GetEntertainmentTypes that returns a list of EntertainmentType. In the method return the…

Create a new method named GetEntertainmentTypes that returns a list of EntertainmentType. In the method return the _dataContext's EntertainmentTypes property as a list using the .ToList() method.

B In the ApiController class, add a method named GetTitles that returns type IActionResult. that will get the titles from the database.
1 Add an HttpGet attribute to the method that specifies "titles" as the URL, as shown below.
[HttpGet("titles")]
2 Create a new instance of the APIResponse class and set it to a variable named apiResponse of type APIResponse.
3 Create a new list of Title, and set it to local titles variable of type Title.
4 Create a new TitleDTO variable named titleDTO.
5 Call the _dataServices GetTitles method and set it to the titles variable.
6 For each Title in the titles list

Create a new TitleDTO and name it titleDTO.

Set all of the title properties to the titleDTO's equivalent properties, except for the titleDTO Categories property.

Create a new list of CategoryDTO and set it to the titleDTO Categories property

For each TitleCategory in the title's TitleCategory property

Create a new CategoryDTO variable named category.

Set the title categories category id to the categoryDTO's Id property.

Set the title categories name to the categoryDTO's Title property.

Add the category variable to the titleDTO Categories.

Add the titleDTO to the titleDTOs list.

7 Set the apiResponse's Status property to 0 and set the titleDTOs variable to the apiResponse's Payload property.
8 return Json(apiResponse). The JSON() function returns the apiResponse object as a JSON object.
9 The method should look like the below code.
/// <summary>
/// Gets the netflix titles from the data service.
/// </summary>
/// <returns></returns>
/// <summary>
/// Gets the netflix titles from the data service.
/// </summary>
/// <returns></returns>
[HttpGet("titles")]
public IActionResult GetTitles()
{
// Create a new API response class.
ApiResponse apiResponse = new ApiResponse();
// Create a new list of titles and a new list of title dtos.
List<Title> titles = new List<Title>();
List<TitleDTO> titleDTOs = new List<TitleDTO>();
// Get the list of titles from the data service.
titles = _dataService.GetTitles();
// Foreach title retrieved from the data service.
foreach(Title t in titles)
{
// Create a new data transfer object and set the retrieved titles properties to the new object's properties.
TitleDTO titleDTO = new TitleDTO();
titleDTO.Id = t.Id;
titleDTO.Categories = new List<CategoryDTO>();
// For each title category in the title's title categories...
foreach(TitleCategory tc in t.TitleCategory)
{
// Create a new category data transfer object and set the current title's current title categories category properties to the new object.
CategoryDTO category = new CategoryDTO();
category.Id = tc.Category.Id;
category.Category = tc.Category.Name;
// Add the created category dto to the current title dto's list of categories.
titleDTO.Categories.Add(category);
}
titleDTO.Rating = t.Rating;
titleDTO.ReleaseYear = t.ReleaseYear;
titleDTO.ShowId = t.ShowId;
titleDTO.Title = t.Name;
titleDTO.DateAdded = t.DateAdded;
titleDTO.Description = t.Description;
titleDTO.Type = t.Type;
titleDTO.Duration = t.Duration;
// Add the created title dto to the list of title dtos.
titleDTOs.Add(titleDTO);
}
// Set the api response to be a success status, and the payload to be the retrieved titles.
apiResponse.Status = 0;
apiResponse.Payload = titleDTOs;
// return the response as a JSON object.
return Json(apiResponse);
C Add two more GET requests to the API Controller to get the categories and entertainment types.
1 Create the GetCategories method that returns IActionResult. Add a HttpGet attribute with the route of "categories".

Create a new APIResponse variable named apiResponse.

Create a new list of type CategoryDTO named categoryDTOs

Create a new list of type Category named categories.

Call the _dataService's GetCategories method and set the result to the categories variable.

For each Category in the categories list.

Create a new CategoryDTO named cd.

Set the categories' id to the cd's Id property.

Set the categories' Name to the cd's Category property.

Add the cd to the categoryDTOs list.

Set the apiResponse's Status property to 0 and set the categoryDTOs variable to the apiResponse's Payload property. Return JSON(apiResponse).

2 Create the GetEntertainmentTypes method that returns IActionResult. Add a HttpGet attribute with the route of "types".

Create a new APIResponse variable named apiResponse.

Create a new list of EntertainmentType named entertainmentTypes.

Call the _dataService's GetEntertainmentTypes method and set the results to the entertainmentTypes list.

Set the apiResponse's Status property to 0 and set the entertainmentTypes variable to the apiResponse's Payload property. Return JSON(apiResponse).

11.To set the returned Json Settings, add the below code to the services.AddControllers call, in the ConfigureServices method…

To set the returned Json Settings, add the below code to the services.AddControllers call, in the ConfigureServices method in the startup class.

services.AddControllers().AddNewtonsoftJson();

You will need to add the Microsoft.AspNetCore.Mvc.NewtonsoftJson package to your project from NuGet Packages.

A To set the returned Json Settings, add the below code to the services.AddControllers call, in the ConfigureServices method…

To set the returned Json Settings, add the below code to the services.AddControllers call, in the ConfigureServices method in the startup class.

12.Check your work
A In your Postman workspace, add a new collection named 12.3LabNetflixTitles
B Click on the eye in the upper right corner, and click the Add link in the upper left corner to create a new Local environment.
C Add a new variable named domain with the initial value of https://localhost:5001/api as shown in the below image. Click Add.
Add environment for 12.3 Lab. Use the adjacent task instructions to identify the required controls, output, or debugger values.
Add environment
D Add a GET request named titles, with the below URL that utilizes the domain variable.
{{domain}}/api/titles
E Add a GET request named categories, with the below URL.
{{domain}}/api/categories
F Add a GET request named entertainmenttypes, with the below URL.
{{domain}}/api/types
G Run your project, your browser should display a blank page with https://localhost:5001/api as the URL.
H Once the blank page is displayed in your browser, click Send in Postman to send the Get/titles request. You should receive a…

Once the blank page is displayed in your browser, click Send in Postman to send the Get/titles request. You should receive a response, similar to the below image.

titles api response for 12.3 Lab. Use the adjacent task instructions to identify the required controls, output, or debugger values.
titles api response
I While your application is still running click Send in Postman for both the categories and entertainment types request. The…

While your application is still running click Send in Postman for both the categories and entertainment types request. The responses should be similar to the below images.

categories for 12.3 Lab. Use the adjacent task instructions to identify the required controls, output, or debugger values.
categories
types for 12.3 Lab. Use the adjacent task instructions to identify the required controls, output, or debugger values.
types
Add a title through the API
Acceptance Criteria
Acceptance criteria
  • The POST accepts the specified title fields and stores the record.
  • The response reports the required success result.
  • The follow-up GET and database check confirm the new record, and the ZIP and Word evidence are submitted.
Instructions
13.Create a POST request.
A In the DataService class add a method named AddTitle that accepts a parameter of type Title named title.
1 Call the _dataContext field's Add method, and pass in the title parameter.
2 Call the _dataContext field's SaveChanges method
B Create another method in the DataService class named AddTitleCategory that accepts a parameter of type TitleCategory named…

Create another method in the DataService class named AddTitleCategory that accepts a parameter of type TitleCategory named titleCategory.

1 Call the _dataContext field's Add method, and pass in the titleCategory parameter.
2 Call the _dataContext field's SaveChanges method
C In the APIController, create a new AddTitle POST method as shown below.
[HttpPost("add/title")]
public IActionResult AddTitle([FromBody]TitleDTO titleDTO){}

The [FromBody] attribute forces the API to read the type from the call's request body.

1 Create a new instance of the Title class and set it to a variable named title.
2 Set all of the titleDTO's properties to the corresponding title's property.
3 Create a new instance of TitleCategory and set it to the title's TitleCategory property.
4 Call the dataService's AddTitle method, passing in the title variable.
5 Get the newly added title with the below code.

Title addedTitle = _dataService.GetTitles().Where(x => x.ShowId == titleDTO.ShowId).FirstOrDefault();

6 foreach CategoryDTO in titleDTO's Categories

Create a new instance of the TitleCategory class named tc.

Set the addedTitle's Id property to the TitleCategory's TitleId property.

Set the CategoryDTO's Id property to the TitleCategory's CategoryId property.

Call the _dataService's AddTitleCategory() method, passing in the tc variable.

7 return a new StatusCodeResult passing in 200.
8 The completed POST request should look like the below code.
[HttpPost("add/title")]
public IActionResult AddTitle([FromBody]TitleDTO titleDTO)
{
Title title = new Title();
title.ShowId = titleDTO.ShowId;
title.Name = titleDTO.Title;
title.Rating = titleDTO.Rating;
title.ReleaseYear = titleDTO.ReleaseYear;
title.TypeId = titleDTO.Type.Id;
title.DateAdded = titleDTO.DateAdded;
title.Duration = titleDTO.Duration;
title.Description = titleDTO.Description;
title.TitleCategory = new List<TitleCategory>();
_dataService.AddTitle(title);
Title addedTitle = _dataService.GetTitles().Where(x => x.ShowId == titleDTO.ShowId).FirstOrDefault();
foreach (CategoryDTO c in titleDTO.Categories)
{
TitleCategory tc = new TitleCategory();
tc.TitleId = addedTitle.Id;
tc.CategoryId = c.Id;
_dataService.AddTitleCategory(tc);
}
return new StatusCodeResult(200);
}
14.Check your work
A In Postman, add a POST request named POST/add/title. Use the below URL for the connection string, using the domain local…

In Postman, add a POST request named POST/add/title. Use the below URL for the connection string, using the domain local environment variable.

{{domain}}/api/add/title
B In the body tab, select the raw radio button, and select JSON from the drop down menu.
C Paste in the below JSON object into the body editor.
{
"categories": [
{
"id": 23,
"category": "Horror Movies"
}
],
"dateAdded": "2020-11-23 00:00:00.0000000",
"description": "A movie about an alien",
"duration": "117 min",
"title": "Alien",
"rating": "R",
"releaseYear": 1979,
"showId": 101,
"type": {
"id": 2,
"type": "Movie"
}
}
D Run your application, once the blank page displays in your browser window, click Send on the POST/add/title request.
E The response should be empty with a Status of 200 OK.
F Send the GET/titles request and scroll down to the bottom of the response to verify that the movie, and all of it's…

Send the GET/titles request and scroll down to the bottom of the response to verify that the movie, and all of it's properties were added.

15.Submit a zipped folder containing your completed application and a Word Document with snippets of successful responses of…

Submit a zipped folder containing your completed application and a Word Document with snippets of successful responses of each of the API calls in Postman.

A Submit a zipped folder containing your completed application and a Word Document with snippets of successful responses of…

Submit a zipped folder containing your completed application and a Word Document with snippets of successful responses of each of the API calls in Postman.

Completion review
16.Review the feature acceptance criteria
A Confirm the required results

Return to each story and verify its acceptance criteria. Preserve the submission format and destination stated in the activity; a reading, setup guide, lab, video demonstration, and oral final may require different evidence.

Prepare the Netflix Titles database and API Map and query the stored titles Return titles, categories, and types Add a title through the API