9
votes

I have an angular project that I'd like to include in my Visual Studio solution. I added a new project with type ASP.NET Core 2/Empty that has all of the files, excluding the node_modules and similar ones via wildcard directly in csproj.

The problem I'm having is with overriding default build target - when build target is triggered I'd like to call "ng build", but this doesn't happen. Some materials about this can be found here and here

1 Attempted to override default build target:

 <Target Name="Build">
    <Message Importance="high" Text="Overriding default build" />
 </Target>

But still it doesn't execute.

2 Tried to specify DefaultTargets, but it doesn't get called just the same:

 <Project DefaultTargets="NgBuild" Sdk="Microsoft.NET.Sdk.Web">
   ...
 <Target Name="NgBuild">
    <Message Importance="high" Text="Overriding default build" />
 </Target>

Only after I add attribute BeforeTargets="Build" the message is there.

So the question is - how do I override default build behavior? Ultimately, I'd like to have a target that will invoke <Exec Command="ng build"> inside of it and doesn't produce an .exe and doesn't require any .cs files in the project.

2
Why don't you post your entire project file. Order of definitions and how the file is defined does matter in this case.Jacek Blaszczynski

2 Answers

20
votes

The reason the Build target is not to overridden is because it isn't defined yet at the time your custom target is loaded - your custom target is overridden by the default target.

If you use an SDK-based project file using <Project Sdk="…">, the SDK props and targets files (just two msbuild project files) are automatically imported before and after your project file. The Build target is actually defined through the import that comes after the project's contents and thus overrides the one you define in the project file.

If you really want to override the Build target (more on that later), I suggest you move from implicit SDK imports to explicit SDK imports:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />
  <!-- Project content -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
  <Target Name="Build">
    <!-- this will override the default Build target. -->
  </Target>
</Project>

However, the SDK is built around compiling and generating .NET assemblies. You may find that overriding the Build target may lead to unexpected results, including your project not being able to produce output that can be referenced by other projects (if you want that).

If you simply want to add a build step to your project, I suggest adding a custom target that hooks into the exiting build process:

<Target Name="NgBuild" BeforeTargets="BeforeBuild">
  <Exec Command="ng build" />
</Target>
3
votes

Seems, you need to specify a new target to solve your problem.

For example in my .csproj I have following lines:

  <Target Name="TestTarget">
    <Exec Command="echo hello" />
    <Exec Command="echo goodbye" />
  </Target> 

To call them, I need to execute the following command:

dotnet msbuild /t:TestTarget

In this scenario, you can specify commands and order of execution. Hope, this will help.