Deploying Angular App using Asp.Net Core and Azure SQL

Firat
14 min readDec 13, 2022

--

I will show you an easy way to deploy your full-stack application to Azure quickly using Angular and Asp.Net Core 6.

Basically, you can use your own hosting firm to deploy your projects but if you use the same host to deploy multiple applications that consist of angular and asp.net core, you might run into CORS policy problems. Sometimes the CORS problem could be tricky when you do not check the correct point which is why you can use Azure and deploy your application cheaper and sometimes free.

Azure will be easy to configure in terms of CORS because it has its own CORS configuration.

Create an angular project using

ng new <project-name>

After creating your angular app, open it using VS code

<your application root>/code .

You should have a similar screen after all processes

Now, time to create an ASP.Net Core 6 web application to have some Restful APIs.

Click on Create a new project
Type Asp.Net Core Web API and select the first one
Put the Project name and select the location. After that, click on the Next button.
Just click on the Create button

You should have a screen like this after all process

Now, time to create a SQL database on Azure. Go to the

https://azure.microsoft.com

Click on sign in and put in your credentials.

Before you create an SQL database, you need to create a subscription. Go to the search box and type subscription after that click on Subscription.

Click on the Add button and fill in the details.

After filling in the details, click on the Review+create button and then create it. Now, you have a subscription name and can use it to create a SQL database. Go to the search box and type SQL database and select SQL databases

Click on SQL databases

Click on SQL databases

Click on the Create link

Click on the Create link

Select Subscription and Resource group. If you do not have a resource group, click on the create new button and create a new resource group.

Type a database name that you like and if you do not have a server, click on the create a new link.

You will see a page like this put the details and then click on the OK button.

We do not need SQL elastic pool at this time which is why keep it No.

The workload environment will be Production as it is.

Now, you should configure your database, otherwise, you might face a big bill end of the month which is why to go to Configure database and then select Basic service tier. Its estimated cost should be 4.90 USD.

You do not need backup storage right now and that is why the third one will be ok for you. Click on the review+create button and continue.

You will see a summary page of your SQL database and then click on the create button if you are comfortable with the summarize page.

After the SQL database is created you should be able to see the new SQL database in the list, click on the DB name, and then check the details of SQL DB.

In order to connect SQL DB on Azure, you have to create a firewall rule for the Backend. That is why go to your backend app and copy the IP

Create a firewall rule. Basically, you are saying that your backend IP can go through SQL Db.

Now, time to configure our backend project which is why click on the show database connection string link and then copy the connection string.

Open the backend project and go to the appsettings.Development.Json file and enter the ConnectionString

In order to test your database connection, go to the Microsoft SQL Management Studio and try to connect to the server.

If you get the below error after clicking on the Connect button

Go to Azure SQL DB and click on the Set Server firewall tab.

Set the Public network access to Selected networks and then click on the Save button.

Now, you should be able to connect to the database. ( If Management studio wants you to sign in to Azure, just put in your credentials and connect the Azure)

After you connect to the management studio, you are able to see your DB in the database list.

In order to test our client and backend API, we should create a table. The below code shows how we create a table using T-SQL but if you do not want to use the code, you will see how we create a table using EF Core below.

create table [Users]
(
Id int primary key identity(1,1),
[Name] varchar(25),
LastName varchar(25)
)

Now, time to create a DbContext to connect to the Database. In order to have this process, go to the visual studio and follow the steps respectively;

  1. Add entity framework packages
  2. Create a data folder
  3. Create an entity folder in the data folder
  4. Create a user entity model class in the entity folder
  5. DbContext class in the data folder and implement DbContext

Add Packages…

In order to use the entity framework and connect to the database, we have to install some packages which are

  1. Microsoft.EntityFrameworkCore
  2. Microsoft.EntityFrameworkCore.Design
  3. Microsoft.EntityFrameworkCore.Relational
  4. Microsoft.EntityFrameworkCore.SqlServer
  5. Microsoft.EntityFrameworkCore.Tools

Right-click on the solution and select Manage NuGet Packages.

