Build a SPA with ASP.NET Core 2.1, Stripe, and Angular 6

Build a SPA with ASP.NET Core 2.1, Stripe, and Angular 6

Buying things on the Internet has become a daily activity and is a feature many new projects require. In this tutorial, I will show you how to build an app to sell tickets using an Angular 6 single page app (SPA) using an ASP.NET Core 2.1 backend API...

Buying things on the Internet has become a daily activity and is a feature many new projects require. In this tutorial, I will show you how to build an app to sell tickets using an Angular 6 single page app (SPA) using an ASP.NET Core 2.1 backend API...

Upgrade to Angular 6

I love to use the latest and greatest when starting a new project. But when you use a project generator (like Angular-CLI, or the DotNetCLI), you may be at the mercy of the latest version the authors of those libraries have added. Right now, the DotNet CLI generates an Angular application with dotnet new angular gives you an Angular app at about version 4.5, which is about two versions behind the latest. Let me show you how to upgrade the templates and the generated application so that you’re using Angular 6, which is the latest as of the time of this article.

Update the DotNet command line tools with:

dotnet new --install Microsoft.DotNet.Web.Spa.ProjectTemplates::2.1.0

Then run:

dotnet new --install Microsoft.AspNetCore.SpaTemplates::2.1.0-preview1-final

Generate the ASP.NET Angular App

Now you can scaffold a new project:

dotnet new angular -o ticket-sales-example

Upgrade the Angular App To 6

The closest that gets you is Angular v5.2.0. To update Angular to v6.0.9 (as of this writing) switch to the ClientAppdirectory and run:

ng update --all

This will update the package.json file; then you need to run:

npm install

If you get a message about @angular/cli you can update it by running:

ng update @angular/cli

You may now see some vulnerabilities in your NPM packages. To fix them run:

npm audit fix

You may have to run this several times as some of the fixes introduce new vulnerabilities. I was only able to get my vulnerability list down to 6. I still have one low and five moderate vulnerabilities. If you want to get to zero vulnerabilities, you would have to hunt them each down and fix them manually.

Create a Stripe Account

One of the easiest ways to take payments on the web is to use Stripe. You can create a free developer account on Stripe’s registration page.

Once you’ve registered, make sure that you go to your dashboard and on the left-hand menu, click the toggle to ensure you are viewing test data. Then click on the Developers menu item and then click API Keys. Copy down the Publishable key to use in your Angular app.

Add Stripe to Your Angular 6 App

In your index.html file, add a script tag for Stripe’s JavaScript library, right below the app-root component.

<script type="text/javascript" src="https://js.stripe.com/v2/" />

Also add your publishable key to the Stripe object:

<script type="text/javascript">
  Stripe.setPublishableKey(&apos;{yourPublishableKey}&apos;);
</script>

Make sure that your publishable key starts with pk_test_. If it doesn’t, you’re using the production key, and you don’t want to do that yet.## Create the Stripe Ticket Registration Page

You can easily scaffold the base registration component with the Angular CLI. Go to a command line and change directories into the src/app directory. Then run the command:

ng generate component registration

The shorthand for the CLI is:

ng g c registration

The generate command will generate a folder called registration, and inside that a registration.compomnent.css, registration.component.html, a registration.component.spec.ts, and a registration.component.ts file. These are all the basic files for an Angular 6 component. I won’t be covering testing in this tutorial, so you can ignore or delete the registration.component.spec.ts file.

First, add some basic HTML to your registration.component.html file for displaying tickets. So the final file contents looks like this:

<h1>Register for SuperDuperConf</h1>

<div class="ticket conf-only">
  <span class="title">Conference Only Pass</span>
  <span class="price">$295</span>
  <button (click)="selectTicket(&apos;Conference Only&apos;, 295)">Register Now!</button>
</div>

<div class="ticket full">
  <span class="title">Full Conference + Workshop Pass</span>
  <span class="price">$395</span>
  <span class="value">Best Value!</span>
  <button (click)="selectTicket(&apos;Full Conference + Workshop&apos;, 395)">Register Now!</button>
</div>

<div class="ticket work-only">
  <span class="title">Workshop Only Pass</span>
  <span class="price"><h1>Register for SuperDuperConf</h1>

