NyxSql Part II - .Net project files

Intro

Within this article we will take a look at the upgrade project file and how it should look like : )

With .Net (Core), Microsoft introduced a much better formatted and usable project file than in previous versions. Sadly, the upgrade assistant and new projects had been a mess in the beginning (for creating the project files), but slowly it seems to get better.

At the end of this article, you can find an example of the Nyx project file after the upgrade. I am not posting it right here, because nobody likes to scroll over dozens of lines...

General

When reformatting/extracting the project file, it is important to know about the different properties. So, if you find some which are unknown to you, just look it up using the MSDN and be happy that you learned something new! : ) *Sadly, right now F1 (=Open Help) is only usable on the root properties, so we have to look them up manually.

Especially when working in teams it is important to have a unique structure throughout all projects. Imagine you want to change some setting, and always must search the project file, if and where this setting is used.

The first thing I normally do is execute the auto-formatting on the file by pressing Ctrl + Alt + Enter. Another important thing, use commentary blocks for a better visual structure.

Normally I split the project file into two different blocks. The first one does contain properties that are valid/required for all projects and the second one which is different for each project.

The first, general, block

The properties which are valid for all projects: `

<Project Sdk="Microsoft.NET.Sdk">
    <!--
    fixed settings, same for every .net 6 project
    -->
    <PropertyGroup>
        <!--general -->
        <Company>y0</Company>
        <Copyright>Copyright © 2022</Copyright>
        <PackageLicenseUrl>www.mit-license.com</PackageLicenseUrl>
        <PackageProjectUrl>www.myproject.com</PackageProjectUrl>
        <!--application versioning-->
        <AssemblyVersion>1.1.0</AssemblyVersion>
        <!--general settings-->
        <RestorePackages>true</RestorePackages>
        <PlatformTarget>x64</PlatformTarget>
        <TargetFramework>net6.0-windows</TargetFramework>
        <LangVersion>latest</LangVersion>
        <Deterministic>False</Deterministic>
        <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
        <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
    </PropertyGroup>
    <!-- unit test / visible to .Test assembly -->
    <ItemGroup>
        <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
            <_Parameter1>$(AssemblyName).Tests</_Parameter1>
        </AssemblyAttribute>
    </ItemGroup>
    <!--general debug and release settings-->
    <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
        <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
        <DebugType>portable</DebugType>
    </PropertyGroup>
    <PropertyGroup>
        <OutputType>Exe</OutputType>
    </PropertyGroup>
    <!--
    dynamic project related 
    -->
</Project>

Conditions, Configuration == build configurations

Settings related to the configuration, platform or other conditions are next.

Do we really require different AnyCpu/x86/x64 conditions? Very rare required but mostly taking much space and causing big confusions (the platform target was already set in the first section.

If not, we can simply remove the platform condition by transferring:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> .. </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> ... </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> .. </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> ... </PropertyGroup> to: ```