After you add packages, create a folder which is named Data. In the data folder, create another folder which is named Entity.

Create UserEntity class in the Entity folder

Create DbContext class in the Data folder

You can create your folder and class structure whatever you want. You do not have to follow my structure.

After all processes, you should have folders and classes like the ones below

User Entity Class

namespace AzureDeployment.Data.Entity;

public class UserEntity
{
public int Id { get; set; }
public string? Name { get; set; }
public string? LastName { get; set; }
}

DbContext class

using AzureDeployment.Data.Entity;
using Microsoft.EntityFrameworkCore;

namespace AzureDeployment.Data;

public class MediumDbContext : DbContext
{
public MediumDbContext()
{

}
public MediumDbContext(DbContextOptions options) : base(options)
{
}

public DbSet<UserEntity> Users { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer("<your connectionstring>");
}

To create a database using the code

add-migration <migration-name>

If you get an error, put this code in DbContext class

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("<your connectionstring>");
}
}

After the migration file is created, use the code

update-database

After all processes, you should be able to see the database with a table

Use the SQL code to create a row

INSERT INTO [Users] VALUES('Name','LastName')

Now, create an API to fetch the data. In order to do this, we will create a folder which is named Services and implement a fetching service in it. After that, we will inject our service into the controller and configure it in the program.cs using dependency injection technique.

After you create folders and files, you should have a structure like the one below

IUserService.cs

namespace AzureDeployment.Services;

public interface IUserService
{
Task<object> GetAllUsers();
}

UserService.cs

using AzureDeployment.Data;
using AzureDeployment.Data.Entity;
using Microsoft.EntityFrameworkCore;

namespace AzureDeployment.Services;

public class UserService : IUserService
{
private readonly MediumDbContext _context;

public UserService(MediumDbContext context)
{
this._context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<object> GetAllUsers()
{
try
{
return await _context.Users.ToListAsync();
}
catch (Exception excp)
{
// if you have a logging mechanism, implement here
throw;
}
}
}

UserController.cs

using AzureDeployment.Services;
using Microsoft.AspNetCore.Mvc;

namespace AzureDeployment.Controllers;

[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserService _userService;

public UserController(IUserService userService)
{
this._userService = userService;
}

[HttpGet]
[Route("GetAllUsers")]
public async Task<IActionResult> GetAllUsers()
{
return Ok(await _userService.GetAllUsers());
}
}

After you create the API, try it to see if it is working or not. Run the project and check it on the swagger.

You should have a result like below

Now, time to configure the client side. You need to create a service and get the data from the API. That is why go to the angular project and create a service using

ng generate service <your-service-name>

Here, you have to import HttpClientModule to imports in the app.module.ts file

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

After importing HttpClientModule you will be able to inject HttpClient into your service and create the function to retrieve all user data from the API. Before you create the function, go to the environment.ts file under the environment folder and add the backend URL.

Go to your service and create an instance of it after adding the backend endpoint to environment.ts

Create the HTTP get method and retrieve the data from API in User.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';

@Injectable({
providedIn: 'root'
})
export class UserService {

private API_URL=environment.API_URL;

constructor(private _httpClient:HttpClient) { }

getAllUsers():Observable<any>{
return this._httpClient.get<any>(this.API_URL+'api/user/GetAllUsers');
}
}

In order to use Observable, import RxJS because observable is coming from the RxJS library.

Implement getAllUsers function and get the data from the service in app.components.ts

import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'Test';

users:any=[];
constructor(private _userService: UserService) { }

ngOnInit() {
this.getAllUsers();
}

getAllUsers() {
this._userService.getAllUsers().subscribe({
next: response => {
this.users=response;
},
error: error => alert('Error occured when retrieving the data')
})
}
}

Use ngFor directive and show the data in app.component.html

<ul>
<li *ngFor="let user of users">
{{user.name}} - {{user.lastName}}
</li>
</ul>

The last thing, is you have to enable CORS to have communication between your Angular App and API which is why go to your backend project and update the program.cs file. (If you do not enable it, you will get a CORS error once you try to retrieve data from API)

