Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / SQL

Angular and .NET Core Web API Starter Application

5.00/5 (1 vote)
2 Nov 2020CPOL4 min read 6.5K   33  
Angular/.NET Core Web API application that can be used as the starting point for building your applications.
This is an Angular and .NET Core Web API Starter Application with basic functionality for adding, editing, and deleting customers so you can use it as a starting point for building your applications.

You can see the source and latest updates to this project HERE

This is an Angular/.NET Core Web API starter application that has the basic functionality for adding, editing, and deleting customers so that you can use it as a starting point for building your applications. It uses the following frameworks:

  • Angular Material
  • Bootstrap
  • .NET Core
  • Entity Frameworks

How to run on your computer

Please be sure to have the following installed first:

  • Node v12.19.*
  • Angular CLI 10.2.*
  • .NET Core 3.1

In the code downloaded, open the file api/Api/appsettings.Development.json and change the Data Source to point to your SQL Server:

"AngApiStarterConn": "Data Source=YourServerNameHere;
Initial Catalog=AngApiStarter;Integrated Security=True;"

Build the API solution to make sure the NuGet packages are installed and the solution builds successfully.  The solution needs to be built successfully before you can run Entity Framework updates for the database.

Open the command prompt and navigate to api/Data, then run the command below which will update your SQL Server with the structure needed for the application:

dotnet ef database update -s ..\Api\Api.csproj

You should now have a database named AngApiStarter with a table named Customers in the SQL Server. You can insert a sample customer with the SQL below into the table:

insert into customers(firstName, lastName)
values('John', 'Smith');

Check that the API can get the data from the database by running the API project and go to the url below, which should return the list of customers in the database:

https://localhost:44381/api/customer

Navigate to the ui folder in the command prompt and run the command below to get the libraries needed for running Angular:

npm update

If you get an error for modules not found, then you can run the command below to get the modules needed:

npm install

Start Angular by running the command below, which will start the server and open the application in the browser:

ng serve --open

How the application was built

Starting with the data layer from the API, a class model for Customer was created:

C#
public class Customer
    {
        [Required]
        public int CustomerId { get; set; }

        [Required, StringLength(80)]
        public string FirstName { get; set; }
        [Required, StringLength(80)]
        public string LastName { get; set; }
    }

Then the DbContext class for the Customer was created, using the Customer class as the DbSet which will ultimately become a table in the database:

C#
public class AngApiStarterDbContext : DbContext
    {
        public DbSet<Customer> Customer { get; set; }

        public AngApiStarterDbContext(DbContextOptions<AngApiStarterDbContext> options)
            : base(options)
        {
        }
    }

In the API project, we then define the database connection string, and add the code below to the ConfigureServices method of the Startup.cs as shown below. This is so that we can use the connection string defined in the API project to create the database and table in SQL Server:

//add the db context with the connection string
            services.AddDbContextPool<AngApiStarterDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("AngApiStarterConn"))
            );

Build the solution, then using the command prompt, navigate to the Data project folder and run the command below to create the classes for the database migration:

dotnet ef migrations add initialCreate -s ..\Api\Api.csproj

After the classes are created, run the command below to create the database and tables in SQL Server:

dotnet ef database update -s ..\Api\Api.csproj

In the Data project, it has the Interface and the implementation of the Interface using Entity Framework:

public interface ICustomerData
    {
        Task<IEnumerable<Customer>> Get();
        Task<Customer> GetCustomerById(int id);
        Task<Customer> Update(Customer customer);
        Task<Customer> Add(Customer customer);
        Task<int> Delete(int customerId);
    }
public class SqlCustomerData : ICustomerData
    {
        public AngApiStarterDbContext DbContext { get; }

        public SqlCustomerData(AngApiStarterDbContext dbContext)
        {
            DbContext = dbContext;
        }

        ...
    }

Now on to the API project. In the API project, it defines the implementation class for the interface in the ConfigureServices method:

services.AddScoped<ICustomerData, SqlCustomerData>();

