Build a Basic Website with ASP.NET MVC and Angular

Build a Basic Website with ASP.NET MVC and Angular

Build a Basic Website with ASP.NET MVC and Angular. Get Started with ASP.NET MVC. Create an Angular Project. Set up a Database for ASP.NET. Add Authentication to Your Angular Application. Set Up Your ASP.NET API Endpoints. Set a Default Formatter for ASP.NET Web API 2.

Build a Basic Website with ASP.NET MVC and Angular. Get Started with ASP.NET MVC. Create an Angular Project. Set up a Database for ASP.NET. Add Authentication to Your Angular Application. Set Up Your ASP.NET API Endpoints. Set a Default Formatter for ASP.NET Web API 2.

ASP.NET has been around for a long time. When Microsoft introduced ASP.NET MVC, it changed the way many developers approach their codebase. There is an excellent separation of concerns, a TDD friendly framework, and easy integration with JavaScript while maintaining full control over rendered HTML. On the client side, a lot of .NET developers prefer Angular because it comes with TypeScript and it’s a much closer language to C# than plain JavaScript. Angular is an excellent framework for building enterprise-level, feature rich, applications.

You will be using .NET Framework 4.7.1, and you should have the latest version of Visual Studio 2017 installed. Also, you should have Node and npm installed since you will use Angular tools that require Node and npm.

Get Started with ASP.NET MVC

Create an API using a built-in template within Visual Studio. You’ll start from a scratch.

In Visual Studio, select File -> New Project

Select Web, ASP.NET Web Application (.NET Framework)

On the following screen select MVC:

You should have a new ASP.NET MVC application ready now, with all the folders and files as shown in the following picture:

At this moment, in your project, you have some NuGet packages you won’t be using. You can get rid of them quite quickly. Run the following commands inside of your Package Manager Console

Uninstall-Package Microsoft.ApplicationInsights.Web
Uninstall-Package Microsoft.ApplicationInsights.WindowsServer
Uninstall-Package Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel
Uninstall-Package Microsoft.ApplicationInsights.PerfCounterCollector
Uninstall-Package Microsoft.ApplicationInsights.DependencyCollector
Uninstall-Package Microsoft.ApplicationInsights.Agent.Intercept
Uninstall-Package Microsoft.ApplicationInsights


Additionally, make sure you delete ApplicationInsights.config file.

After finishing, you should have a clean project and perfect starting ground.

Create an Angular Project

Using Angular CLI is the best way to get started with Angular applications. With Angular CLI tools, you can easily create new projects, update existing projects, add different components to your codebase, and do all of that by entering a few commands in your terminal. You can also run the application in the development environment and publish it to production environments. It saves you the trouble of setting up configuration and Webpack. It can also do all the optimizing, compressing and minifying for you. It’s highly recommended to use Angular CLI to prepare your applications for production environments.

You can install the Angular CLI by entering the following in your favorite terminal:

npm install -g @angular/[email protected]


After that, navigate to the folder of your MVC project and open your terminal there and enter the following:

ng new Angular --skip-tests --style=scss


This will create a new Angular project under Angular folder within your MVC project. The --skip-tests argument will make sure that CLI skips creating spec files.

You should include the Angular folder in your MVC project. To do that, click on the Show All Files button in your Solution Explorer. You can now navigate to Angular folder and include all folders and files except for node_modules. After you do that you should have a folder structure like on the following picture:

Set up a Database for ASP.NET

You will use Entity Framework (EF) 6 as your Object-Relational Mapper (ORM), a proven solution from Microsoft. EF 6 is pretty easy to set up and get going, and you don’t need to know any SQL to have it working for your applications. Think of it as an adapter or bridge to your database. All of your database queries will go through Entity Framework.

The central point is your DbContext class, and that’s where you define your connection string and the tables for your database. EF 6 uses the DbSet collection type to represent a table in a database. All you need to do is create a connection string, create a new class that inherits from DbContext, make the data models and create appropriate properties within DbContext for those models. Those properties will represent tables in the database. From that point, it’s pretty easy to get and update existing data by using Language Integrated Queries (LINQ).

You should first install the EF 6, by running the following code in the Package Manager Console:

Install-Package EntityFramework -Version 6.2.0


Add the Connection String

You can get started by adding a connection string to your Web.config file. Make sure to add it inside of the section, and after :

<connectionStrings>
  <add name="OktaConnectionString"
    connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=JoggingTracker;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\WeightTracker.mdf"
    providerName="System.Data.SqlClient"
  />
</connectionStrings>


Create Your DbContext and Data Models in Angular

First, create a model for a recording a jog. Create a file in the Models directory called JoggingRecord.cs:

using System;

namespace OktaAspNetMvcAngular.Models
{
  public class JoggingRecord
  {
    public int Id { get; set; }

    public float Distance { get; set; }

    public string Description { get; set; }

    public DateTime CreatedAt { get; set; }
  }
}


Nothing special here, a standard Id property that represents a unique identifier for every row within a table and Entity Framework will use a naming convention and automatically set it as a primary key for this table. You definitely need the Distance property to track your jogs, a Description to describe the jog and CreatedAt property for an audit trail.

Next, create an ApplicationDbContext class inside of a new folder called Data. For now, it will be pretty straightforward:

using System.Data.Entity;
using OktaAspNetMvcAngular.Models;

namespace OktaAspNetMvcAngular.Data
{
  public class ApplicationDbContext : DbContext
  {
    public ApplicationDbContext() : base("OktaConnectionString")
    {
    }

    public static ApplicationDbContext Create() => new ApplicationDbContext();

    public DbSet<JoggingRecord> JoggingRecords { get; set; }
  }
}


The piece of code that calls the base DbContext class is used to set up the connection string. There is the DbSet property that I previously mentioned, and it will be used to fetch records from the table, update and delete those records.