In order to enable CORS

var confCors = "ConfCors";
builder.Services.AddCors(options =>
{
options.AddPolicy(confCors,
policy =>
{
policy.AllowAnyHeader().
AllowAnyMethod().
AllowAnyOrigin();
});
});

.....
.....

.....
.....

app.UseCors(confCors);

You can put a specific Client endpoint if you want to but in this example, we can accept all endpoints.

After you enable the CORS, you should have a program.cs like this one below

using AzureDeployment.Data;
using AzureDeployment.Services;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddTransient<IUserService, UserService>();


builder.Services.AddControllers();

builder.Services.AddDbContext<MediumDbContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("AzureDbConnection"));
});


// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var confCors = "ConfCors";
builder.Services.AddCors(options =>
{
options.AddPolicy(confCors,
policy =>
{
policy.AllowAnyHeader().
AllowAnyMethod().
AllowAnyOrigin();
});
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseCors(confCors);

app.UseAuthorization();

app.MapControllers();

app.Run();

Now, you can test your projects. First, run the backend project and then run the angular app. For angular app, you can use

ng serve --o

After you run both projects, you will be able to see the result

Now, time to deploy our projects to Azure. In order to deploy our projects you need to create WebApp which is why go to Azure and type App Services in the Search box.

Click on App Services and then Create button.

Fill in the details

I chose Free F1 because of this article. You can choose up to your requirements.

Click on Review+Create after filling in all details and check your web app details. Click on Create button if you are ok with your web app details.

This will be for the Backend and now you will deploy your backend to the web app. Click on Go to resource after deployment is done and then click on Get publish profile to download the profile

Go to your backend project and right-click on the solution and Publish

Select Import Profile and add the import file that you downloaded from Azure. Click on Finish.

Click on Publish and wait for the process to be done.

You should get a succeeded message once it is done

Let’s try to call API from the client side. First, you need to update the environment.ts file because you will try to connect to Azure. Go to your MediumBackend web app and copy the URL and paste it into the environment.ts

environment.ts should be like this

// This file can be replaced during build by using the `fileReplacements` array.
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const environment = {
production: false,
API_URL:"https://mediumbackend.azurewebsites.net/"
};

/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.

Once you try to fetch data, you will get a CORS error

because Azure has its own CORS policy configuration and you have to configure it before you call the API which is why to go to Azure > your backend project and then search for CORS

Add http://localhost:4200 (or your UI endpoint) to Allowed Origins and click on the Save button.

After the configuration is done, you should be able to see the data on the page.

Now, you have to create one more Web App for the Angular project. You can check how to create a Web App above. You need to select the node js version on your machine for the Angular app service. I am using Node Js v16 which is why I selected it.

Note that if you do not select windows machine, you might face some errors when you are trying to deploy your angular app.

Could not detect any platform in the source directory.

Error: Couldn’t detect a version for the platform ‘nodejs’ in the repo.

Once you create a web app, go to VS code

  1. Update environment.prod.ts
export const environment = {
production: true,
API_URL:"https://mediumbackend.azurewebsites.net/"
};

2. Execute the ng serve --configuration=production, after that, you should have a dist folder

3. Install the Azure App Service extension

Once you install the extension, connect to your Azure Web App.

Right-click on your Angular service and select Deploy to Web App

And then select Browse and select your dist folder.

After deployment is done, you might face the error below

You need to make some configuration

  1. Configure your root
  2. Update CORS

Go to the configuration of Angular App and do index.html as the default

Go to Path mappings and update your Physical path. You can find your application name in package.json

Go to CORS and enter your angular app endpoint to the backend app service

After configurations are done, you should be able to see the result

It is a long explanation but I tried to show how a full-stack project can be deployed to Azure easily.

You can access code the links below

Angular: https://github.com/frttnk/Angular-App-for-Medium

API: https://github.com/frttnk/Asp.Net-Core-6-Restful-API

--

--

Firat

I am a Senior Full-Stack .Net Developer who is trying to share hands-on experience and other technologies that are related to Full-stack development.