<div class="ticket conf-only">
  <span class="title">Conference Only Pass</span>
  <span class="price">$295</span>
  <button (click)="selectTicket(&apos;Conference Only&apos;, 295)">Register Now!</button>
</div>

<div class="ticket full">
  <span class="title">Full Conference + Workshop Pass</span>
  <span class="price">$395</span>
  <span class="value">Best Value!</span>
  <button (click)="selectTicket(&apos;Full Conference + Workshop&apos;, 395)">Register Now!</button>
</div>

<div class="ticket work-only">
  <span class="title">Workshop Only Pass</span>
  <span class="price">$195</span>
  <button (click)="selectTicket(&apos;Workshop Only&apos;, 195)">Register Now!</button>
</div>

<div class="alert alert-success" *ngIf="model.successMessage">{{successMessage}}</div>
<div class="alert alert-danger" *ngIf="model.errorMessage">{{errorMessage}}</div>

<div *ngIf="model.ticket.price">

  <form (submit)="purchaseTicket()" class="needs-validation" novalidate #regForm="ngForm">
    <div class="form-group">
      <label for="firstName">First Name:</label>
      <input type="text" class="form-control" name="firstName" id="firstName" [(ngModel)]="model.firstName" required #firstName="ngModel">
      <div [hidden]="firstName.valid || firstName.pristine" class="text-danger">First Name is required.</div>
    </div>

    <div class="form-group">
      <label for="lastName">Last Name:</label>
      <input type="text" class="form-control" name="lastName" id="lastName" [(ngModel)]="model.lastName" required #lastName="ngModel">
      <div [hidden]="lastName.valid || lastName.pristine" class="text-danger">Last Name is required.</div>
    </div>

    <div class="form-group">
      <label for="email">Email Address:</label>
      <input type="text" class="form-control" name="email" id="email" [(ngModel)]="model.emailAddress" required #email="ngModel">
      <div [hidden]="email.valid || email.pristine" class="text-danger">Email Address is required.</div>
    </div>

    <div class="form-group">
      <label for="password">Password:</label>
      <input type="password" class="form-control" name="password" id="password" [(ngModel)]="model.password" required #password="ngModel">
      <div [hidden]="password.valid || password.pristine" class="text-danger">Password is required.</div>
    </div>

    <div class="form-group">
      <label for="cardNumber">Card Number:</label>
      <input type="text" class="form-control" name="cardNumber" id="cardNumber" [(ngModel)]="model.card.number" required>
    </div>

    <div class="form-group form-inline">
      <label for="expiry">Expiry:</label>
      <br/>
      <input type="text" class="form-control mb-1 mr-sm-1" name="expiryMonth" id="expiryMonth" [(ngModel)]="model.card.exp_month"
        required> /
      <input type="text" class="form-control" name="expiryYear" id="expiryYear" [(ngModel)]="model.card.exp_year" required>
    </div>

    <div class="form-group">
      <label for="cvc">Security Code:</label>
      <input type="text" class="form-control" name="cvc" id="cvc" [(ngModel)]="model.card.cvc" required>
    </div>
    <button type="submit" class="btn btn-success" [disabled]="!regForm.form.valid">Pay ${{model.ticket.price / 100}}</button>
  </form>
</div>

95</span>
  <button (click)="selectTicket(&apos;Workshop Only&apos;, 195)">Register Now!</button>
</div>

<div class="alert alert-success" *ngIf="model.successMessage">{{successMessage}}</div>
<div class="alert alert-danger" *ngIf="model.errorMessage">{{errorMessage}}</div>