Enable and Run Migrations in Your ASP.NET Project

Open the Package Manager Console, and run the following to enable migrations:

Enable-Migrations


Now you can add your initial migration, which will contain the creation of the JoggingRecords table:

Add-Migration Initial


Now, you can update the database:

Update-Database -Verbose


The verbose flag will allow you to see the generated SQL statements, and this can help you in resolving errors if any occur.

Seed the Database

After you have updated the database, add Migrations by adding code inside of the Seed method in the Configuration class.

First, add the using for the Models namespace:

using OktaAspNetMvcAngular.Models;


After that, add the following code for the Seed method:

protected override void Seed(OktaAspNetMvcAngular.Data.ApplicationDbContext context)
{
  context.JoggingRecords.AddOrUpdate(x => x.Id,
    new JoggingRecord { Id = 1, Description = "Friday Evening", Distance = 5.5f, CreatedAt = new DateTime(2018, 5, 1) },
    new JoggingRecord { Id = 2, Description = "Saturday morning", Distance = 6.15f, CreatedAt = new DateTime(2018, 4, 4) },
    new JoggingRecord { Id = 3, Description = "Marathon", Distance = 20, CreatedAt = new DateTime(2018, 5, 13) },
    new JoggingRecord { Id = 4, Description = "Short one", Distance = 3.5f, CreatedAt = new DateTime(2018, 6, 6) }
  );

  //  This method will be called after migrating to the latest version.

  //  You can use the DbSet<T>.AddOrUpdate() helper extension method
  //  to avoid creating duplicate seed data.
}


Add Authentication to Your Angular Application

Handling the authentication is never an easy or comfortable task. If you want to quickly and easily take care of authentication for your application you’re likely in the market for a solution like Okta. That’s why so many developers love and use Okta, they never want to build auth again and are happy to leave it to us.

To get started with Okta, sign up for a forever-free developer account or (log in if you already have one).

You should see the Dashboard and in the upper right corner, there should be your unique Org URL. Save it for later.

Now you need to 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 OktaMvcAngular as your name value and select Implicit(Hybrid).

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 (of course, yours will be different).

It is quite easy to add authentication to ASP.NET MVC with help of Okta.

Add the following to your Web.config file, inside of :

<!-- 1\. Replace these values with your Okta configuration -->
<add key="okta:ClientId" value="{yourClientId}" />
<add key="okta:ClientSecret" value="{yourClientSecret}" />
<add key="okta:OrgUri" value="https://{yourOktaDomain}/oauth2/default" />

<!-- 2\. Update the Okta application with these values -->
<add key="okta:RedirectUri" value="http://localhost:8080/authorization-code/callback" />
<add key="okta:PostLogoutRedirectUri" value="http://localhost:8080/Account/PostLogout" />


Install the required NuGet packages:

Install-Package Okta.AspNet -Version 1.1.1 
Install-Package Microsoft.Owin.Host.SystemWeb -Version 4.0.0
Install-Package Microsoft.Owin.Security.Cookies -Version 4.0.0


Add the Startup class. Right click on the project -> Add new item -> OWIN Startup Class:

Replace the content of that file with the following code:

using IdentityModel.Client;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Security.Claims;
using System.Threading.Tasks;

[assembly: OwinStartup(typeof(OktaAspNetMvcAngular.Startup))]

namespace OktaAspNetMvcAngular
{
  public class Startup
  {
    // These values are stored in Web.config. Make sure you update them!
    private readonly string clientId = ConfigurationManager.AppSettings["okta:ClientId"];
    private readonly string redirectUri = ConfigurationManager.AppSettings["okta:RedirectUri"];
    private readonly string authority = ConfigurationManager.AppSettings["okta:OrgUri"];
    private readonly string clientSecret = ConfigurationManager.AppSettings["okta:ClientSecret"];
    private readonly string postLogoutRedirectUri = ConfigurationManager.AppSettings["okta:PostLogoutRedirectUri"];

    public void Configuration(IAppBuilder app)
    {
      // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
      app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
      app.UseCookieAuthentication(new CookieAuthenticationOptions());
      app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
      {
        ClientId = clientId,
        ClientSecret = clientSecret,
        Authority = authority,
        RedirectUri = redirectUri,
        ResponseType = OpenIdConnectResponseType.CodeIdToken,
        Scope = OpenIdConnectScope.OpenIdProfile,
        PostLogoutRedirectUri = postLogoutRedirectUri,
        TokenValidationParameters = new TokenValidationParameters
        {
          NameClaimType = "name"
        },

        Notifications = new OpenIdConnectAuthenticationNotifications
        {
          AuthorizationCodeReceived = async n =>
          {
            // Exchange code for access and ID tokens
            var tokenClient = new TokenClient(authority + "/v1/token", clientId, clientSecret);
            var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, redirectUri);

            if (tokenResponse.IsError)
            {
              throw new Exception(tokenResponse.Error);
            }

            var userInfoClient = new UserInfoClient(authority + "/v1/userinfo");
            var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
            var claims = new List<Claim>();
            claims.AddRange(userInfoResponse.Claims);
            claims.Add(new Claim("id_token", tokenResponse.IdentityToken));
            claims.Add(new Claim("access_token", tokenResponse.AccessToken));

            if (!string.IsNullOrEmpty(tokenResponse.RefreshToken))
            {
              claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
            }

            n.AuthenticationTicket.Identity.AddClaims(claims);

            return;
          },
          RedirectToIdentityProvider = n =>
          {
            // If signing out, add the id_token_hint
            if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
            {
              var idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token");
              if (idTokenClaim != null)
              {
                n.ProtocolMessage.IdTokenHint = idTokenClaim.Value;
              }
            }

            return Task.CompletedTask;
          }
        },
      });
    }
  }
}


Add an a new MVC 5 empty controller inside of Controllers folder. You can name it AccountController and paste the following code inside of it:

