Abstract: ASP.NET Core 3.0 with EF Core 3.0 provides a cool mechanism to access Cosmos DB for performing CRUD operations, very similar to a relational database. The built-in Angular template with ASP.NET Core provided a rich experience for front-end development. This tutorial builds an end-to-end app to utilize these conce
For developing modern web applications, a robust application framework, as well as a solid runtime is needed both on the server-side and at the front-end.
ASP.NET Core 3.0 is one such open-source framework which integrates seamlessly with client-side frameworks and libraries, including Blazor, React, Angular, Vue.js etc.
Editorial Note: If you are new to .NET Core 3.0, read What’s New in .NET Core 3.0?
.NET Core 3.0 introduces various new features, some of them being:
- Single-File Executable
- Assembly linking
- Tiered compilation
- Desktop Applications like WPF and WinForms
- …and many more
All these new features are useful for modern application development.
Web Applications often have complex requirements now-a-days. Some of these requirements demand that the application must be cross-platform, application data must be stored in relational as well as NoSQL database, the front-end must be modular and highly responsive, and so on.
.NET Core was created to be cross-platform and releases from .NET Core v2.0 onwards, help to design solutions to fulfill most of these requirements.
In ASP.NET Core 2.0 onwards, application templates provide an integration with front-end frameworks like Angular, React, React-Redux. We can make use of these templates to develop applications as per the requirements from users.
Editorial Note: In case you are interested in a Vue.js template, check this tutorial: ASP.NET Core Vue CLI Templates.
Figure 1 shows a projected application implementation we will be building in this tutorial.
Figure 1: ASP.NET Core application with EF Core, SQL Server, CosmosDB and Angular
As seen in Figure 1, in .NET Core 2.2, EF core v2.2 was used only as an ORM for relational databases like SQL Server, etc. So, it was necessary for developers to write a separate data access layer for accessing data from Azure Cosmos DB, generally classified as a NoSQL database. This means that our .NET Core 2.2 application would need separate Data Access Layers for relational databases, as well as for a NoSQL one.
Editorial Note: Those new to Cosmos DB can read Azure Cosmos DB – Deep Dive.
In .NET Core 3.0, there is a cool feature provided in EF Core 3.0 which can be used to map the entity classes to a Cosmos DB NoSQL database and generate the database in the traditional code-first approach.
We can make use of DbContext class to map with the Cosmos DB database collection.
.NET Core 3.0 provides the Microsoft.EntityFrameworkCore.Cosmos package which provides the Microsoft.EntityFrameworkCore.Cosmos assembly. This assembly contains the CosmosDbContextOptionsExtensions class with the UseCosmos overloaded method. This is an extension method for the DbContextOptionsBuilder class and this class is used to configure the Cosmos DB database for the application.
The UseCosmos method accepts the following parameters:
- The Cosmos DB database account endpoint – application can connect to Cosmos DB using this Endpoint
- The Account key – used for client application authentication
- Database Name – to which the application is connecting
Using EF Core 3.0, one can directly access the Azure Cosmos DB database and perform CRUD operations. You can use the Code-First approach of EF Core to create a database and collection. Using the ASP.NET Core 3.0 Angular Template and EF Core 3.0 with Cosmos DB, we can modify Figure 1 to the one shown in Figure 2:
Figure 2: Using EF Core 3.0 as ORM for Cosmos DB
Developing an application Using ASP.NET Core 3.0, EF Core 3.0 and Azure Cosmos DB
Let’s first create a Cosmos DB database account so that we can have an Endpoint and Key to access Cosmos DB in our application.
Step 1: Open Azure portal using portal.azure.com. Make sure that you have an Azure subscription. Once you login with your credentials, you are inside the portal.
Step 2: In the portal, click on the Create a resource link blade on the top left (see Figure 3). In the search box on this blade, enter Azure Cosmos DB, and the UI will display the Azure Cosmos DB option as shown in Figure 3.
Figure 3: The Cosmos DB resource option in the portal
Click on the Azure Cosmos DB link that is marked red in the above figure. This will open a new blade for creating an Azure Cosmos DB Account as shown in Figure 4.
Figure 4: Create an Azure Cosmos DB Account
To create an Azure Cosmos DB Account, you need to enter the Azure Subscription and Resource Group (if you have not already created a resource group, it can be created using Create new link provided below the Resource Group combobox).
You can then enter an Account Name as per your choice and then select the Cosmos DB API. In our case, we will be using Core (SQL) which is a JSON document storage. You need to select a Location for the Account and other information as per your requirement. To create the account, click on the Review + create button. Once the Cosmos DB Account is created, we can see its details as shown in Figure 5.
Figure 5: The Azure Cosmos DB Account
Figure 5 shows the Cosmos DB Account details. We can use Data Explorer (marked red) to view all the databases and their containers. The Keys (marked red) in Figure 5 are authentication keys so that the client application can connect with Cosmos DB and perform operations like create database, create container, etc.
Are you a .NET, C#, Cloud or Web Developer looking for a resource covering New Technologies, in-depth Tutorials and Best Practices?
Well, you are in luck! We at DotNetCurry release a FREE digital magazine once every few months aimed at Developers, Architects and Technical Managers. This magazine covers ASP.NET Core, Xamarin, C#, Patterns and Practices, .NET Core, ASP.NET MVC, Azure, DevOps, ALM, TypeScript, Angular, React, Vuejs and much more.
Subscribe to this magazine for FREE and receive the current and upcoming editions, right in your Inbox. No Spam Policy.
Creating an ASP.NET Core 3.0 application with Angular Template
As we have created a Cosmos DB Account, it’s time for us to create an ASP.NET Core 3.0 application with an Angular template. This template was introduced in ASP.NET Core 2.2.
We will create Web APIs using ASP.NET Core 3.0. These Web APIs will access Cosmos DB. The Angular application will be the front-end for our application. We will create an Angular application that will capture the profile information of Students and this profile information will be stored in Cosmos DB as JSON documents. The overall structure of the application is explained in Figure 6.
Figure 6: The actual application
Step 1: Open Visual Studio 2019 and create a new ASP.NET Core Web Application. Name this application as ProfileAppNet30. Select the Angular Template for the application. Make sure that you select ASP.NET Core 3.0 as the project version as shown in Figure 7.
Figure 7: The ASP.NET Core 3.0 app with Angular template
Note: Please disable the option “Configure for HTTPS” if you are using Kestrel to avoid CORS errors. Otherwise you will have to change the protocol to https and port to 5001 in the Angular application.
Open the Solution Explorer to see the project structure with references of assemblies targeted to .NET Core 3.0 as shown in Figure 8.
Figure 8: The ASP.NET Core 3.0 Project structure
The ClientApp folder shows the Angular application structure. If you look in the package.json file, you will see that the Angular version supported for this template is Angular 8.0.0.
Step 2: Since we need to access Cosmos DB using EF Core, we need to add EF Core package to the project. (Note that the EF Core package is not present by default in the ASP.NET Core 3.0 Project Template.)
Right click on Dependencies and select Manage NuGet Packages. Search for Microsoft.EntityFrameworkCore.Cosmos package. Once the package is found, install it as shown in Figure 9.
Figure 9: Installing Microsoft.EntityFrameworkCore.Cosmos package
Step 3: Modify the appsettings.json file by adding key/value pairs for Cosmos DB settings like EndPoint, AccountKey and DatabaseName. The EndPoint, AccountKey and DatabaseName can be found from the Settings > ConnectionString blade.
Listing 1: appsettings.json for Cosmos DB Settings
Step 4: In the project, add a folder named Models and in this folder, add a new class file and name it as ModelClasses.cs. In this class file, add the following code:
Listing 2: The Model classes. These classes will be used to map with Cosmos DB to create JSON documents
The Education class contains properties for storing Education details of the end user. The WorkExperience class contains properties to store experience of the end user. The ProfileMaster class contains properties for storing personal information of the end user. This class also contains a list of Education details and WorkExperiences of the end user. This is done for a One-To-Many Relationship between ProfileMaster to Education and WorkExperience classes.
We expect that the collection contains JSON document with collection of Education details and WorkExperiences for a single Profile information.
Step 5: In the Models folder, add a new class file and name it as ProfileDbContext.cs. Add the following code in this file:
Listing 3: The ProfileDbContext class contains code for EF Core mapping with Cosmos DB.
If you have used EF Core earlier, then you will find the code familiar. If not, here’s an old albeit useful tutorial.
The ProfileDbContext class is derived from DbContext class. This class is responsible for connection creation and mapping with the database. The class contains a DbSet property for ProfileMaster model class. This will map with the container in Cosmos DB.
The OnModelCreating() method defines the container name as Profiles and defines the strategy of the document creation with relationship between ProfileMaster, Education and WorkExperience class. It contains code for defining a One-To-Many relationship between ProfileMaster, Education and WorkExperience class.
Step 6: In the project, add a new folder and name it as Services. In this folder, add an interface file and name it as ICosmosDbService.cs. Then add a class file, and name this class file as CosmosDbService.cs. Add the following code in ICosmosDbService.cs
Listing 4: The repository interface.
Add the following code in CosmosDbService.cs file
Listing 5: The repository class.
The ICosmosDbService interface is a multi-type generic interface. This interface defines methods for reading and writing data. This interface is implemented by the CosmosDbService class with TEntity parameter as ProfileMaster and TPk parameter as string. The class has a constructor injected with ProfileDbContext class. The constructor contains code to make sure that the database is created in Cosmos DB, if it has not already been created. The other methods of the class contain a familiar code for performing read and write operations against the database using EF Core.
Step 7: Modify Startup.cs file by adding the following code in the ConfigureServices() method of the Startup class
Listing 6: Registering ProfileDbContext class in DI Container along with CosmosDbService class and code for suppressing the default JSON serialization naming policy
Step 8: In the Controllers folder, add a new empty Web API controller and name it as ProfilesController.cs. In this controller, add code as shown in Listing 7:
Listing 7: The ProfilesController code
The controller we just saw in Listing 7 has the CosmosDbService class injected in the constructor . The controller contains HTTP Get and Post methods for returning and accepting profile information from an Angular client application.
Creating Angular Client Code
Step 1: Expand the ClientApp folder. In this folder, we have the src folder that contains the app sub-folder. In the app folder, add three folders named models, profile and services.
Since we will be using Angular material library for a rich UI like dialog-box, we need @angular/cdk and @angular/material package dependencies in the project. Open the Command Prompt and navigate to the ClientApp folder of the current application and run the following command to install these packages.
Note: Node.js must be installed on the machine to run npm command.
Step 2: In the Models folder, add a new TypeScript file and name it as app.constants.ts. This file will contain constant arrays:
Listing 8: Array constants for showing constant data in Angular View
Listing 8 contains constants for information (e.g. Degree, Specialization, etc.) that we need to capture from the end user.
Step 3: In the Models folder, add a new TypeScript file and name it as app.models.ts. This file will contain TypeScript classes for ProfileMaster, Education and WorkExperience corresponding server-side Models classes in our ASP.NET Core application.
Listing 9: Model classes on the client
Step 4: We will create an Angular Service to make an HTTP request to the Web API. To do so, in the Services folder, add a new TypeScript file and name it as app.profile.service.ts. In this file, add the code as shown in Listing 10.
Note: Run the application in Kestrel instead of IIS Express (the default used by VS 2019) otherwise, you will get a CORS error. If the application automatically redirects to HTTPS, change the baseUrl value in the code to https://localhost:5001.
Listing 10: Angular Service to request Web API
Listing 10 contains the ProfileService class decorated as @Injectable. This means that the class will be injected wherever it is required. This class HttpClient is injected in the service class for making an HTTP call to Web API.
Step 5: It’s time for us to create Angular Views and their logic.
To do so, we need to add components in the application. Since we intend to use Angular Material’s dialog boxes for WorkExperience and Educational details, we need to add separate components for a dialog box implementation.
To use a Dialog box in Angular, we need to use the MatDialogRef object. To pass data to this Dialog box, make use of the MAT_DIALOG_DATA object.
This object uses interface to accept data for the dialog box. In our application, we will show dialog boxes for Educational details and Work Experience which will be used by the end user to enter multiple records for Educational details and WorkExperience details.
In the profile folder, add a new TypeScript file and name it as app.educationinfo.dialog.component.ts.
Add the following code in this file as shown in Listing 11:
Listing 11: The Educational Details Dialog box
In Listing 11, the EducationDialogData defines an object of the type Education. This object will be used as MAT_DIALOG_DATA for the dialog box. This dialog box also uses various constant arrays declared in app.constants.ts file. To show user interface for the dialog box, add a new HTML file in the profile folder and name it as app.educationinfo.dialog.view.html.
Add the following markup for this file:
Listing 12: The HTML for the Education Dialog box
Editorial Note: A label can be bound to an element either by using the “for” attribute, or by placing the element inside the element. Here the author has skipped binding the label with the element as he won’t be using it anywhere, but nevertheless, it should be used to specify the type of form element a label is bound to.
Listing 12 shows markup that contains the following Material attributes:
· mat-dialog-title – represents title of the dialog box.
· mat-dialog-content – represents UI elements shown on the dialog box.
· matInput – represents the UI element which will be used to capture input from the end user.
· mat-dialog-actions – represents action elements e.g. button on the dialog box.
o The mat-dialog-actions are applied on button elements as mat-dialog-close. So, when the button is clicked, the dialog box will be closed.
Step 6: Similar to dialog boxes for Education details, we need to add a dialog box component for Work Experience also. In the profile folder, add a new TypeScript file and name it as app.workexperience.dialog.component.ts.
Add the following code in this newly added file:
Listing 13: The WorkExperience dialog component
To define user interface for the WorkExperience dialog, we need to add a new HTML file in the profile folder and name it as app.workexperience.dialog.view.html. Add the following markup in the HTML file:
Listing 14: The HTML for WorkExperience
We have added the dialog boxes! Now it’s time for us to define components that will use these dialog boxes and also display a user interface for accepting the profile information.
Step 7: In the profile folder, add a new TypeScript file and name it as app.profile.component.ts. In this file, add the following code
Listing 15: The ProfileComponent
The ProfileComponent uses Education and WorkExperience dialog boxes. This component has ProfileService and MatDialog objects injected in the constructor. Using ProfileService, the component can make HTTP calls to the Web API.
The MatDialog object is used to manage the dialog box. The MatDialog object contains a method to open the dialog box and a method to read data entered in the dialog box after the close event of the dialog box is fired. The saveProfile() method of the component will be used to access postProfile() method of the ProfileService to post the profile information to the server.
In the profile folder, add a new HTML file and name it as app.profile.component.view.html. In this file, add the following markup:
Listing 16: The ProfileComponent markup
The markup in Listing 16 contains input elements and select elements for entering the Profile information. These elements are bound with the properties defined in the ProfileMaster class.
We have tables for showing Education details and WorkExperience details. We have button elements on the top of these tables. These buttons are bound with the methods from the component class to open Education and WorkExperience dialog boxes.
In the component class, we have educationTableHeaders and workexperienceTableHeaders arrays. These arrays will be populated from properties of the Education and WorkExperience classes respectively. In the HTML markup, we will be dynamically generating table headers based on these properties.
Step 8: Modify the style.css as shown in the following listing to import @angular/material style to show dialog box.
Listing 17: The material style
Step 9: It’s time for us to update app.module.ts file from the app folder. In this file, we will import all components created for dialog boxes and ProfileComponent. We need to import various material modules so that dialog boxes will be executed successfully. Listing 18 shows the modified app.module.ts:
Listing 18: The app.module.ts file with required imports
We have defined the routing for the profile component using RouterModule. We have also imported various Material modules like MatDialogModule, MatInputModule, MatSelectModule, MatNativeModule to execute the MatDialog.
So far, so good! We have completed developing both the Server-Side as well as the Front end.
To test the application, run it using F5.
Note: The Application needs to run on Kestrel hosting environment (not IIS Express) since we are using http with port 5000.
Figure 10 shows the application loaded in the browser:
Figure 10: Application loaded in the browser
Update nav-menu.component.html to add the navigation for the profile page as shown in listing 19.
Listing 19: The navigation link for profile
Click on the Profile link on the top right, the following profile page as shown in Figure 11, will be displayed.
Figure 11: The Profile Page
Enter details like the First Name, Middle Name, Last Name etc. and click on the Click to Add Education button. This brings up the Dialog Box shown in Figure 12.
Figure 12: The dialog box
Click on the OK button, and the education details as shown in Figure 13 will be displayed in the table.
Figure 13: The Education details table
Now click on the Click to Experience details button to add experience details. A dialog box will be displayed where you can enter the experience details. Once these details are added, click on the Save button to add the profile and save the information in Cosmos DB. This will create a container named as Profiles and the document is added in it.
Figure 14 shows the data added in Cosmos DB by creating Profiles
Figure 14: The data added in Cosmos DB by creating Profiles
Conclusion: In this tutorial, we saw how ASP.NET Core 3.0 with EF Core 3.0 provides a cool mechanism to access Cosmos DB (classified as a NoSQL database ) for performing CRUD operations, very similar to a relational database.
Additionally, the built-in Angular template with ASP.NET Core provided a rich experience for front-end development. ASP.NET Core provides a unified platform for building web UI and web APIs using a Relational or a NoSQL Database.
No comments:
Post a Comment