Click here to Skip to main content
15,881,852 members
Articles / Web Development / ASP.NET / ASP.NET Core
Tip/Trick

ASP.NET Core: Deploy Web API and Angular from the Same Project to the Same IIS Port

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
13 Jul 2020CPOL2 min read 72.3K   570   7   4
Deploy Web API and Angular from the same project to the same IIS port
Previously, I used to host web API and Angular in different ports at IIS, the source codes were also allocated in different projects. Then I found a way to publish and deploy things together. Let's check how we can do it.

Introduction

Previously, I used to host web API and Angular using different ports at the same IIS, the source codes were also allocated in two different Visual Studio projects. Then I found a way to publish and deploy things together. Let's check how we can do it.

Project Structure

Here is my project structure. WebApiAndAngular is the main project.

Image 1

  • Controllers: All the API controller classes
  • ClientApp: Angular web UI project
  • wwwroot: Here, we are going to publish the Angular web UI project.

Angular Project Changes

Now, we are going to make some changes to our Angular project. The aim is to change the publish location from "dist" to API projects "wwwroot" folder. So in angular.json, let's change the output path to "outputPath": "../wwwroot".

Image 2

API Project Changes

Add the below code to .csproj file to manage typescript:

XML
<PropertyGroup>
  <!--added me-->
  <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>

SPA Startup

There is an option in ASP.NET CORE to build a single page application, we are going to use that feature. Here is a SPA Startup class:

C#
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace WebApiAndAngular
{
    internal class SpaStartup
    {
        internal static void Configure(IApplicationBuilder app)
        {
            app.UseStaticFiles();
            app.UseSpaStaticFiles();
            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";
                //if (env.IsDevelopment())
                //{
                //    spa.UseAngularCliServer(npmScript: "start");
                //}
            });

            // here you can see we make sure it doesn't start with /api, 
            // if it does, it'll 404 within .NET if it can't be found
            app.MapWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
            {
                builder.UseMvc(routes =>
                {
                    routes.MapSpaFallbackRoute(
                        name: "spa-fallback",
                        defaults: new { controller = "Home", action = "Index" });
                });
            });
        }

        internal static void ConfigureServices(IServiceCollection services)
        {
            //added me
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "wwwroot";
            });
        }
    }
}

We are going to use this new startup class inside our main Startup class like below. Check /*Spa Startup*/ section:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.Swagger;

namespace WebApiAndAngular
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. 
        // Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            ApiDocStartup.ConfigureServices(services);
            /*Spa Startup*/
            SpaStartup.ConfigureServices(services);
        }

        // 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.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. 
                // You may want to change this for production scenarios, 
                // see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
            ApiDocStartup.Configure(app);
            /*Spa Startup*/
            SpaStartup.Configure(app);
        }
    }
}

Build/Publish Process

Debug Process

First, we need to do ng build/ng serve our Angular project using Visual Code or terminal.

Then, we will run our Web API project in debug mode using Visual Studio or command.

Publish Process

First, we need to publish bg build/ng build --prod our Angular project using Visual Code or terminal.

Then, we will publish our Web API project using Visual Studio or command.

Publish Script Using Cake

This is also possible with a cake build script, I will share it soon.

Result

In debug/release mode, we will see both API and UI views working fine. Now I am running project in debug mode using Visual Studio, the port number may not be the same for you.

API

API Doc Page(swagger): https://localhost:44395/api/index.html

Value API: https://localhost:44395/api/values

Image 3

Angular UI

Page: https://localhost:44395/deshboard

Image 4

Limitations

Try not to use any route like /api/anything in the Angular app, because /api/ suffix is going to navigate things to API classes.

History

  • 13th July, 2020: Initial version

License

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


Written By
Bangladesh Bangladesh
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questiongreat really but i have problem Pin
Member 1451304512-Dec-21 11:23
Member 1451304512-Dec-21 11:23 
QuestionRe: great really but i have problem Pin
DiponRoy20-Dec-21 17:08
DiponRoy20-Dec-21 17:08 
waht if change [object%20Object] to api/, may be this is the issue.
PraisePractical and Useful Pin
mldisibio14-Jul-20 7:19
mldisibio14-Jul-20 7:19 
GeneralRe: Practical and Useful Pin
DiponRoy25-Jul-20 1:27
DiponRoy25-Jul-20 1:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.