using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using System.Web;
using System.Web.Mvc;

namespace OktaAspNetMvcAngular.Controllers
{
  public class AccountController : Controller
  {
    public ActionResult Login()
    {
      if (!HttpContext.User.Identity.IsAuthenticated)
      {
        HttpContext.GetOwinContext().Authentication.Challenge(OpenIdConnectAuthenticationDefaults.AuthenticationType);
        return new HttpUnauthorizedResult();
      }

      return RedirectToAction("Index", "Home");
    }

    [HttpPost]
    public ActionResult Logout()
    {
      if (HttpContext.User.Identity.IsAuthenticated)
      {
        HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType, OpenIdConnectAuthenticationDefaults.AuthenticationType);
      }

      return RedirectToAction("Index", "Home");
    }

    public ActionResult PostLogout()
    {
      return RedirectToAction("Index", "Home");
    }
  }
}


Add Login Section to Layout

Inside of Views/Shared folder create a new partial view named _LoginPartial and paste the following code inside:

@if (Context.User.Identity.IsAuthenticated)
{
  <ul class="nav navbar-nav navbar-right">
    <li>
      <p class="navbar-text">Hello, <b>@Context.User.Identity.Name</b></p>
    </li>
    <li>
      <a onclick="document.getElementById('logout_form').submit();" style="cursor: pointer;">Log out</a>
    </li>
  </ul>
  <form action="/Account/Logout" method="post" id="logout_form"></form>
}
else
{
  <ul class="nav navbar-nav navbar-right">
    <li>@Html.ActionLink("Log in", "Login", "Account")</li>
  </ul>
}


Set Up Your ASP.NET API Endpoints

You will use the controller as your endpoint source for the API. Add a new Web API controller namedJoggingRecordsController.cs class inside of your Controllers folder and paste the following code:

using OktaAspNetMvcAngular.Data;
using OktaAspNetMvcAngular.Models;

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;

namespace OktaAspNetMvcAngular.Controllers
{
  public class JoggingRecordsController : ApiController
  {
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET: api/JoggingRecords
    public IQueryable<JoggingRecord> GetJoggingRecords() => db.JoggingRecords;

    // GET: api/JoggingRecords/5
    [ResponseType(typeof(JoggingRecord))]
    public async Task<IHttpActionResult> GetJoggingRecord(int id)
    {
      JoggingRecord joggingRecord = await db.JoggingRecords.FindAsync(id);
      if (joggingRecord == null)
      {
        return NotFound();
      }

      return Ok(joggingRecord);
    }
  }
}


The code above adds two endpoints. The first one will fetch all JoggingRecords from the database. In your applications, you will probably want some kind of paging and filtering. The second endpoint will fetch individual JoggingRecords instances based on the id parameter that the client will pass to the API. That parameter will match the Id in JoggingRecords table in the database.

Set a Default Formatter for ASP.NET Web API 2

Unfortunately, ASP.NET Web API 2 is set to use XML as default formatter. Remove it and make sure JSON formatter is the default one. Add the following code at the end of the Register() method inside of WebApiConfig.cs file:

// Set JSON formatter as default one and remove XmlFormatter

var jsonFormatter = config.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.Remove(config.Formatters.XmlFormatter);
jsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;


You’ll also need to add the following using statement for the JSON serializer to the file:

using Newtonsoft.Json.Serialization;


You will also want to specify the port for your ASP.NET application. You need to know the exact address so you can communicate with the API from your Angular application. To do so, right click on the project in the solution explorer and click properties. In the main properties window, choose Web from the left-hand menu and set the Project Url property to http://localhost:8080.

Set Up the Angular Application for ASP.NET MVC

Since you will let your ASP.NET MVC application handle routing you can remove the app-routing.module.ts file and its references in the AppModule. Your app.module.ts file should look like this:

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

import { AppComponent } from './app.component';

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


After that is done, delete the code from app.component.html.

You also need to make sure that the Angular CLI outputs files to the appropriate folder. Inside of your Angular folder open angular.json file and change the outputPath setting:

"outputPath": "../Bundles/AngularOutput",


In the ASP.NET MVC application, you will add a new JS and CSS bundle for Angular. Locate the BundleConfig.cs file inside of App_Start folder and at the end of the RegisterBundles function add the following code:

// Angular bundles
bundles.Add(new ScriptBundle("~/bundles/Angular")
  .Include(
    "~/bundles/AngularOutput/inline.*",
    "~/bundles/AngularOutput/polyfills.*",
    "~/bundles/AngularOutput/scripts.*",
    "~/bundles/AngularOutput/vendor.*",
    "~/bundles/AngularOutput/runtime.*",
    "~/bundles/AngularOutput/main.*"));

bundles.Add(new StyleBundle("~/Content/Angular")
  .Include("~/bundles/AngularOutput/styles.*"));


For this to work, you need to make use of these bundles inside of your views. You should first create a new MVC view for your Angular application. Create a new folder inside of Views folder called AngularData and inside of it create new Index.cshtml file:

@{
  ViewBag.Title = "Index";
}

@Styles.Render("~/Content/Angular")

<app-root>test</app-root>

@Scripts.Render("~/bundles/Angular")


The code above will actually render the JS bundle that our angular application produces. Angular will find the tag and render the App component and everything inside of it.

To access this view, you need to create a matching controller. Inside of Controllers folder create a new MVC 5 controller named AngularDataController:

using System.Web.Mvc;

namespace OktaAspNetMvcAngular.Controllers
{
  public class AngularDataController : Controller
  {
    public ActionResult Index()
    {
      return View();
    }
  }
}


You should also update the layout file so that you can access the Angular application from the menu bar. Locate the _Layout.cshtml file inside of Views/Shared folder. Make sure your navbar looks like this:

