Tom Maher
Tom Maher

Reputation: 2054

When converting an existing ASP.Net Core Angular App to use the new VS2022 Project Template why does the Angular content not publish?

I have an existing ASP.Net Core Angular application that used a previous Visual Studio project template where the Web API backend server code and SPA client app are all contained within a single csproj file.

The new Visual Studio 2022 ASP.Net Core Angular application project template as detailed by the following MSDN article uses 2 projects. One csproj for the backend server Web API C# code and another separate esproj (ECMA script project) for the Angular typescript code.

Visual Studio 2022 ASP.Net Core Angular Project Template

So I wanted to convert over to use the new 2 project format and I followed the template example. I got everything working when running the application in Visual Studio which launches the Web API server code and client app code on 2 different urls and proxies between them.

However when the application goes through the continuous integration pipeline the application is published. This uses the publish profiles and in this particular case a standard folder publish profile. When this runs it produces the site with the server code assemblies but no Angular content. When I run the publish locally it completes successfully but with the same result. There is no Angular content. I can see from the build output in Visual Studio that esproj file is definitely being built.

In the old single project setup where was a build target within the crproj file that looked like the following:

<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --configuration=production" />

<!-- Include the newly-built files in the publish output -->
<ItemGroup>
    <!-- Adjust the Include path to match the actual output directory of your Angular build -->
    <DistFiles Include="$(SpaRoot)\dist\**" />
    <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <!-- Ensure the files are copied to the wwwroot directory -->
        <RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
        <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </ResolvedFileToPublish>
</ItemGroup>

However in the new 2 project setup the csproj has no such build target. So I am guessing it uses some sort of convention to retrieve the Angular content from the dist output path. Like both the MSDN article and example project. I made sure I added the project reference from csproj to the esproj like this:

<ProjectReference Include="..\angularwithasp.client\angularwithasp.client.esproj">
   <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

However the was still no Angular content when doing a publish.

Upvotes: 1

Views: 466

Answers (1)

Tom Maher
Tom Maher

Reputation: 2054

It took a while to work out what the issue was with my project when compared to the template example. However after several hours of going through and trying various changes I realised that the output of the Angular content in the template example was ending up in a directory named after the esproj project name under the standard dist output path. This was controlled by the outputPath property in the angular.json file:

...
"projects": {
  "angulardotnetapp1.client": {
    "projectType": "application",
    "schematics": {},
    "root": "",
    "sourceRoot": "src",
    "prefix": "app",
    "architect": {
      "build": {
        "builder": "@angular-devkit/build-angular:browser",
        "options": {
          "outputPath": "dist/angularwithasp.client",
          "index": "src/index.html",
          "main": "src/main.ts",
          "polyfills": [
            "zone.js"
          ],
...

The output path in the application I was converting over to use the new 2 project setup was set to just dist. Publish must use some sort of convention that looks for a folder with the name of the project most likely based on the project references. And then copies this over.

As it took me a long to work this out and this convention does not appear to be documented anywhere I thought I would post it here as an answer to my own question.

I hope this helps other people.

Upvotes: 2

Related Questions