<div *ngIf="model.ticket.price">

  <form (submit)="purchaseTicket()" class="needs-validation" novalidate #regForm="ngForm">
    <div class="form-group">
      <label for="firstName">First Name:</label>
      <input type="text" class="form-control" name="firstName" id="firstName" [(ngModel)]="model.firstName" required #firstName="ngModel">
      <div [hidden]="firstName.valid || firstName.pristine" class="text-danger">First Name is required.</div>
    </div>

    <div class="form-group">
      <label for="lastName">Last Name:</label>
      <input type="text" class="form-control" name="lastName" id="lastName" [(ngModel)]="model.lastName" required #lastName="ngModel">
      <div [hidden]="lastName.valid || lastName.pristine" class="text-danger">Last Name is required.</div>
    </div>

    <div class="form-group">
      <label for="email">Email Address:</label>
      <input type="text" class="form-control" name="email" id="email" [(ngModel)]="model.emailAddress" required #email="ngModel">
      <div [hidden]="email.valid || email.pristine" class="text-danger">Email Address is required.</div>
    </div>

    <div class="form-group">
      <label for="password">Password:</label>
      <input type="password" class="form-control" name="password" id="password" [(ngModel)]="model.password" required #password="ngModel">
      <div [hidden]="password.valid || password.pristine" class="text-danger">Password is required.</div>
    </div>

    <div class="form-group">
      <label for="cardNumber">Card Number:</label>
      <input type="text" class="form-control" name="cardNumber" id="cardNumber" [(ngModel)]="model.card.number" required>
    </div>

    <div class="form-group form-inline">
      <label for="expiry">Expiry:</label>
      <br/>
      <input type="text" class="form-control mb-1 mr-sm-1" name="expiryMonth" id="expiryMonth" [(ngModel)]="model.card.exp_month"
        required> /
      <input type="text" class="form-control" name="expiryYear" id="expiryYear" [(ngModel)]="model.card.exp_year" required>
    </div>

    <div class="form-group">
      <label for="cvc">Security Code:</label>
      <input type="text" class="form-control" name="cvc" id="cvc" [(ngModel)]="model.card.cvc" required>
    </div>
    <button type="submit" class="btn btn-success" [disabled]="!regForm.form.valid">Pay ${{model.ticket.price / 100}}</button>
  </form>
</div>

I know it seems like a lot, but there is a lot of repetition here. The first section lists three tickets that a user can buy to register for the “SuperDuperConf”. The second section is just a form that collects the information needed to register an attendee for the conference.

The important thing to take note of here is the [(ngModel)]="model.some.thing" lines of code. That weird sequence of characters around ngModel is just parentheses inside of square brackets. The parentheses tell Angular that there is an action associated with this field. You see this a lot for click event handlers. It usually looks something like (click)="someEventHandler()". It is the same, in that the ngModel is the handler of the event when the model changes.

The square brackets are used for updating the DOM when something on the model changes. It is usually seen in something like disabling a button as you did above with [disabled]="!regForm.form.valid". It watches the value on the form, and when it is not valid, the button is disabled. Once the form values become valid, the disabled property is removed from the DOM element.

Now that you have all the fields on the page, you will want to style that ticket section up a bit so that it looks like tickets.

.ticket {
  text-align: center;
  display: inline-block;
  width: 31%;
  border-radius: 1rem;
  color: #fff;
  padding: 1rem;
  margin: 1rem;
}

.ticket.conf-only,
.ticket.work-only {
  background-color: #333;
}

.ticket.full {
  background-color: #060;
}

.ticket span {
  display: block;
}

.ticket .title {
  font-size: 2rem;
}

.ticket .price {
  font-size: 2.5rem;
}

.ticket .value {
  font-style: italic;
}

.ticket button {
  border-radius: 0.5rem;
  text-align: center;
  font-weight: bold;
  color: #333;
  margin: 1rem;
}

These are just three basic ticket types I regularly see for conference registrations.

Now the meat of the registration page, the TypeScript component. You will need a few things to make the page work. You will need a model to store the values that the user enters, a way for the user to select a ticket, and a way for the user to pay for the ticket they have selected.

import { Component, ChangeDetectorRef, Inject } from &apos;@angular/core&apos;;
import { HttpClient } from &apos;@angular/common/http&apos;;

@Component({
  selector: &apos;app-registration&apos;,
  templateUrl: &apos;./registration.component.html&apos;,
  styleUrls: [&apos;./registration.component.css&apos;]
})
export class RegistrationComponent {
  public model: any;
  public card: any;

  public errorMessage: string;
  public successMessage: string;

  constructor(
    private http: HttpClient,
    private changeDetector: ChangeDetectorRef,
    @Inject(&apos;BASE_URL&apos;) private baseUrl: string
  ) {
    this.resetModel();
    this.successMessage = this.errorMessage = null;
  }

