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.
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".
API Project Changes
Add the below code to .csproj file to manage typescript:
<PropertyGroup>
<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:
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";
});
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)
{
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:
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; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
ApiDocStartup.ConfigureServices(services);
SpaStartup.ConfigureServices(services);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
ApiDocStartup.Configure(app);
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
Angular UI
Page: https://localhost:44395/deshboard
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