<ul class="nav navbar-nav">
  <li>@Html.ActionLink("Home", "Index", "Home")</li>
  <li>@Html.ActionLink("Angular", "Index", "AngularData")</li>
  <li>@Html.ActionLink("About", "About", "Home")</li>
  <li>@`Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>


To have the Angular application outputting the content, navigate inside of the Angular folder and open your favorite terminal. Enter the following command:

ng build --extractCss --watch


The command above will make sure that new bundle is produced whenever you change any code that is part of the Angular codebase, and it will also extract CSS from global styles into CSS files instead of JS ones.

Create a Model and API Service for Your Angular Application

Your app contains only one root module, AppModule, and one component AppComponent. Since the application that you will be making here is a small one you will not create additional modules. Once the application grows and gets more complicated, you should introduce new modules, shared modules to organize your code better. The application itself will only show some records from the API. However, since your Angular application is interacting with the server, you should create a separate Angular service for this purpose.

You can also create a TypeScript model for the JoggingRecord. First create a shared folder inside the app folder, which is part of the Angular application that gets created by the Angular CLI.

Inside of the shared folder create a new file — JoggingRecord.ts:

export default class JoggingRecord {
  id: number;
  distance: number;
  description: string;
  createdAt: string;
}


The class above will allow you to have a strongly typed model for the JoggingRecord inside of your Angular application.

You can now create the API service inside of the shared folder. Name the file api.service.ts:

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

import JoggingRecord from './JoggingRecord';

@Injectable()
export default class ApiService {
  public API = 'http://localhost:8080/api';
  public JOGGING_RECORDS_ENDPOINT = `${this.API}/joggingrecords`;

  constructor(private http: HttpClient) { }

  getAll(): Observable<Array<JoggingRecord>> {
    return this.http.get<Array<JoggingRecord>>(this.JOGGING_RECORDS_ENDPOINT);
  }
}


The ApiService class is the bridge between our Angular application and our Web API endpoints. You need it to fetch the data from our server.

Add the service to the App module by updating the providers array inside of app.module.ts file. You also need to import the HttpClientModule. Your app.module.ts file should end up looking like this:

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

import { AppComponent } from './app.component';
import ApiService from '../shared/api.service';

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


Fetch Data from the ASP.NET API Endpoint

Update the app.component.ts file with the following content:

import { Component, OnInit } from '@angular/core';

import JoggingRecord from '../shared/JoggingRecord';
import ApiService from '../shared/api.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit  {
  joggingRecords: Array<JoggingRecord>;

  constructor(private apiService: ApiService) {
  }

  ngOnInit() {
    this.apiService.getAll().subscribe(data => {
      this.joggingRecords = data;
    });
  }
}


The code above will subscribe will assign the data that ApiService fetches from server to the joggingRecords property.

You also need to update this component’s template (app.component.html):

<div style="text-align:center">
  <h1>
    Jogging Records
  </h1>

  <span *ngFor="let record of joggingRecords">
    {{record.description}} - {{record.distance}}
    <br />
  </span>
</div>


Test Out Your ASP.NET and Angular Application

Since you already have the Angular CLI outputting the code changes for your Angular application in the Bundles/AngularOutput folder, and your MVC application is making use of that folder you can simply start the MVC application and preview Angular app inside of it.

From your Visual Studio use CTRL+F5 to start the application your browser should open and you should see the following screen:

Clicking on the Angular link in the menu will actually render the MVC view for the Angular application and from that point it’s Angular who is in charge of rendering. The Angular page should look like this:

If you open the Dev Tools on your editor you should see that the Angular application actually hits the ASP.NET API:

Learn More

Angular 7 (formerly Angular 2) - The Complete Guide

Learn and Understand AngularJS

Angular Crash Course for Busy Developers

The Complete Angular Course: Beginner to Advanced

Angular (Angular 2+) & NodeJS - The MEAN Stack Guide

Become a JavaScript developer - Learn (React, Node,Angular)

Angular (Full App) with Angular Material, Angularfire & NgRx

The Web Developer Bootcamp

The Complete ASP.NET MVC 5 Course

Build a Real-world App with ASP.NET Core and Angular 2 (4+)

ASP NET Core (ASP.NET 5),MVC 6,C#,Angular2 & EF Crash Course

Angular and ASP.NET Core

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.

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.

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 ng new and ng serve --open 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?".

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 yourApplicationFolder/dist. You can check it out by going to your Angular application and doing an ng build.

Go on, I'll wait.

When you do ng serve --open you are actually using a stand-alone web 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 ng serve 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 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.

You can find the definition of this pipeline on the Startup.cs file, in the Configure method. For example, here's the pipeline that you get when you do a dotnet new mvc:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Every time a request comes in to this ASP.NET Core application it can go through at most three middlewares. First the DeveloperExceptionPage/ExceptionHandler middleware depending if the ASP.NET Core application is running in development mode or not. Then the StaticFiles middleware and then finally the Mvc middleware.

The middleware that is key here is StaticFiles. This is the middleware that serves files contained in the wwwroot folder, i.e. if a request comes in for index.html and there's an index.html file at wwwroot/index.html then that file is sent to the client. StaticFiles middleware won't call the middlewares below it after this (in this case it would be Mvc).

You can probably already see how this could work with an Angular application. Just put it under wwwroot.

That's absolutely correct, however there's a detail about StaticFiles that is important to know. StaticFiles won't try to do any guesses for you, i.e. if your request is for /, StaticFiles won't look for /index.html. It will just assume that this request isn't supposed to be handled by it and it will call the next middleware in the pipeline, in this case Mvc.

For this approach to work you need another middleware named DefaultFiles which must come before StaticFiles in the pipeline:

//...
app.UseDefaultFiles();
app.UseStaticFiles();
//...

DefaultFiles will cause cause StaticFiles to look for index.html if the url ends with /.

Now the only thing left to do is to configure your Angular CLI to compile to your ASP.NET Core application's wwwroot folder.

If you look in your Angular's application folder you'll find a .angular-cli.json file. In that file look for the outDir property:

...
"apps": [
{
    ...
    "outDir": "dist",
...

Change it from "dist" to the path of your ASP.NET Core's wwwroot folder. Run ng build in your Angular application and now if you run your ASP.NET Core web application you should see your Angular application in the browser.

A nice development workflow is to run the Angular CLI build in watch mode: In a console window do ng build --watch or ng build -w if you want to save a few key strokes, and leave it running. Now every time you make a change in your Angular application you can just refresh the browser and see the change (you also need to have your ASP.NET Core application running).

There is one thing missing from this approach, though. Deep-linking support, i.e. if your Angular application uses routing and you send a user a url with a valid Angular route (e.g http://yourapplication.com/products/5) the receiving user won't be able to open it. Trying to get to that route will result in a 404 Not Found response.

That's because the request will go all the way through your ASP.NET Core application's pipeline and when it reaches the MVC middleware it won't know what to do with it and will set the response's status code to 404 Page Not Found.

What we can do is at the top of the pipeline we look for a 404 response that is about to be sent and change its path to our Angular application's index.html file (that way what gets served is the Angular application which will know what to do with the url in terms of routing). After this we make the request go through the pipeline again:

//add this at the start of Configure
app.Use(async (HttpContext context, Func<Task> next) =>
{
    await next.Invoke();

    if (context.Response.StatusCode == 404)
    {
        context.Request.Path = new PathString("/index.html");
        await next.Invoke();
    }
});

That fixes deep links but introduces a new problem. What if your web api (that you've implemented in your ASP.NET Core application) needs to send a 404 response. That's something more than reasonable to do. Instead of a 404, the service call will receive a 200 response with index.html.

The solution here is to look at the url and decide if it's intended for the web api or an Angular route. Usually a call to the web api will have /api in the url. That's a simple test to perform and it will solve this problem. Here's the revised version of a custom middleware that solves this problem:

//add this at the start of Configure
app.Use(async (HttpContext context, Func<Task> next) =>
{
    await next.Invoke();

    if (context.Response.StatusCode == 404 && !context.Request.Path.Value.Contains("/api")))
    {
        context.Request.Path = new PathString("/index.html");
        await next.Invoke();
    }
});

One last note about this approach. I've seen examples where the Angular application is in the same Visual Studio solution as the ASP.NET application. Visual Studio (not VS Code) will try to compile the typescript files. If you are using ng build -w you'll want Visual Studio to leave your Typescript files alone. To do that open your project's .csproj and add in any PropertyGroup:

<TypescriptCompileBlocked>true</TypescriptCompileBlocked>

Nginx

Nginx is a web server that can act as a reverse proxy for ASP.NET Core applications and which is also very good at serving static content.

The setup for having an Angular application work with ASP.NET Core is much simpler in Nginx. You just need a configuration similar to this:

server {
    listen 80;        

    location / {
        root /pathToYourAngularApplication/dist;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://localhost:5000;
    }
}

This is how a typical Nginx configuration file looks like. If you are not familiar with Nginx and ASP.NET Core I recommend my blog post: HTTPS in ASP.NET Core from Scratch. It has a section with instructions on how to install and setup websites using Nginx.

This configuration allows us to have both the Angular and ASP.NET Core application on port 80. Let's look at the important parts in it.

The listen 80 statement establishes that Nginx will respond to requests coming in on port 80.

The location blocks are where we are going to define how our two applications will be served (Angular and ASP.NET). Each time a request comes in, Nginx will look at the URL and try to find the location block that best matches it. In this case the location blocks urls act like a "prefix match", i.e., the first block will match every URL (every url that starts with a /). The second location block matches URLs that start with /api/.

Nginx picks the most "specific" location block, so even though a request for /api/users would match both location blocks, since the second one (/api/) is more specific, it will be the one that would be used to handle the request.

In the first location block (/):

root /pathToYourAngularApplication/dist sets the path where static content will be looked for as the location where your compiled Angular application files are (dist is the CLI's default output folder).

index index.html specifies which file should be served for URLs that end in /.

try_files $uri $uri/ /index.html can be read this way: check if there's a file that matches the normalized URL (e.g. http://www.yourwebsite.com/assets/image.jpg -> /assets/image.jpg), if that file does not exist try the normalized URL plus a / (e.g. http://www.yourwebsite.com/documents -> /documents/ -> /documents/index.html because of the index rule). If all of that fails serve the file /index.html.

Serving /index.html if no match is found is what enables us to use deep linking. For example a URL such as http://www.yourwebsite.com/documentswith no math in the file system will be served with the Angular application's index.html. Index.html will load all the necessary files for the Angular application to run, specifically the routing module. The routing module will then look at the url, and according to the routes defined in the angular app will decide which component to load.

Finally, the last location block. It instructs Nginx to forward the requests that start with /api/ to a webserver that is listening on port 5000 on localhost. That will be your ASP.NET Core's application.

One note about the Nginx's syntax for proxy_pass. It matters a lot if the URL for the application has a / at the end or not. The url in proxy_pass is treated differently if it has what is described in [Nginx's documentation as a "optional URI"](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass "Nginx's documentation as a "optional URI"") (optional URI isn't a great name, since in the end a URL is a URI).

An example of a URL with an optional URI is: http://localhost:5000/optionalURI/. If the location's path is /api/, then a request for http://yourwebsite.com/api/users will be forwarded to your ASP.NET Core's application as http://localhost:5000/optionalURI/users.

That's why not adding the / at the end in proxy_pass is so important, because if you do (e.g.: proxy_pass http://localhost:5000/;) it falls into the "optional URI" category (it will be interpreted as an empty optional URI), and a request for http://yourwebsite.com/api/users will be seen in your ASP.NET Core's application as a request for http://localhost:5000/users.

If you don't add the / at the end (e.g.: proxy_pass http://localhost:5000;) then a request for http://yourwebsite.com/api/users will be seen in the ASP.NET Core application as a request for http://localhost:5000/api/userswhich is probably what you want.

If you need a more complete example that explains how you can make this work outside a development-time scenario (i.e. have your ASP.NET Core application auto start and remain online even if there's an exception) check out HTTPS in ASP.NET Core from Scratch where there's an example describing how you can use Supervisor to keep the ASP.NET application running even in the event of errors (by auto restarting it).

IIS

With IIS it becomes very cumbersome to have a configuration similar to what we can do with Nginx where both the Angular and ASP.NET Core applications are served on port 80.

To understand why it makes it easier if we understand the IIS concepts of Website and Application. When you create a website you define (among other settings) the port (e.g. 80) where it will be served from. A website can then have several applications "inside" it, all of which will share the website configuration (and therefore be served on the same port).

We could for example put our Angular application inside the "Default Web Site" and the ASP.NET Core one as an IIS Application under it, and call it for example "api".

If the "Default Web Site" responds at http://localhost, then the ASP.NET Core application could be at http://localhost/api. Which seems to be exactly what we want. However, the requests for http://localhost/api would be seen in ASP.NET Core without the api in the url.

As far as I know there's no way to change this behavior.

This means your ASP.NET Core application will behave differently when running inside IIS vs when executed directly (either in Visual Studio or with dotnet run).

To make matters worse an ASP.NET Core application needs to be published (dotnet publish) for it to work in IIS. It's not like a non-Core ASP.NET application where you can just point an IIS Application to the folder that contains the ASP.NET application's files .

So when using IIS the reasonable options are to either have ASP.NET Core serve the angular application as it was described in the first section of this article or have two separate Websites.

Lets walk-though the process of creating two separate websites. First a website for the Angular project and then for ASP.NET Core.

Angular in IIS

We'll be adding a Website named MyNgWebSite on port 80. That means that if you have a "Default Web Site", which in all likelihood you'll have, you need to stop it or change its bindings since the default for it is port 80.

But before we get there we need to create an application pool for our Angular application. Right click on Application Pools in IIS Manager:

The Application Pool for an Angular application does not require Managed Code (we only need to serve static files). We should choose "No Managed Code" in the .NET CLR Version:

We can now add a new IIS web site and set the new application pool we created as its application pool:

The physical path should be set to where your Angular project is being compiled to, usually this is the dist folder.

If you were to try to access http://localhost right now (and assuming that you stopped the "Default Web Site" or used a different port than 80) you would get a permissions error. That's because when you create an application pool a ["virtual" user is created](https://docs.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities ""virtual" user is created"). That user is a local user and must have permissions to access the folder that contains the files you are trying to serve.

That user's name is IIS AppPool\ApplicationPoolName, in this example it's IIS AppPool\ApplicationPoolForAngular.

Go to the folder that contains the compiled Angular project, right click on it and select properties, go to the security tab, click edit, then add and finally add the application pool user:

We should now be able to access your Angular application if you go to http://localhost.

We still need to do one more thing though. Enable deep-linking support.

If you have routes in your Angular application these won't work if someone tries to access them from "outside" the Angular app. What this means is that if navigating to http://localhost/documents is valid inside the Angular application and you send that url to someone else, when that someone else clicks the link they will be greeted with a 404 page from IIS.

That's because there is no documents folder nor index file inside it for IIS to serve. We need to tell IIS that it must serve the file index.html when someone tries to access a URL that does not exists.

We are going to use the same mechanism used for having a custom 404 page, but instead of a 404 page we'll serve the Angular application.

To achieve this we need to create a web.config file and put it in the src folder of the Angular application with this inside:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Custom" existingResponse="Replace">
            <remove statusCode="404"/>
            <error statusCode="404" responseMode="ExecuteURL" path="/index.html"/>
        </httpErrors>
    </system.webServer>
</configuration>

A very quick explanation of what's going on. We are using httpErrors with an errorMode="Custom" and existingResponse="Replace". This instructs IIS to replace the default error pages with the one we are about to specify.

remove statusCode="404" will remove any custom settings for 404 pages if they already exist.

error statusCode="404" responseMode="ExecuteURL" path="/index.html" will configure IIS to execute the /index.html url if there's a 404 error. This will effectively serve your Angular application and won't change the URL seen by the client.

Now we need to edit the .angular-cli.json file so that web.config gets copied to the output folder as an asset when the application is compiled. The assets section is under "app", here's an example:

{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
    "name": "your-app"
},
"apps": [
    {
    "root": "src",
    "outDir": "dist",
    "assets": [
        "assets",
        "favicon.ico", 
        "web.config"
    ],
    "index": "index.html",
...

ASP.NET Core in IIS

The process for the configuring an ASP.NET Core application in IIS is similar, although we need to select a different port.

But before you start you need to make sure you have the ASP.NET Core Module for IIS installed. It might already be installed if you installed the .Net Core SDK, however the best way to make sure is to go to IIS Manager and see if it's in the modules' list:

If you don't have it you can find more information about it here and a direct link to download it here.

This module takes care of starting and keeping an ASP.NET Core application running.

Before we create the website in IIS we need the published version of the ASP.NET Core application. You can do that in the command line with dotnet publish or, in full Visual Studio, right click on the project and select Publish, then click publish to folder.

Create a new Website and point it to the ASP.NET Core project published folder, give it a different port number (for example 8080) and create an Application Pool for it.

An application pool for an ASP.NET Core application is also unmanaged (No Managed Code). Although this might seem odd, it's because IIS is actually just acting as a reverse proxy.

Before we're able to run the ASP.NET Project using IIS we need to changed the published folder's permissions so that the Application Pool user can access it. If you don't you'll get this moderately unhelpful error message:

HTTP Error 500.19 - Internal Server Error> HTTP Error 500.19 - Internal Server Error

If you look at the Config Error section you'll see "Cannot read configuration file due to insufficient permissions", which pretty much says it all.

Go to the published folder and add the application pool user to the list of users with permissions over that folder.

Your ASP.NET Core application should now be available on the port you've selected when you created the website in IIS. However, if you try to call it from the Angular application you'll get this error "Failed to load ... No 'Access-Control-Allow-Origin' header is present on the requested resource...". Here's an example of how that would look like in the developer tools console tab:

That's because even though both our our Angular and ASP.NET Core applications are on the same domain, they are in different ports, and that's enough to qualify the request as a Cross Origin Resource Sharing (CORS) request in all browsers except IE.

We need to enable CORS on the ASP.NET Core application. To do that we need to add the package Microsoft.AspNetCore.Cors and in ConfigureServices(IServiceCollection services... method in Startup.csadd services.AddCors():

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddCors();
    //...
}

And in the Configure method we need to create a "policy" that says that we are expecting requests from http://localhost. We should do that before the MVC middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //...
    app.UseCors(builder => builder.WithOrigins("http://localhost"));
    app.UseMvc();
}

You should be good to go. Your Angular and ASP.NET Core should both be working now.

Platform Agnostic Development Setup

Both Angular and ASP.NET Core applications provide ways to detect if they are running in development or production mode. That can be leveraged to create a setup that works both in Linux, Windows or Mac.

The easiest way to run an Angular application is to use run ng serve. That spins up a webpack development server that serves the Angular application on port 4200 by default.

This also has the advantage of having hot module replacing, which means you can see your changes to the Angular application as soon as you make then without even having to refresh the browser.

So ideally we want to run the Angular application this way.

For the ASP.NET Core application we want to run it without having to publish it which you would have to if it is being served by IIS.

This is the ideal development scenario, ng serve for Angular and dotnet run or running the ASP.NET Core from Visual Studio without having to publish it.

In this ideal scenario when developing we could have the Angular application running on port 4200 (through ng serve) and the ASP.NET Core application running on port 5000. When in production the Angular application would typically be served from port 80 and the ASP.NET Core application for port 8080 for example (or from a different server on port 80).

On the ASP.NET Core side of things we'd have to configure CORS to accept requests from port 4200 when in development and from port 80 when in production. In Startup.cs that would look like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
    //...        
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //...
    if (env.IsDevelopment())
    {
        //...
        app.UseCors(builder => builder.WithOrigins("http://localhost:4200"));
    }else 
    {
        app.UseCors(builder => builder.WithOrigins("http://localhost"));
    }

    app.UseMvc();
}

That takes care of the ASP.NET Core application.

For Angular we need to leverage the environemnt.ts and environemnt.prod.ts files. You can find then under a folder name environemnts under the src folder on an Angular project.

What you put on environment.ts will be available when you run in development mode (the default) and the values in environment.prod.ts will be used when in production. To compile the Angular project with the environment set to production use the --env=prod flag (e.g. ng build --env=prod).

Here's a simple example of how the environment files could be configured to support our hypothetical scenario, environment.ts:

export const environment = {
    production: false,
    apiBaseUrl: "http://localhost:4200/"
};

environment.prod.ts:

export const environment = {
    production: true,
    apiBaseUrl: "http://localhost/"
};

In your Angular services, to get to the environment values you just need to import the environment (always environment and not environment.prod):

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

@Injectable()
export class MyServiceService {

    constructor(private httpClient: HttpClient) { }

    getStuff(){
        return this.httpClient.get(`${environment.apiBaseUrl}/api/suff`);
    }  
}

This approach would work even if you host on Nginx or IIS so probably the best option if you need/want to support having developers using different platforms of if you just want to compare performance between them.

Building Single Page Application Using ASP.NET Core & Angular

In this video, you'll learn building applications on Asp.Net Zero platform using Asp.Net Core & Angular.

It starts with introducing Asp.Net Zero and its features. Then deeply investigates the source code structure with live demos and helps you to get up and running with Asp.Net Zero. If finally shows how to create your business functionality step by step on top of the existing source code.

Thanks for watching

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Angular 8 (formerly Angular 2) - The Complete Guide

The Complete ASP.NET MVC 5 Course

Build an app with ASPNET Core and Angular from scratch

Build A Real World Beautiful Web APP with Angular 8 — A to Z

Best 50 Angular Interview Questions for Frontend Developers in 2019

Best 17 Angular Libraries Every Angular Developers Should Know in 2019


Single Page Application using Asp.Net Core 2.2 and Angular

In this blog post, we are going to create Single Page Application (spa) using Asp.Net Core 2.2 and Angular. Microsoft has recently announce the release of Asp.Net Core 2.2.&nbsp;.NET Core 2.2 is supported by&nbsp;<a href="https://visualstudio.microsoft.com/vs/" target="_blank">Visual Studio 15.9</a>, Visual Studio for Mac and Visual Studio Code.

In this blog post, we are going to create Single Page Application (spa) using Asp.Net Core 2.2 and Angular. Microsoft has recently announce the release of Asp.Net Core 2.2. .NET Core 2.2 is supported by Visual Studio 15.9, Visual Studio for Mac and Visual Studio Code.

Download

Download the .Net Core 2.2 SDK from below link, if you don’t have in your machine.

Download the .Net Core 2.2 SDK – Mac OS x64 Installer

Run

Run the downloaded Installer

Finish Installation

After all these steps, this setup has installed Microsoft .Net Core SDK 2.2 successfully on your MacOS. The following packages have been installed on your MacOS with this installer.

  • .Net Core SDK 2.2.101
  • .Net Core Runtime 2.2.0
  • Asp.Net Core Runtime 2.2.0
Verify Installation

Check the Installation by running these commands in your terminal window.

dotnet
Or
dotnet –version
Let’s create our Angular app in .Net Core 2.2. We are going to use Visual Studio Core on MacOS. If you don’t have Visual Studio Core, you can download from below link.

Download Visual Studio Core

Create Angular App

Moving forward, let’s create our Angular app using the below command in terminal window. I have created a AngularDemo directory, and run the command inside this directory.

cd angulardemo> dotnet new angular -o zeptoapp
After running this command, it will create Visual studio .csproj file in your folder.

Open the Visual Studio Core IDE, and open the zeptoapp folder. It looks like this.

This project template create an ASP.NET Core app and Angular app. You can use ASP.NET Core app for data access, authorization, and other server-side functionalities.

Your Angular App is inside the ClientApp folder.

Run Angular app

Now, go to clientapp->src folder, and try to run your Angular app by this command in terminal.

ng serve –open
Note:- If you see this error message in your console.
Could not find module “@angular-devkit/build-angular” from “/Users/XXX/Documents/AngularDemo/zeptoapp/ClientApp”.> Error: Could not find module “@angular-devkit/build-angular” from “/Users/XXX/Documents/AngularDemo/zeptoapp/ClientApp”.> at Object.resolve (/usr/local/lib/node_modules/@angular/cli/node_modules/@angular-devkit/core/node/resolve.js:141:11)> *at Observable.rxjs_1.Observable *as _subscribe> at Observable._trySubscribe (/usr/local/lib/node_modules/@angular/cli/node_modules/rxjs/internal/Observable.js:44:25)> at Observable.subscribe (/usr/local/lib/node_modules/@angular/cli/node_modules/rxjs/internal/Observable.js:30:22)> at /usr/local/lib/node_modules/@angular/cli/node_modules/rxjs/internal/Observable.js:99:19> at new Promise ()> at Observable.toPromise (/usr/local/lib/node_modules/@angular/cli/node_modules/rxjs/internal/Observable.js:97:16)> at ServeCommand.initialize (/usr/local/lib/node_modules/@angular/cli/models/architect-command.js:91:94)> *at *> at process._tickCallback (internal/process/next_tick.js:188:7)
Run this npm command in your terminal.
npm install –save-dev @angular-devkit/build-angular
Once this @angular-devkit has been installed in your project folder, you are now good to go. Now, run your Angular app using
ng serve –open

This will successfully launch Angular app at http://localhost:4200/

Run Asp.net Core api with Angular app

Run the complete project. Go to Debug->Start Debugging or Pressing F5, your Angular app and .Net Core app will run altogether.

                                                                                Home Screen

                                                                                 Counter Screen

                                                                         Fetch Data Screen

If you look at the Fetch Data screen, you will be wondering how this data is coming, as we haven’t created any Angular component or service to display the data. This is the magic of .Net Core with Angular. We got everything setup for us. Let’s look into the details of each section.

Let’s first look at out .Net Core Controller API code.

SampleDataController.cs

You can see, our have SampleDataController.cs file in Controllers folder of our project. In the controller file, we have code for our Fetch Data page.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace zeptoapp.Controllers
{
    [Route("api/[controller]")]
    public class SampleDataController : Controller
    {
        private static string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        [HttpGet("[action]")]
        public IEnumerable<WeatherForecast> WeatherForecasts()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                DateFormatted = DateTime.Now.AddDays(index).ToString("d"),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            });
        }

        public class WeatherForecast
        {
            public string DateFormatted { get; set; }
            public int TemperatureC { get; set; }
            public string Summary { get; set; }

            public int TemperatureF
            {
                get
                {
                    return 32 + (int)(TemperatureC / 0.5556);
                }
            }
        }
    }
}

Now, look at the Angular component in our project solution.

                                                  import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-fetch-data',
  templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
  public forecasts: WeatherForecast[];

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
      this.forecasts = result;
    }, error => console.error(error));
  }
}

interface WeatherForecast {
  dateFormatted: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}
<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

<p *ngIf="!forecasts"><em>Loading...</em></p>

<table class='table table-striped' *ngIf="forecasts">
  <thead>
    <tr>
      <th>Date</th>
      <th>Temp. (C)</th>
      <th>Temp. (F)</th>
      <th>Summary</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let forecast of forecasts">
      <td>{{ forecast.dateFormatted }}</td>
      <td>{{ forecast.temperatureC }}</td>
      <td>{{ forecast.temperatureF }}</td>
      <td>{{ forecast.summary }}</td>
    </tr>
  </tbody>
</table>

Run Angular app Independently

The project is configured to start its own instance of the Angular CLI server in the background when the ASP.NET Core app starts in development mode. This is convenient because you don’t have to run a separate server manually.

There’s a drawback to this default setup. Each time you modify your C# code and your ASP.NET Core app needs to restart, the Angular CLI server restarts. Around 10 seconds is required to start back up. If you’re making frequent C# code edits and don’t want to wait for Angular CLI to restart, run the Angular CLI server externally, independently of the ASP.NET Core process. To do so:

  • In terminal, go to ClientApp folder, and run this command.

npm start* Modify your ASP.NET Core app to use the external Angular CLI instance instead of launching one of its own. In your Startup class, replace the spa.UseAngularCliServer invocation with the following:
spa.UseProxyToSpaDevelopmentServer(“http://localhost:4200”);; "http://localhost:4200”);")
When you start your ASP.NET Core app, it won’t launch an Angular CLI server. The instance you started manually is used instead. This enables it to start and restart faster. It’s no longer waiting for Angular CLI to rebuild your client app each time.

Summary

In summary, we have learned how to create a single page application using Asp.Net core as backend and Angular as frontend. This is more productive, flexible and less time consuming process.