  resetModel(): any {
    this.model = {
      firstName: &apos;&apos;,
      lastName: &apos;&apos;,
      emailAddress: &apos;&apos;,
      password: &apos;&apos;,
      token: &apos;&apos;,
      ticket: { ticketType: &apos;&apos;, price: 0 }
    };
    this.card = { number: &apos;&apos;, exp_month: &apos;&apos;, exp_year: &apos;&apos;, cvc: &apos;&apos; };
  }

  selectTicket(ticketType: string, price: number) {
    this.model.ticket = { ticketType, price: price * 100 };
  }

  purchaseTicket() {
    (<any>window).Stripe.card.createToken(
      this.card,
      (status: number, response: any) => {
        if (status === 200) {
          this.model.token = response.id;
          this.http
            .post(this.baseUrl + &apos;api/registration&apos;, this.model)
            .subscribe(
              result => {
                this.resetModel();
                this.successMessage = &apos;Thank you for purchasing a ticket!&apos;;
                console.log(this.successMessage);
                this.changeDetector.detectChanges();
              },
              error => {
                this.errorMessage = &apos;There was a problem registering you.&apos;;
                console.error(error);
              }
            );
        } else {
          this.errorMessage = &apos;There was a problem purchasing the ticket.&apos;;
          console.error(response.error.message);
        }
      }
    );
  }
}

Even if you’re familiar with Angular, some of this may look foreign. For instance, the BASE_URL value that is getting injected into the component. It comes from the main.ts file that the Angular CLI generated. If you look at that file, right below the imports, there is a function called getBaseUrl() and below that is a providers section that provides the value from the getBaseUrl() function, which is just a simple way to inject constant values into components.

The other thing that might look strange is the purchaseTicket() function. If you’ve never used Stripe before, the createToken() method creates a single-use token that you can pass to your server to use in your server-side calls, that way you don’t have to send credit card information to your server, and you can let Stripe handle the security of taking online payments!

Add the ASP.NET Registration Controller

Now that your Angular app can get a token from Stripe, you’ll want to send that token and the user’s information to the server to charge their card for the ticket. Create a controller in the Controllers folder in the server-side application root. The contents of the file should be:

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Okta.Sdk;
using Stripe;
using ticket_sales_example.Models;

namespace ticket_sales_example.Controllers
{
  [Produces("application/json")]
  [Route("api/[controller]")]
  public class RegistrationController : ControllerBase
  {
    [HttpPost]
    public async Task<ActionResult<Registration>> CreateAsync([FromBody] Registration registration)
    {
      ChargeCard(registration);
      var oktaUser = await RegisterUserAsync(registration);
      registration.UserId = oktaUser.Id;
      return Ok(registration);
    }

    private async Task<User> RegisterUserAsync(Registration registration)
    {
      var client = new OktaClient();
      var user = await client.Users.CreateUserAsync(
        new CreateUserWithPasswordOptions
        {
          Profile = new UserProfile
          {
            FirstName = registration.FirstName,
            LastName = registration.LastName,
            Email = registration.EmailAddress,
            Login = registration.EmailAddress,
          },
          Password = registration.Password,
          Activate = true
        }
      );

      var groupName = "";
      if (registration.Ticket.TicketType == "Full Conference + Workshop")
      {
        groupName = "FullAttendees";
      }
      if (registration.Ticket.TicketType == "Conference Only")
      {
        groupName = "ConferenceOnlyAttendees";
      }
      if (registration.Ticket.TicketType == "Workshop Only")
      {
        groupName = "WorkshopOnlyAttendees";
      }

      var group = await client.Groups.FirstOrDefault(g => g.Profile.Name == groupName);
      if (group != null && user != null)
      {
        await client.Groups.AddUserToGroupAsync(group.Id, user.Id);
      }



      return user as User;
    }

    private StripeCharge ChargeCard(Registration registration)
    {
      StripeConfiguration.SetApiKey("sk_test_uukFqjqsYGxoHaRTOS6R7nFI");

      var options = new StripeChargeCreateOptions
      {
        Amount = registration.Ticket.Price,
        Currency = "usd",
        Description = registration.Ticket.TicketType,
        SourceTokenOrExistingSourceId = registration.Token,
        StatementDescriptor = "SuperDuperConf Ticket"
      };

      var service = new StripeChargeService();
      return service.Create(options);
    }
  }
}

