{"id":84094,"date":"2019-04-25T15:20:08","date_gmt":"2019-04-25T15:20:08","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=84094"},"modified":"2026-04-15T18:29:24","modified_gmt":"2026-04-15T18:29:24","slug":"building-an-angularjs-application-with-asp-net-core","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/building-an-angularjs-application-with-asp-net-core\/","title":{"rendered":"Angular App with ASP.NET Core API: HTTP Calls and CRUD Integration"},"content":{"rendered":"<h2>Executive Summary<\/h2>\n<p><strong>This article builds an Angular frontend application connected to an ASP.NET Core Web API &#8211; a common modern .NET web architecture. The Angular app uses HttpClient to make HTTP requests to the API, and the project builds up from a basic GET call to a complete CRUD notes application supporting create, read, update, and delete operations through Angular components and services. Visual Studio Community Edition and the latest Angular CLI are the only requirements.<\/strong><\/p>\n<p>Many applications today have similarities when it comes to separating the front- and back-ends. It means that the back-end can be hosted anywhere: in the cloud or on a dedicated server. There can be many serverless functions. It can be created in any programming language, using any stack tools of your choice. The same can happen to the front-end: you can go from a Single Page Application (SPA) loading everything through Ajax or use any framework to render your data from the server synchronously.<\/p>\n<p>For SPAs, Angular has always appeared as an excellent choice because of its asynchronous nature, modularization via components, and the templating system which allows easy reuse of pieces of screens and logic. For the back-end, ASP.NET services have proven their value and effectiveness when it comes to speed, security, and even asynchronicity of the endpoints.<\/p>\n<p>In this article, you\u2019ll learn how to match both worlds in a concise and fully working application for the management of notes built on top of Angular in the front and an ASP.NET API in the back.<\/p>\n<h2>Setting Up<\/h2>\n<p>First, you\u2019ll need to have <a href=\"https:\/\/visualstudio.microsoft.com\">Visual Studio Community Edition<\/a> properly installed. Also, make sure to have installed the latest versions of .NET Core and ASP.NET Core frameworks as well. Then, select the option <em>File &#8211;&gt; New Project<\/em>, then <em>ASP.NET Core Web Application<\/em>. Fill in the blank spaces as shown in Figure 1.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-84095\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2019\/04\/word-image-190.png\" width=\"713\" height=\"494\" \/><\/p>\n<p class=\"caption\">Figure 1. Creating a new ASP.NET Core application project.<\/p>\n<p>Once you\u2019ve finished, click <em>OK<\/em>. You\u2019ll be requested to select the project template. Note here that you also have an option for an Angular template which you won\u2019t select since the focus is on learning how Angular works separately from the .NET project itself. It\u2019ll help you to understand both worlds working independently and see how a front-end application usually communicates with the back-end, specifically with Angular projects.<\/p>\n<p>Select the API option (Figure 2), which will create several files, including a ready-to-use API with the four main HTTP methods for CRUD operations: <code>GET<\/code>, <code>POST<\/code>, <code>PUT<\/code> and <code>DELETE<\/code>. That\u2019ll be useful for testing purposes.<\/p>\n<p>Remember not to select anything else: you won\u2019t use any authentication mechanism nor Docker support to keep this example simple.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-84096\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2019\/04\/word-image-191.png\" width=\"724\" height=\"509\" \/><\/p>\n<p class=\"caption\">Figure 2. Selecting the project template for ASP.NET Core application.<\/p>\n<p>Now, set up the configurations for the Angular side. Since you did not install the Angular template in the wizard process, you\u2019ll have to do that manually via command line. Before that, you need to install the latest version of Node.js and npm (Node package manager). It will be helpful to install and configure the proper packages directly from the official CDN sources.<\/p>\n<p>Navigate to the <a href=\"https:\/\/nodejs.org\/en\/download\/\">Node.js website<\/a> and download the proper installer for your OS. Pay attention to the version of your OS, whether it is 32-bit or 64-bit. Conclude the installation just like shown on the Node website instructions. Once you\u2019re done, check the version in your command line:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">node -v\nnpm -v<\/pre>\n<p>Great. Now, install <a href=\"https:\/\/cli.angular.io\/\">Angular CLI<\/a>. Angular CLI is a command line interface to scaffold apps for Angular based on its official packages, making the whole process of building an Angular app more productive and concise. For that, run the following command:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">npm install -g @angular\/cli<\/pre>\n<p>The <code>-g<\/code> flag will make sure to install it globally, that is, for everyone in your machine. Wait until it\u2019s finished and, then, run the second following command:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">ng new angular-simpletalk --skip-install<\/pre>\n<p><em>Note: If you don\u2019t have Git installed, a warning message could appear at the end of the command, but don\u2019t worry, it won\u2019t prevent the project from being created.<\/em><\/p>\n<p>Notice that the command <em>ng<\/em> will only be available once you\u2019ve installed the Angular CLI tool. It is the official command for Angular operations in the command line. The command <code>new<\/code>, in turn, is responsible for creating the whole structure of the project, initializing it and creating the necessary files (HTML, CSS, and JavaScript) with preset configs that\u2019ll be important during development. Figure 3 shows the questions the installer will ask you, such as if you\u2019d like to enable Angular routing to the application (which you\u2019ll say yes, since you\u2019ll need this to navigate through pages in the app), and which stylesheet format you\u2019d like to use (plain CSS, in case).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-84097\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2019\/04\/word-image-192.png\" width=\"791\" height=\"739\" \/><\/p>\n<p class=\"caption\">Figure 3. Creating a new Angular project via Angular CLI.<\/p>\n<p>This will generate a bunch of folders and files inside the <em>\/angular-simpletalk<\/em> directory. After it\u2019s finished, go to the Visual Studio project, spot these assets and move them to the root directory, the same as the ASP.NET Core files. This is because the files need to be placed at the same level as the ASP.NET project.<\/p>\n<p>Run these last commands to have the Angular HTTP dependency added as a dependency to the project:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">npm install @angular\/core@latest\nnpm install @angular\/http@latest\nnpm install<\/pre>\n<p>You\u2019ll need the HTTP package of Angular to make requests to the API.<\/p>\n<h2>Making the First Call to the API<\/h2>\n<p>To make HTTP requests in Angular, you first need to import the proper modules from the dependency packages imported earlier. Navigate to the <em>\/src\/app\/app.module.ts<\/em> file and modify it as follows:<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule } from '@angular\/core';\nimport { AppRoutingModule } from '.\/app-routing.module';\nimport { AppComponent } from '.\/app.component';\nimport { FormsModule } from '@angular\/forms';\nimport { HttpModule } from '@angular\/http';\n@NgModule({\n  declarations: [\n    AppComponent\n  ],\n  imports: [\n    BrowserModule,\n    AppRoutingModule,\n    FormsModule,\n    HttpModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }<\/pre>\n<p>Notice that you\u2019ve added two new imports: the HTTP and Forms modules. These are required because the application will not only send requests but also send them from web forms in later examples. The rest of the file remains the default.<\/p>\n<p>Next, comes the component (specifically the file <em>app.component.ts<\/em>) that is responsible for making the request call itself. Change its content to the following:<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { Component, OnInit } from '@angular\/core';\nimport { Http } from '@angular\/http'\n@Component({\n  selector: 'app-root',\n  templateUrl: '.\/app.component.html',\n  styleUrls: ['.\/app.component.css']\n})\nexport class AppComponent implements OnInit {\n  constructor(private _httpService: Http) { }\n  accessPointUrl: string = 'https:\/\/localhost:44324\/api\/values';\n  apiValues: string[] = [];\n  ngOnInit() {\n    this._httpService.get(this.accessPointUrl).subscribe(values =&gt; {\n      this.apiValues = values.json() as string[];\n    });\n  }\n}<\/pre>\n<p>Apart from the component imports Angular usually makes use of when it comes to this type of file, you also include the import of HTTP previously set. The constructor of this component receives the <code>httpService<\/code> as an injected parameter and calls the API inside the <code>ngOnInit<\/code> method, through the <code>get()<\/code>method. Note that the URL of the API is stored in a variable and passed to this method. The subscribe method, in turn, guarantees that the result will be stored asynchronously into the variable <code>apiValues<\/code>, once everything\u2019s done.<\/p>\n<p>Finally, adapt the <em>app.component.html<\/em> to read the retrieved data. Open it and change its contents to the following:<\/p>\n<pre class=\"lang:c# theme:vs2012\">&lt;!--The content below is only a placeholder and can be replaced.--&gt;\n&lt;div&gt;\n  &lt;h1&gt;Application says what?&lt;\/h1&gt;\n  &lt;ul&gt;\n    &lt;li *ngFor=\"let value of apiValues\"&gt;{{value}}&lt;\/li&gt;\n  &lt;\/ul&gt;\n&lt;\/div&gt;\n&lt;router-outlet&gt;&lt;\/router-outlet&gt;<\/pre>\n<p>An Angular directive inside of the <code>&lt;li&gt;<\/code> element iterates over the list of values the API returned and was stored into <code>apiValues<\/code> public variable. For now, you\u2019ll keep using the autogenerated API endpoints, that is, those which return hardcoded values just as a matter of testing.<\/p>\n<p>It happens that the application still won`t work because of a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/CORS\">CORS<\/a> problem. You must enable it to allow the Angular application to call an API hosted in a different address. For this, you`ll have to add the following content to the <code>ConfigureServices<\/code> method in <code>Startup<\/code> class:<\/p>\n<pre class=\"lang:c# theme:vs2012\">services.AddCors(options =&gt;\n      {\n        options.AddPolicy(\"CorsPolicy\",\n            builder =&gt; builder.AllowAnyOrigin()\n            .AllowAnyMethod()\n            .AllowAnyHeader()\n            .AllowCredentials());\n      });<\/pre>\n<p>As well as this one to the <em>Configure<\/em> method:<\/p>\n<pre class=\"lang:c# theme:vs2012\">app.UseCors(\"CorsPolicy\");<\/pre>\n<p>To run the application, make sure to first run the API application in the back-end. Then, in the command line, run the following command:<\/p>\n<pre class=\"lang:c# theme:vs2012\">ng serve<\/pre>\n<p>It\u2019ll both start your Angular application and watch for file changes. Access the address <a href=\"http:\/\/localhost:4200\/\">http:\/\/localhost:4200\/<\/a> with your browser and you\u2019ll see something like:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"455\" height=\"298\" class=\"wp-image-84098\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2019\/04\/word-image-193.png\" \/><\/p>\n<p class=\"caption\">Figure 4. Showing values from the API with Angular.<\/p>\n<h2>Creating a Notes App CRUD<\/h2>\n<p>Now, you\u2019ll create a complete application that manages notes from scratch. It\u2019s helpful for you to understand how CRUD operations work in Angular-based apps. Figure 5 shows how the app will look when it\u2019s complete:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-84099\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2019\/04\/word-image-194.png\" width=\"1037\" height=\"500\" \/><\/p>\n<p class=\"caption\">Figure 5. The final screen of the Angular app.<\/p>\n<p>Within the same application, create a new folder called <em>Models<\/em>. It\u2019ll host the POCOs (Plain Old C# Objects). Then create a new class naming it <em>Note.cs<\/em>. Add the following content to it:<\/p>\n<pre class=\"lang:c# theme:vs2012\">using System.ComponentModel.DataAnnotations;\nnamespace AngularFirstSteps.Models\n{\n  public class Note\n  {\n    public int Id { get; set; }\n    [Required]\n    public string Title { get; set; }\n    [Required]\n    public string Description { get; set; }\n  }\n}<\/pre>\n<p>It is made of simple attributes and getters and setters. Next, create a new controller class that will store the REST operations for each of the CRUD ones. Give it the name of<em> NotesController.cs<\/em> and add the following content:<\/p>\n<pre class=\"lang:c# theme:vs2012\">using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing AngularFirstSteps.Models;\nusing Microsoft.AspNetCore.Mvc;\nnamespace AngularFirstSteps.Controllers\n{\n  [Produces(\"application\/json\")]\n  [Route(\"api\/[controller]\")]\n  [ApiController]\n  public class NotesController : ControllerBase\n  {\n    private static List&lt;Note&gt; notes = new List&lt;Note&gt;();\n    private static int count = 0;\n    static NotesController()\n    {\n      Note note1 = new Note\n      {\n        Id = count++,\n        Title = \"30 min run\",\n        Description = \"It's important to your health\"\n      };\n      Note note2 = new Note\n      {\n        Id = count++,\n        Title = \"Call the plumber\",\n        Description = \"To fix the plumbing\"\n      };\n      notes.Add(note1);\n      notes.Add(note2);\n    }\n    \/\/ GET api\/notes\n    [HttpGet]\n    public IEnumerable&lt;Note&gt; Get()\n    {\n      return notes;\n    }\n    \/\/ GET api\/notes\/5\n    [HttpGet(\"{id}\")]\n    public async Task&lt;IActionResult&gt; Get(int id)\n    {\n      return Ok(notes.Where(note =&gt; note.Id == id).FirstOrDefault());\n    }\n    \/\/ POST api\/notes\n    [HttpPost]\n    public async Task&lt;IActionResult&gt; Post([FromBody] Note note)\n    {\n      note.Id = count++;\n      notes.Add(note);\n      return CreatedAtAction(\"Get\", new { id = note.Id }, note);\n    }\n    \/\/ PUT api\/notes\/5\n    [HttpPut(\"{id}\")]\n    public async Task&lt;IActionResult&gt; Put(int id, [FromBody] Note note)\n    {\n      Note found = notes.Where(n =&gt; n.Id == id).FirstOrDefault();\n      found.Title = note.Title;\n      found.Description = note.Description;\n      return NoContent();\n    }\n    \/\/ DELETE api\/notes\/5\n    [HttpDelete(\"{id}\")]\n    public async Task&lt;IActionResult&gt; Delete(int id)\n    {\n      notes.RemoveAll(n =&gt; n.Id == id);\n      return NoContent();\n    }\n  }\n}<\/pre>\n<p>It\u2019s basically the same thing as the previous Controller class, with the slight difference that each of our endpoints are now async, i.e., the client (Angular application) can make calls to the back-end REST endpoints and wait for them to respond asynchronously via callback functions.<\/p>\n<p>The connection to a database, or anything like that, will not be covered as not to lose the focus of the article. Here, the operations will be stored in a static list, which will simulate a database, at least while the ASP.NET application is up in the server.<\/p>\n<p>Now it\u2019s time to set up our new components. There are three components to this app:<\/p>\n<ol>\n<li><strong>app.component<\/strong>: it was already created within the application setup. It will call the next two templates;<\/li>\n<li><strong>notes-listing.component<\/strong>: it will handle the operations of listing in a table the notes were added;<\/li>\n<li><strong>add-update-notes.component<\/strong>: it will store the form and the other CRUD operation links.<\/li>\n<\/ol>\n<p>For that, run the following commands at the command line (inside the \u201c\\AngularFirstSteps\\angular-first-steps\\src\\app\u201d folder):<\/p>\n<pre class=\"lang:c# theme:vs2012\">ng generate component NotesListing \nng generate component AddUpdateNotes<\/pre>\n<p>Run, in sequence, another command for the creation of an Angular service; this one is responsible for the REST service orchestration:<\/p>\n<pre class=\"lang:c# theme:vs2012\">ng generate service NotesService<\/pre>\n<p>This will generate the following new folder structures:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"373\" height=\"505\" class=\"wp-image-84100\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2019\/04\/word-image-195.png\" \/><\/p>\n<p class=\"caption\">Figure 6. New components folders.<\/p>\n<p>The new components must be included in the <em>app.module.ts<\/em> file, which registers all the components, modules and new services of an Angular app. The final content of the file must be exactly as<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule } from '@angular\/core';\nimport { AppRoutingModule } from '.\/app-routing.module';\nimport { AppComponent } from '.\/app.component';\nimport { RouterModule, Routes } from '@angular\/router';\nimport { FormsModule } from '@angular\/forms';\nimport { HttpModule } from '@angular\/http';\nimport { HttpClientModule } from '@angular\/common\/http';\nimport { NotesListingComponent } from '.\/notes-listing\/notes-listing.component';\nimport { AddUpdateNotesComponent } from '.\/add-update-notes\/add-update-notes.component';\nimport { NotesService } from '.\/notes-service.service';\nconst appRoutes: Routes = [\n  { path: '', component: AppComponent }\n];\n@NgModule({\n  declarations: [\n    AppComponent,\n    NotesListingComponent,\n    AddUpdateNotesComponent\n  ],\n  imports: [\n    BrowserModule,\n    RouterModule.forRoot(appRoutes),\n    AppRoutingModule,\n    FormsModule,\n    HttpModule,\n    HttpClientModule\n  ],\n  providers: [NotesService],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }<\/pre>\n<p>Some basic actions:<\/p>\n<ul>\n<li>Add the proper imports of the needed modules, components and services at the beginning of the file. Here, the modules will be:\n<ul>\n<li><a href=\"https:\/\/angular.io\/guide\/router\">Routers<\/a>: enables navigation from one view to the next as users perform application tasks. We\u2019ll only use to state that the root address of the application will always redirect to our home view;<\/li>\n<li><a href=\"https:\/\/angular.io\/api\/forms\">Forms<\/a>: implements a set of directives and providers to communicate with native DOM elements when building forms to capture user input;<\/li>\n<li><a href=\"https:\/\/angular.io\/guide\/http\">Http<\/a>: offers a simplified client HTTP API for Angular applications that rests on the XMLHttpRequest interface exposed by browsers. We\u2019ll need to communicate with our REST endpoints;<\/li>\n<li><a href=\"https:\/\/angular.io\/api\/common\/http\">HttpClient<\/a>: implements an HTTP client API for Angular apps that relies on the XMLHttpRequest interface exposed by browsers;<\/li>\n<\/ul>\n<\/li>\n<li>Add the name of the components to each respective NgModule <em>declarations<\/em> tag; each of the imported modules to the <em>imports<\/em> tag, and the service to the <em>providers<\/em> one.<\/li>\n<\/ul>\n<p>All set to be used. Start by coding notes-service.service.ts, which will be responsible for calling the back-end API. That\u2019s its code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { Injectable } from '@angular\/core';\nimport { HttpClient, HttpHeaders } from '@angular\/common\/http';\n@Injectable()\nexport class NotesService {\n  private headers: HttpHeaders;\n  private url: string = 'https:\/\/localhost:44324\/api\/notes';\n  constructor(private http: HttpClient) {\n    this.headers = new HttpHeaders({ 'Content-Type': 'application\/json' });\n  }\n  public get() {\n    return this.http.get(this.url, { headers: this.headers });\n  }\n  public add(payload) {\n    return this.http.post(this.url, payload, { headers: this.headers });\n  }\n  public remove(payload) {\n    return this.http.delete(this.url + '\/' + payload.id, { headers: this.headers });\n  }\n  public update(payload) {\n    return this.http.put(this.url + '\/' + payload.id, payload, { headers: this.headers });\n  }\n}<\/pre>\n<p>Please, don\u2019t forget to pay attention to the right port your ASP.NET application was started with. Change it properly in the <code>accessPoint<\/code> variable. Nothing too exceptional here, just a function for each of the corresponding endpoints of the API receiving a payload and returning the same result our API returns. The pure logic will be spread out over the other components.<\/p>\n<p>Take a look at the <em>add-update-notes.component.ts<\/em> file:<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { Component, EventEmitter, Input, Output, OnInit } from '@angular\/core';\n@Component({\n  selector: 'app-add-update-notes',\n  templateUrl: '.\/add-update-notes.component.html',\n  styleUrls: ['.\/add-update-notes.component.css']\n})\nexport class AddUpdateNotesComponent implements OnInit {\n  @Output() noteCreated = new EventEmitter&lt;any&gt;();\n  @Input() note: any;\n  constructor() {\n    this.clearNotes();\n  }\n  ngOnInit() {\n  }\n  \/\/ Create an empty note object\n  private clearNotes = function () {\n    this.note = {\n      id: undefined,\n      title: '',\n      description: ''\n    };\n  };\n  public addUpdateNote = function(event) {\n    this.noteCreated.emit(this.note);\n    this.clearNotes();\n  };\n}<\/pre>\n<p>In Angular, a component can emit an event using <code>@Output<\/code> that\u2019ll be, in turn, attached to an <code>EventEmitter<\/code>. The same will happen to <code>@Input<\/code> for an Angular model object that has its attribute bindings mapped in the HTML page. Both must be imported from the <code>@angular\/core<\/code> default module.<\/p>\n<p>There are two functions: one for handling the cleanup stuff, that is, recreating the <em>note<\/em> object with default values, and another one for dealing with the event emitting when a note is created. Since the same button will be used for both operations of saving and updating, its function will be responsible for emitting the respective note object.<\/p>\n<p>The following is the HTML code for the respective <em>add-update-notes.component.html<\/em>:<\/p>\n<pre class=\"lang:c# theme:vs2012\">&lt;div&gt;\n  &lt;h2 *ngIf=\"!note || note.id === undefined\"&gt;Add note&lt;\/h2&gt;\n  &lt;h2 *ngIf=\"note &amp;&amp; note.id !== undefined\"&gt;Update note&lt;\/h2&gt;\n  &lt;form&gt;\n    &lt;div class=\"form-group\"&gt;\n      &lt;label for=\"title-input\"&gt;Title:&lt;\/label&gt;\n      &lt;input name=\"title\" type=\"text\" id=\"title\" [(ngModel)]=\"note.title\" class=\"form-control\" \/&gt;\n    &lt;\/div&gt;\n    &lt;div class=\"form-group\"&gt;\n      &lt;label for=\"desc-input\"&gt;Description:&lt;\/label&gt;\n      &lt;textarea name=\"description\" type=\"text\" id=\"desc-input\" [(ngModel)]=\"note.description\" class=\"form-control\" &gt;&lt;\/textarea&gt;\n    &lt;\/div&gt;\n    &lt;button type=\"button\" class=\"btn btn-primary\" (click)=\"addUpdateNote($event);\"&gt;Save&lt;\/button&gt;\n  &lt;\/form&gt;\n&lt;\/div&gt;<\/pre>\n<p>Here, it\u2019s just mapping the right <code>&lt;h2&gt;<\/code> title based on which type of operation you\u2019re doing. In other words, both register and update of a note will be handled by this page. The <code>ngModel<\/code> attribute maps each of the <em>note<\/em> object property that will receive the input value. The <code>(click)<\/code> attribute will map the corresponding function in the component js for receiving the event and pass it on.<\/p>\n<p>The next component covered is the <em>notes-listing.component.ts<\/em>:<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { Component, EventEmitter, Input, Output, OnInit } from '@angular\/core';\n@Component({\n  selector: 'app-notes-listing',\n  templateUrl: '.\/notes-listing.component.html',\n  styleUrls: ['.\/notes-listing.component.css']\n})\nexport class NotesListingComponent implements OnInit {\n  @Input() notes: Array&lt;any&gt;;\n  @Output() recordDeleted = new EventEmitter&lt;any&gt;();\n  @Output() newClicked = new EventEmitter&lt;any&gt;();\n  @Output() editClicked = new EventEmitter&lt;any&gt;();\n  public delete(data) {\n    this.recordDeleted.emit(data);\n  }\n  public edit(data) {\n    this.editClicked.emit(Object.assign({}, data));\n  }\n  public new() {\n    this.newClicked.emit();\n  }\n  ngOnInit() {\n  }\n}<\/pre>\n<p>For the notes listing, you\u2019ll need an input that is also an array. It\u2019ll receive its values from the service that, in turn, will catch them from the server endpoint. Each output event emitter will be attached to the corresponding function for editing, removing or creating a new (blank) note. Note that for the edit operation, you\u2019re passing a copy of the data, instead of the original, in order to evict it to be modified.<\/p>\n<p>That\u2019s the content of the <em>notes-listing.component.html<\/em>:<\/p>\n<pre class=\"lang:c# theme:vs2012\">&lt;table class=\"table mt-5\"&gt;\n  &lt;thead&gt;\n    &lt;tr&gt;\n      &lt;th scope=\"col\"&gt;Title&lt;\/th&gt;\n      &lt;th scope=\"col\"&gt;Description&lt;\/th&gt;\n      &lt;th scope=\"col\"&gt;Actions&lt;\/th&gt;\n    &lt;\/tr&gt;\n  &lt;\/thead&gt;\n  &lt;tbody&gt;\n    &lt;tr *ngIf=\"notes?.length == 0\"&gt;&lt;td&gt;No data&lt;\/td&gt;&lt;\/tr&gt;\n    &lt;tr *ngFor=\"let note of notes\"&gt;\n      &lt;td&gt;{{ note.title }}&lt;\/td&gt;\n      &lt;td&gt;{{ note.description }}&lt;\/td&gt;\n      &lt;td&gt;\n        &lt;a href=\"#\" class=\"m-1\" (click)=\"edit(note)\"&gt;Edit&lt;\/a&gt;\n        &lt;a href=\"#\" class=\"m-2\" (click)=\"delete(note)\"&gt;Delete&lt;\/a&gt;\n      &lt;\/td&gt;\n    &lt;\/tr&gt;\n  &lt;\/tbody&gt;\n&lt;\/table&gt;\n&lt;button type=\"button\" class=\"btn btn-primary mb-2\" (click)=\"new()\"&gt;New&lt;\/button&gt;<\/pre>\n<p>This HTML basically exposes the table that will store the list of notes. Note that it\u2019s using a <code>ngIf<\/code> directive to check if the list of notes is empty in order to show a proper message instead of the listing. Otherwise, the table will be iterated over the <code>notes<\/code> object as well as set each corresponding value to the columns. The rest of the code deals with the three links that\u2019ll call the edit, delete and new functions.<\/p>\n<p>Finally, analyze the code for the <em>app.component.ts<\/em>:<\/p>\n<pre class=\"lang:c# theme:vs2012\">import { Component, OnInit } from '@angular\/core';\nimport { NotesService } from '.\/notes-service.service';\nimport * as _ from 'lodash';\n@Component({\n  selector: 'app-root',\n  templateUrl: '.\/app.component.html',\n  styleUrls: ['.\/app.component.css']\n})\nexport class AppComponent implements OnInit {\n  public notes: Array&lt;any&gt;;\n  public currentNote: any;\n  constructor(private notesService: NotesService) {\n    notesService.get().subscribe((data: any) =&gt; this.notes = data);\n    this.currentNote = this.getDefaultNote();\n  }\n  private getDefaultNote() {\n    return {\n      id: undefined,\n      title: '',\n      description: ''\n    }\n  }\n  public createUpdateNote = function (note: any) {\n    let noteWithId = _.find(this.notes, (el =&gt; el.id === note.id));\n    if (noteWithId) {\n      const updateIndex = _.findIndex(this.notes, { id: noteWithId.id });\n      this.notesService.update(note).subscribe(\n        this.notes.splice(updateIndex, 1, note)\n      );\n    } else {\n      this.notesService.add(note).subscribe(\n        noteRecord =&gt; {\n          note.id = noteRecord.id;\n          this.notes.push(note)\n        }\n      );\n    }\n    this.currentNote = this.getDefaultNote();\n  };\n  public editNote = function(record: any) {\n    this.currentNote = record;\n  };\n  public newNote = function () {\n    this.currentNote = this.getDefaultNote();\n  };\n  public deleteNote(record) {\n    const deleteIndex = _.findIndex(this.notes, { id: record.id });\n    this.notesService.remove(record).subscribe(\n      result =&gt; this.notes.splice(deleteIndex, 1)\n    );\n  }\n  ngOnInit() {\n  }\n}<\/pre>\n<p>The first important thing about this code is that it\u2019s injecting the NotesService in the constructor of the component since it is when the component is initiated that it will retrieve all the notes from the API and store them in the <em>notes<\/em> array. The function <code>createUpdateNote()<\/code> is the engine to decide whether to call the <code>POST<\/code> or <code>PUT<\/code> in the API. It\u2019ll be called from the HTML page, specifically from the subcomponent tags. If the note id is passed in as an argument is into the current list of notes, it means it is an update. Otherwise, register a new one.<\/p>\n<p>Note that it\u2019s using an underscore <code>_<\/code> operator to perform the search in the array. This is because you\u2019ve imported <a href=\"https:\/\/lodash.com\/\">Lodash<\/a> at the beginning of the file. Lodash makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc.<\/p>\n<p>The rest of the functions will take care of placing the current note object to the <code>currentNote<\/code> variable or removing it from the <code>notes<\/code> array. Here is the content of the app.component.html file:<\/p>\n<pre class=\"lang:c# theme:vs2012\">&lt;section class=\"jumbotron\"&gt;\n  &lt;div class=\"container\"&gt;\n    &lt;div class=\"row\"&gt;\n      &lt;div class=\"col-md-12\"&gt;\n        &lt;app-add-update-notes (noteCreated)=\"createUpdateNote($event)\" [note]=\"currentNote\"&gt;&lt;\/app-add-update-notes&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=\"row\"&gt;\n      &lt;div class=\"col-md-12\"&gt;\n        &lt;app-notes-listing [notes]=\"notes\" (editClicked)=\"editNote($event)\" (newClicked)=\"newNote()\" (recordDeleted)=\"deleteNote($event)\"&gt;&lt;\/app-notes-listing&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/section&gt;<\/pre>\n<p>Here, the code is invoking the two components created for add\/update and listing of the notes. Note that they must have the exact same name as the ones put into the <code>selector<\/code> attribute of the <code>@Component<\/code> annotation. Pay attention, as well, to the bindings made from each subcomponent\u2019s functions to this component\u2019s functions.<\/p>\n<p>The reader may have noticed that a lot of CSS classes common to Bootstrap are used. This is because you\u2019re composing the views using it, and now you need to install its npm package via the following command:<\/p>\n<pre class=\"lang:c# theme:vs2012\">npm install bootstrap \u2013save<\/pre>\n<p>Then, go to the styles.css file and add the following content:<\/p>\n<pre class=\"lang:c# theme:vs2012\">@import '~bootstrap\/dist\/css\/bootstrap.min.css';<\/pre>\n<p>This will provide the style of Bootstrap to the HTML. That\u2019s it.<\/p>\n<p>In order to run the application, start your ASP.NET application and go to the command line and run:<\/p>\n<pre class=\"lang:c# theme:vs2012\">ng serve<\/pre>\n<p>Then, access the URL <a href=\"http:\/\/localhost:4200\/\">http:\/\/localhost:4200<\/a> and test your application.<\/p>\n<h2>Conclusion<\/h2>\n<p><a id=\"post-84094-_gjdgxs\"><\/a> You can access the source code for this project <a href=\"https:\/\/github.com\/iamjuliosampaio\/AngularFirstSteps\">here<\/a>. There\u2019s a lot more to explore on Angular, and the <a href=\"https:\/\/angular.io\">official docs<\/a> can help you. No matter what subject, ASP.NET will follow the path and give excellent solutions for API calls and more.<\/p>\n<p>Take your time to explore it and make your own changes. Add more fields, validations, and interactions to the screen. Have fun!<\/p>\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs: Building an Angular Application with ASP.NET Core<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. How do I make HTTP calls from Angular to an ASP.NET Core API?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Import HttpClientModule in your AppModule: import { HttpClientModule } from &#8216;@angular\/common\/http&#8217;; and add it to the imports array. Inject HttpClient in your service or component constructor: constructor(private http: HttpClient) {}. Make GET calls with this.http.get&lt;YourType[]&gt;(&#8216;https:\/\/localhost:5001\/api\/resource&#8217;).subscribe(data =&gt; this.items = data). Set up CORS in your ASP.NET Core API to allow requests from your Angular dev server origin (typically localhost:4200).<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. What is the difference between Angular and AngularJS for ASP.NET Core integration?<\/h3>\n            <div class=\"faq-answer\">\n                <p>AngularJS (Angular 1.x) is the original Google framework from 2010, using a different architecture (two-way data binding with $scope, controllers, ng-app). Angular (2 through current) is a complete rewrite released in 2016, built with TypeScript, components, and a modern RxJS-based architecture. For new ASP.NET Core projects, use Angular (2+) &#8211; the version covered in this article. AngularJS reached end-of-life in December 2021.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. How do I implement CRUD operations in an Angular app with ASP.NET Core?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Create an Angular service that wraps HttpClient calls for each CRUD operation: getAll() calls GET \/api\/items, create(item) calls POST \/api\/items with the item as JSON body, update(id, item) calls PUT \/api\/items\/{id}, and delete(id) calls DELETE \/api\/items\/{id}. In the corresponding ASP.NET Core controller, implement matching action methods returning IActionResult. Angular components inject the service and call the methods, binding results to template variables displayed with *ngFor.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">4. Should I use the ASP.NET Core Angular template or set up Angular manually?<\/h3>\n            <div class=\"faq-answer\">\n                <p>The dotnet new angular template (and the Visual Studio Angular template) scaffolds a combined solution with both projects and a proxy configured for development. This is faster for getting started. Setting up Angular separately with ng new gives you more control over Angular CLI version and project configuration, and keeps front-end and back-end concerns separated for teams that deploy them independently. The manual approach is demonstrated in this article.<\/p>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Build an Angular app backed by an ASP.NET Core API. Covers Angular project setup, HttpClient for REST calls, and a complete CRUD notes application with create, read, update, and delete operations via Angular components.&hellip;<\/p>\n","protected":false},"author":323407,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":true,"footnotes":""},"categories":[143538,146992,53],"tags":[95509],"coauthors":[93894],"class_list":["post-84094","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-angular","category-featured","tag-standardize"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/84094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/323407"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=84094"}],"version-history":[{"count":9,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/84094\/revisions"}],"predecessor-version":[{"id":109793,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/84094\/revisions\/109793"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=84094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=84094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=84094"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=84094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}