Then the controller too uses the interface by dependency injection:

public class CustomerController : ControllerBase
    {
        public ICustomerData CustomerData { get; }

        public CustomerController(ICustomerData customerData)
        {
            CustomerData = customerData; 
        }

        ...

Since the API and the UI will be run from different website, it needs to allow the UI website to access the API using CORS. In the API’s appsettings.Development.json, it has the UI’s url:

"CorsUrl": "http://localhost:4200"

Then the CORS policy is specified in the Startup.cs file:

private readonly string corsPolicy = "defaultPolicy";

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy(corsPolicy,
                builder =>
                {
                    builder.WithOrigins(Configuration["CorsUrl"])
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                            .AllowCredentials();
                });
            });

            ...
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            ...
            app.UseCors(corsPolicy);
            ...
        }

Now on to the UI project with Angular. Using the Getting Started project from Angular, the Angular Materials components are defined in the project under app/common/material.module.ts, where all the components are added so that you can use the components without explicitly adding it to app.module.ts.  Then in app.module.ts, it just includes the Material module:

import { MaterialModule } from './common/material.module';

The location of the API url is defined in environments/environments.ts file:

export const environment = {
  production: false,
  apiCustomer: 'https://localhost:44381/api/customer'
};

The model is defined in model/ICustomer.ts file, with the same model signature as the API:

export interface ICustomer{
    customerId: number,
    firstName: string,
    lastName: string
}

The support for interacting with the API is in service/customer.service.ts file. It uses BehaviorSubject to make the list of customers as an Observable (you can think of it as a data stream).  When the Observable changes, all the Observers (you can think of it as listeners or subscribers) get notified of the change and can react accordingly.  In the CustomerService class, the customerList.next method is called when the Observable needs to notify all the Observers:

private customerList = new BehaviorSubject<ICustomer[] | null>(null);
    customerList$ = this.customerList.asObservable();

    ...

    //get the list of customers
    get(){
        this.http.get<ICustomer[]>(this.url).pipe(
            ).subscribe(result => {
                if (result)
                    //notify the Observers of the change
                    this.customerList.next(result)
            });
    }

The Customer component, which shows the list of customers that you can manage, listens to the changes in the CustomerService class by subscribing to it in the ngOnInit method:

export class CustomerComponent implements OnInit {

    ...
    ngOnInit(){
        this.custService.customerList$.subscribe(data =>
            this.customerList = data
        );
    }

When the user clicks on the Add or Edit customer button, it opens a dialog which you can pass the data to the dialog, and define the action to take when the dialog is closed.  Below shows the data passed to the dialog when adding a new customer, and calling the CustomerService when the dialog is closed:

openAddDialog(){
        let dialogRef = this.custDialog.open(CustomerDialog, {
            width: '300px',
            data: {
                    action: 'add',
                    customer: { customerId: 0, firstName: '', lastName: ''}
                  } 
        });

        dialogRef.afterClosed().subscribe(result => {
            //add the customer
            if (result)
                this.custService.add(result)    
        });
    }

For editing customer, it needs to pass a copy of the customer data to the dialog instead of the actual customer data, so that if the user decided to cancel the customer values are not changed:

customer: {...customer} //shallow copy the customer using spread operator

The dialog component is defined in app/customer/dialog/customer-dialog.component.ts, which accepts the caller’s data using MAT_DIALOG_DATA from Material’s Dialog component:

export class CustomerDialog {

    ...

    constructor(public dialogRef: MatDialogRef<CustomerDialog>,
                @Inject(MAT_DIALOG_DATA) public data: any) {
        this.action = data.action;
        this.customer = data.customer;
    }

Finally, the bootstrap library is added using npm and the reference to the bootstrap stylesheet is added to index.html:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap...>

In the CustomerComponent’s html, the bootstrap’s flexbox classes are added to center align the elements and organize the layout:

<div class="d-flex flex-row justify-content-center">
        <div class="d-flex flex-column">

And that’s all. Hope you find it useful as a starting point for your projects.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)