It seems like there is a bit here, but there is only the HttpPost method CreateAsync() that is the API endpoint for a POST to /api/registration. The other methods are helpers to the endpoint.

The ChargeCard() method does just as the name implies, it charges the user’s credit card using the token that the Angular app got from Stripe and sent to the API. Even though I am setting the Stripe API key with a simple string here for demonstration purposes, you might want to store the key in an environment variable, in a configuration file that doesn’t get checked into source control, or in a key management service like Azure’s Key Vault. This will mitigate the chances that you will accidentally check the test key into your source control and have that end up being deployed to production!

The RegisterUserAsync() method handles registering a user with Okta and putting them into a group that corresponds to the ticket that the user is purchasing. This is done in two steps: by creating the user, then finding the group that corresponds with the ticket purchased, and adding that group’s ID to the newly created Okta user.

Set Up Okta for Your Angular and ASP.NET Core Applications

Dealing with user authentication in web apps is a massive pain for every developer. This is where Okta shines: it helps you secure your web applications with minimal effort.

Why Okta?

At Okta, our goal is to make identity management a lot easier, more secure, and more scalable than what you’re used to. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

To get started, you’ll need to create an OpenID Connect application in Okta. Sign up for a forever-free developer account (or log in if you already have one).

Once you’ve logged in and landed on the dashboard page, copy down the Org URL pictured below. You will need this later.

Then create a new application by browsing to the Applications tab and clicking Add Application, and from the first page of the wizard choose Single-Page App.

On the settings page, enter the following values:

You can leave the other values unchanged, and click Done.

Now that your application has been created copy down the Client ID and Client secret values on the following page, you’ll need them soon.

Finally, create a new authentication token. This will allow your app to talk to Okta to retrieve user information, among other things. To do this, click the API tab at the top of the page followed by the Create Token button. Give your token a name, in this case, “Crud API” would be a good name, then click Create Token. Copy down this token value as you will need it soon.

Even though you have a method for registering users, you’ll need to create the groups for the tickets, set up your API to use Okta, and configure it to receive access tokens from users of the Angular app for authorization.

Start by creating a group for each of the three tickets you’ll be selling. From the Okta dashboard hover over the Usersmenu item until the drop-down appears and choose Groups. From the Groups page, click the Add Group button.

In the Add Group modal that pops up, add a group for each ticket type.

Now, you’ll need to add these newly created groups to the ticket sales application. Click on the Applications menu item, and choose the TicketSalesApp from the list of apps. It should open on the Assignments tab. Click on the Assign button and choose Assign to Groups from the button’s drop-down menu. From here, assign each group you just created to the Ticket Sales app.

Add Groups to the ID Token

Now you just need to add these groups to the token.

  • Hover over the API menu item and select Authorization Servers.
  • Select the default authorization server (it was created for you when you created your Okta account).
  • Choose the Claims tab, and click Add Claim.
  • The name of the claim will be “groups”, Select ID Token and Always from the Include in token type setting.
  • Choose Groups from the Value Type setting, and Regex from the Filter setting.
  • In the text box type .*.
  • Finally, make sure the Disable claim checkbox is unchecked and that the Any scope radio button is selected in the Include in setting.

Add Okta to Your Angular Application

To set up your Angular application to use Okta for authentication, you’ll need to install the Angular SDK and the rxjscompatibility package.

npm install @okta/okta-angular [email protected] --save

Add the components to your app.module.ts file in src/app by first importing them:

import {
  OktaCallbackComponent,
  OktaAuthModule,
  OktaAuthGuard
} from &apos;@okta/okta-angular&apos;;

Now add a configuration variable right below the import statements:

const config = {
  issuer: &apos;https://{yourOktaDomain}/oauth2/default&apos;,
  redirectUri: &apos;http://localhost:5000/implicit/callback&apos;,
  clientId: &apos;{clientId}&apos;
};

Add the callback route to the routes in the imports section of the @NgModule declaration:

{ path: &apos;implicit/callback&apos;, component: OktaCallbackComponent }

That’s all for now in the Angular application. Now let’s get the ASP.NET Core app set up.

