Each ASP.NET Core project type has a project file, also known as MSBuild project file. The name of the project file is {appName}.csproj or {appName}.vbproj based on the selected language (c# or Vb).
The project file (.csproj or .vbproj) has been a part of .NET projects from a long period of time. This means ASP.NET Web Forms and ASP.NET MVC projects also contains one project file.
But, the format and content of the file has significantly changed. Also, the way we used to edit the project file for .NET Framework projects has completely changed with .NET Core (.NET 5). For, example to edit an ASP.NET project that targets .NET Framework we first need to unload the project and then only we become able to edit the project file, but we can open and edit an ASP.NET Core project file by simply double clicking on the project name (root folder) or by right-clicking on the root folder (project Name) and selecting the edit project file option.
An ASP.NET Core project file doesn't contain any reference of the files and folder present in the project. In the previous version of ASP.NET, when we add a file or folder to the project a reference of that file or folder gets included in the project file. In ASP.NET Core the file system determines what files and folders belong to the project this means ASP.NET Core project files and folders are synchronized with physical files and folders. If we add a new file or folder in the project folder then it directly reflects in the solution explorer.
To understand the ASP.NET Core project file, we must have some experience with MSBuild. I will not explain "MSBuild" in detail because it is a vast topic in itself and we rarely need to edit a project file, however, we should know about it.
MSBuild or Microsoft build engine is a platform for building applications. Both .NET CLI and Visual studio uses MSBuild to build a .NET project.
The MSBuild project file is an XML document as you can see in the image shown above. The project file contains the MSBuild code that executes when we fire the command dotnet build / dotnet MSBuild or build the project directly from the visual studio.
The traditional ASP.NET project has large and complex MSBuild project files and is managed automatically by the Visual Studio IDE but now the visual studio is not mandatory for .NET Core or .NET 5 projects. So, a new format of MSBuild project files was released with the release of .NET Core, which is known as SDK-Style project files.
SDK Style project files are thousand times simplified because all the MSBuild Complexity is now encapsulated in an SDK which contains a set of MSBuild properties, items, targets, and tasks for building the project. Now, you might be thinking what are items, targets, tasks, or properties? These are the building blocks of an MSBuild project file which I have discussed later in the article.
Project file at a glance
The <project> element is the root element of an MSBuild project file. The SDK attribute tells MSBuild that this is an SDK-Style project.
Basic elements of an MSBuild project file
Properties
Properties in MSBuild project file are key-value pairs which are used to configure builds, you can think of them as variables in any programming language. Properties are declared as a child of PropertyGroup elements.
For example, the following code creates a property named BuildDir that has a value of Build.
<PropertyGroup>
<BuildDir>Build</BuildDir>
</PropertyGroup>
Properties can be referenced throughout the project file by using the syntax $(<PropertyName>). For example, we can reference the property "BuildDir" by using $(BuildDir).
The "TargetFramework" property specifies the target framework version for the app.
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
Tasks
Tasks are unit of executable code that MSBuild uses to perform build operations. Tasks accept parameters which are passed as attributes of the element. Tasks are created as a child element of Target element.
For example, Exec task Runs a specified command by using the specified arguments.
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo Output written to $(TargetDir)" />
</Target>
Items
Items are inputs into the build system and can be used as parameter for tasks. Items are specified as a child of an ItemGroup element.
For example, we can add a dependency in the project file using the following syntax:
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.9" />
</ItemGroup>
Targets
Targets group Tasks together in a particular order. Targets are declared in the project file by using the target element.
For example, we can use an MSBuild target named PreBuild or PostBuild and can set the BeforeTargets property for PreBuild or the AfterTargets property for PostBuild.
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo Output written to $(TargetDir)" />
</Target>