true TRACE;DEBUG; portable ```

Empty project folders

By using the upgrade-assistant, all empty folders without source files are integrated: <ItemGroup> <Folder Include="NyxMsSql\" /> </ItemGroup> As it is just an empty folder, we delete the folder by using Solution Explorer. By handling it this way, the section is also automatically removed.

Assembly/project references and NuGet packages

And finally, the nodes for the project/assembly references and the NuGet packages. I personally keep the project, then the assembly references and finally the NuGet packages, because NuGet packages are handled automatically.

Summary

With the latest upgrade-assistant it is, not anymore, such a big mess. However, the same structure of the project files is coming in very handy if working with dozens of projects.

One project file is done, two to go! : )

Example formatted file

<Project Sdk="Microsoft.NET.Sdk">
    <!--
    General settings, mostly the same for all projects
    -->
    <PropertyGroup>
        <!--copyright -->
        <Company>Dominik Schischma</Company>
        <Copyright>Copyright © 2022</Copyright>
        <PackageLicenseUrl>www.sigterm.eu</PackageLicenseUrl>
        <PackageProjectUrl>www.sigterm.eu</PackageProjectUrl>
        <!--application versioning-->
        <AssemblyVersion>0.0.1</AssemblyVersion>
        <!--general settings-->
        <RestorePackages>true</RestorePackages>
        <PlatformTarget>AnyCPU</PlatformTarget>
        <TargetFramework>net6.0-windows</TargetFramework>
        <LangVersion>latest</LangVersion>
        <Deterministic>False</Deterministic>
        <!--do not create sub directories like 'net-6.0' -->
        <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath><AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
    </PropertyGroup>
    <!-- build configuration -->
    <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
        <!--only use in debug!-->
        <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
        <DebugType>portable</DebugType>
    </PropertyGroup>
    <!-- unit test / internals visible to .Tests assembly -->
    <ItemGroup>
        <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
            <_Parameter1>$(AssemblyName).Tests</_Parameter1>
        </AssemblyAttribute>
    </ItemGroup>
    <!--
    nyxsql
    -->
    <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <AssemblyName>NyxSql</AssemblyName>
        <RootNamespace>NyxSql</RootNamespace>
        <!--<StartupObject>Nyx.Program</StartupObject>-->
        <ApplicationIcon>Resources\Nyx.ico</ApplicationIcon>
        <!-- still windows forms -->
        <UseWindowsForms>true</UseWindowsForms>
        <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
    </PropertyGroup>
    <!--non-classes & usercontrols-->
    <ItemGroup>
        <Compile Update="NyxControls\AutoCompletition\AcListBox.cs">
            <SubType>Component</SubType>
        </Compile>
        <Compile Update="NyxControls\PreviewTab.cs">
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="NyxControls\ProcedureTab.cs">
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="Tools\Connection\ConnectionInput.cs">
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="NyxControls\SqlRichTextBox.cs">
            <SubType>Component</SubType>
        </Compile>
        <Compile Update="NyxControls\SqlTab.AutoCompletition.cs">
            <DependentUpon>SqlTab.cs</DependentUpon>
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="NyxControls\TableTab.cs">
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="NyxControls\TriggerTab.cs">
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="NyxControls\ViewTab.cs">
            <SubType>UserControl</SubType>
        </Compile>
        <Compile Update="NyxControls\SqlTab.cs">
            <SubType>UserControl</SubType>
        </Compile>
    </ItemGroup>
    <!--project references-->
    <ItemGroup>
        <ProjectReference Include="..\NyxSettings\NyxSettings\NyxSettings.csproj" />
    </ItemGroup>
    <!--assembly references-->
    <ItemGroup>
        <None Update="Assemblies\Mono.Security.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
        <None Update="Assemblies\MySql.Data.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
        <None Update="Assemblies\Npgsql.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
    </ItemGroup>
    <!--nuget-->
    <ItemGroup>
        <PackageReference Include="odp.net.managed" Version="121.1.2" />
        <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
        <PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.346201">
            <PrivateAssets>all</PrivateAssets>
        </PackageReference>
        <Reference Include="MySql.Data, Version=5.0.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
            <Private>False</Private>
        </Reference>
        <Reference Include="Npgsql, Version=0.99.3.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7, processorArchitecture=MSIL">
            <SpecificVersion>False</SpecificVersion>
            <HintPath>assemblies\Npgsql.dll</HintPath>
            <Private>False</Private>
        </Reference>
    </ItemGroup>
</Project>

Example file after the upgrade

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0-windows</TargetFramework>
    <OutputType>WinExe</OutputType>
    <AssemblyName>NyxSql</AssemblyName>
    <StartupObject>Nyx.Program</StartupObject>
    <ApplicationIcon>Resources\Nyx.ico</ApplicationIcon>
    <SignAssembly>true</SignAssembly>
    <AssemblyOriginatorKeyFile>NyxKey.snk</AssemblyOriginatorKeyFile>
    <TargetZone>LocalIntranet</TargetZone>
    <GenerateManifests>false</GenerateManifests>
    <SignManifests>true</SignManifests>
    <ManifestCertificateThumbprint>37D2B3D67A093A04C499A9FE8A89B1EA7E3532D7</ManifestCertificateThumbprint>
    <ApplicationRevision>0</ApplicationRevision>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <UseWindowsForms>true</UseWindowsForms>
    <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <DocumentationFile>bin\Release\NyxSql.XML</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>none</DebugType>
    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <DocumentationFile>bin\Release\NyxSql.XML</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <OutputPath>bin\x86\Debug\</OutputPath>
    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
    <DocumentationFile>bin\Release\NyxSql.XML</DocumentationFile>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <OutputPath>bin\x86\Release\</OutputPath>
    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
    <DocumentationFile>bin\Release\NyxSql.XML</DocumentationFile>
    <DebugType>
    </DebugType>
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="MySql.Data, Version=5.0.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
      <Private>False</Private>
    </Reference>
    <Reference Include="Npgsql, Version=0.99.3.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>assemblies\Npgsql.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Update="NyxControls\AutoCompletition\AcListBox.cs">
      <SubType>Component</SubType>
    </Compile>
    <Compile Update="NyxControls\PreviewTab.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="NyxControls\ProcedureTab.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="Tools\Connection\ConnectionInput.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="NyxControls\SqlRichTextBox.cs">
      <SubType>Component</SubType>
    </Compile>
    <Compile Update="NyxControls\SqlTab.AutoCompletition.cs">
      <DependentUpon>SqlTab.cs</DependentUpon>
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="NyxControls\TableTab.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="NyxControls\TriggerTab.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="NyxControls\ViewTab.cs">
      <SubType>UserControl</SubType>
    </Compile>
    <Compile Update="NyxControls\SqlTab.cs">
      <SubType>UserControl</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <None Update="Assemblies\Mono.Security.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="Assemblies\MySql.Data.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="Assemblies\Npgsql.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <BaseApplicationManifest Include="Properties\app.manifest" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\NyxSettings\NyxSettings\NyxSettings.csproj" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="NyxMsSql\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="odp.net.managed" Version="121.1.2" />
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
    <PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.346201">
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>
</Project>