Add Okta to Your ASP.NET Core API

Now you need to let the API know two things: how to get the user’s identity from an access token (when one is sent) and how to call Okta for user management.

Start by adding the Okta Nuget package:

dotnet add package Okta.Sdk

For the ASP.NET Core application, the best thing to do is set up a file in your home folder to store the configuration. Okta’s SDK will pick the settings up for you, and you’ll never accidentally check them into source control!

In your home directory, create a .okta folder and add a file called okta.yaml. Your home folder will depend on your operating system. For *nix variants like Linux or macOS it is:

~/.okta/okta.yaml

for Windows environments it is:

%userprofile%\.okta\okta.yaml

YAML is just a file format for configuration. The okta.yaml file looks like:

okta:
  client:
    orgUrl: "https://{yourOktaDomain}"
    token: "{yourApiToken}"

In the ConfigureServices() method before the services.AddMvc() line, add:

services.AddAuthentication(sharedOptions =>
{
  sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
  options.Authority = "https://{yourOktaDomain}/oauth2/default";
  options.Audience = "api://default";
});

And in the Configure() method before the app.UseMvc() line add:

app.UseAuthentication();

That’s it! Now your ASP.NET Core app will take that bearer token, get the user’s information from Okta add them to the User object so you can get the currently requesting user’s data. It will also use the API token stored in the okta.yaml file when registering users.

Show the Tickets in Your Angular App

Now that users can purchase a ticket, you’ll want them to be able to log in and see their purchased ticket. To do this, generate a profile component using Angular’s CLI. From the src/app folder of the client app, run:

ng g c profile

Again, this is just shorthand for ng generate component profile, which will generate all the base files for the profile component. The profile.component.ts file should have the following contents:

import { Component, OnInit } from &apos;@angular/core&apos;;
import { OktaAuthService } from &apos;@okta/okta-angular&apos;;
import &apos;rxjs/Rx&apos;;

@Component({
  selector: &apos;app-profile&apos;,
  templateUrl: &apos;./profile.component.html&apos;,
  styleUrls: [&apos;./profile.component.css&apos;]
})
export class ProfileComponent implements OnInit {
  user: any;
  ticket: string;

  constructor(private oktaAuth: OktaAuthService) {}

  async ngOnInit() {
    this.user = await this.oktaAuth.getUser();
    if (this.user.groups.includes(&apos;FullAttendees&apos;)) {
      this.ticket = &apos;Full Conference + Workshop&apos;;
    } else if (this.user.groups.includes(&apos;ConferenceOnlyAttendees&apos;)) {
      this.ticket = &apos;Conference Only&apos;;
    } else if (this.user.groups.includes(&apos;WorkshopOnlyAttendees&apos;)) {
      this.ticket = &apos;Workshop Only&apos;;
    } else {
      this.ticket = &apos;None&apos;;
    }
  }
}

This does two things: it gets the currently logged in user and translates the group name into a displayable string representation of the ticket type purchased. The profile.component.html file is straightforward:

<h1>{{user.name}}</h1>

<p>
  Your Puchased Ticket: {{ticket}}
</p>

The last thing to do is to add a protected route to the profile page in the app.module.ts. I added mine right above the callback route:

{
  path: &apos;profile&apos;,
  component: ProfileComponent,
  canActivate: [OktaAuthGuard]
},

You can now sell tickets, and the users can log in and see which ticket they have once they’ve purchased one. You’re ready to hold your event!

angular asp.net

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Hire ASP.Net Developers

Looking to outsource your asp dot net development requirement? ASP.Net is a special feature of the DOT Net framework created by Microsoft. At [HourlyDeveloper.io](https://hourlydeveloper.io/ "HourlyDeveloper.io"), we have a team of experienced...

Angular 9 CRUD with ASP.NET Core Web API

Implement CRUD Operations in Angular with ASP.NET Core Web API. To demonstrate this topic we've build a project form scratch.In this article, we’ll implement Asp.Net Core 3.0 Web API CRUD Operations with Angular 9. To demonstrate the topic, we’ll build a project from scratch with payment details like Credit/ Debit Card.

Routing in MVC - ASP.NET Core Demystified

ASP.NET Core MVC has introduced quite a few concepts that new (or new-to-ASP.NET) web developers might have some difficulty getting caught up with. My ASP.NET Core Demystified series is designed to help these developers get started building their own custom, full-fledged, working AASP.NET Core applications. In

What is the ASP.Net Machine Account on my Computer?

Some users have reported the existence of the ASP.Net machine account. In this article, I will discuss what is asp.net machine account in windows 10/7 and how to disable it, asp.net machine account password, and can I delete asp.net machine account? .NET Framework is an application on Windows that requires the installation to run several apps or games. However, when the .NET Framework is downloaded and installed, the application automatically creates an ASP NET machine account.

Angular and ASP.NET Core

​ The&nbsp;[Angular CLI](https://cli.angular.io/ "Angular CLI")&nbsp;provides a way to develop front-end applications using angular that hides a lot of details. For example there's no requirement to understand how&nbsp;[Webpack](https://webpack.js.org/ "Webpack")&nbsp;or&nbsp;[SystemJS](https://github.com/systemjs/systemjs "SystemJS")&nbsp;work. ​ In fact, if you don't know a little bit about Webpack, which is what is used to build the latest version of Angular applications, the CLI almost looks like magic. You just need to do a&nbsp;ng new&nbsp;and&nbsp;ng serve --open&nbsp;and you have a working Angular application open in your web browser. ​ The fact that the CLI hides all the plumbing might lead to questions like: "How do I use Angular with ASP.NET Core?". ​ ![](https://res.cloudinary.com/practicaldev/image/fetch/s--dKBafg3O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.blinkingcaret.com/wp-content/uploads/2018/01/asp_net_core_and_angular_logo.png) ​ I hope that by the end of this blog post it will be clear to you how you can answer that question (and not only with ASP.NET Core, with whichever technology you want to use your Angular app with). ​ You see, an angular app is an app in and of itself, it does need to be "served" somehow by a web server. ​ When you compile an angular application you are producing a set of JavaScript, CSS and one index.html file. That's it. ​ The default folder where those "artifacts" get copied to is&nbsp;yourApplicationFolder/dist. You can check it out by going to your Angular application and doing an&nbsp;ng build. ​ Go on, I'll wait. ​ When you do&nbsp;ng serve --open&nbsp;you are actually using a stand-alone web server ([webpack-dev-server](https://github.com/webpack/webpack-dev-server "webpack-dev-server")) to serve that index.html file in the dist folder. ​ The rest of this blog post will describe several approaches that you can take for using Angular with ASP.NET Core. The first is to have ASP.NET Core serve the Angular files. ​ The second approach is to have Angular and ASP.NET Core as different applications. There's an example of how to achieve this using Nginx where both Angular and ASP.NET Core are served using port 80 and in IIS where each application is served from its own port. ​ The final part of the post describes a setup that I consider ideal where you can use Angular's&nbsp;ng serve&nbsp;during development. ​ This post is quite long but the sections are fairly independent. If your are only interested in the last section and you are using Windows I recommend also reading the section on how to configure Angular in IIS. ## Using ASP.NET Core to serve the Angular application ​ It can be argued that serving an Angular application "within" ASP.NET Core is wasteful in terms of resources. In the end the Angular application is just a set of static files, there's no need to have the request for those files go through the ASP.NET Core middleware pipeline. ​ There might be some good reasons for doing it though, also there's no harm in knowing how to do it and since it seems to be a common approach, being familiar with it might be useful. ​ One important thing to know in order to understand how we can serve an ASP.NET Core and Angular application together is to understand how a request is processed in ASP.NET Core. ​ When you run an ASP.NET Core application your request goes through a "pipeline" of&nbsp;[middlewares](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware?tabs=aspnetcore2x "middlewares"). Every time a request comes in it goes through the middlewares in the order they are defined, and then in reverse order. ​ Every middleware has an opportunity to change the request or response two times, once before the other middlewares have been executed, and then after the other middlewares have executed. This allows for a middleware at the top of the pipeline to handle for example, a 401 response set by a middleware further down in the pipeline. ​ An example of this are the authentication middlewares that change a 401 response to a 302 redirect to a login page. The Angular CLI provides a way to develop front-end applications using angular that hides a lot of details. For example there’s no requirement to understand how Webpack or SystemJS work.