Creating a NuGet Metapackage as a MSBuild Project - msbuild

Is there any real way to create a NuGet metapackage as an msbuild .proj instead of directly using a nuspec? I want to do this so I can leverage other MSBuild functionality including PackageVersioning, including content files, etc.
What I mean is that I want to have a simple project for my metapackage (let's say MyMetaPackage.proj:
<Project>
<Import Project="$(MSBuildSDKsPath)\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.0-beta5" PrivateAssets="None" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="3.0.0-beta5" PrivateAssets="None" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.0-beta5" PrivateAssets="None" />
<PackageReference Include="Microsoft.Azure.WebJobs.ServiceBus" Version="3.0.0-beta5" PrivateAssets="None" />
<PackageReference Include="MyOtherPackage" Version="4.5.0" />
<Content PackagePath="readme/$(PackageVersion).txt" Include="readme.txt" />
</ItemGroup>
</Project>
The problem with this is that MyMetaPackage.nupkg ends up having all contentFiles and customs props/targets imported into it that screw it up, even though it's only meant to be a metapackage - those things should only be done for the CONSUMERS of MyMetaPackage.
Adding PrivateAssets to MyMetaPackage.proj isn't at all helpful, because then the nuspec excludes them as well and they won't be passed on to the consumers either.

Related

Azure CI pipeline not putting Razor Class Library static web assets into the correct folder

I'm trying to build a NuGet package that will contain a lot of boilerplate code for an Asp.Net Core web app. As part of this I need to have access to some static web assets (.js, .css files...). When I package the NuGet package on my local PC, the package is created with the static web assets in the correct folder (/staticwebassets/), but when the Azure CI pipeline is run the package is created with the static files in the /content/wwwroot/ folder.
I've tried setting the wwwroot files and folders to both Content and Embedded Resource in Visual Studio and neither seems to make a difference.
Below is a sample of the log output from the Azure DevOps CI log.
2023-02-10T15:49:19.5490937Z Add file 'D:\a\1\s\src\Package.Name\wwwroot\js\site.js' to package as 'content\wwwroot\js\site.js'
For reference, here's the csproj file for the Razor Class Library:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<RootNamespace>Package.Name</RootNamespace>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<GenerateMvcApplicationPartsAssemblyAttributes>true</GenerateMvcApplicationPartsAssemblyAttributes>
<RazorCompileOnBuild>true</RazorCompileOnBuild>
<IncludeRazorContentInPack>false</IncludeRazorContentInPack>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<EnableDefaultRazorGenerateItems>true</EnableDefaultRazorGenerateItems>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="wwwroot\**\*" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<Folder Include="Helpers\" />
<Folder Include="Controllers\" />
<Folder Include="wwwroot\img\" />
<Folder Include="wwwroot\lib\js-cookie\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IronPdf" Version="2023.1.11416" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.8" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.21.1" />
<PackageReference Include="Microsoft.PowerBI.Api" Version="3.17.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="RestSharp" Version="108.0.3" />
<PackageReference Include="Select2.js" Version="4.0.13" />
<PackageReference Include="SendGrid" Version="9.21.0" />
<PackageReference Include="System.Drawing.Common" Version="5.0.3" />
</ItemGroup>
<PropertyGroup>
<StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>
</Project>
I've tried without the StaticWebAssetBasePath property being set as well.
I know we need to update to .Net 6, and we do have a ticket to do this, but I can't do it right now.

Refactor Custom ProblemDetailsFactory

As described and documented here, I like to customize the ProblemDetails hence extended ProblemDetailsFactory class.
However, I want to have this custom implementation to live in .Net Standard shared class library and not in the Web project itself. But I can't do that. It says that the base class ProblemDetailsFactory is not found.
I realized that the version of Microsoft.AspNetCore.Mvc.Core.dll referenced in OOB web application is 3.1 whereas its 2.2.5 in my class library project.
This is what my csproj file looks like:
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
<PackageReference Include="System.Reflection.Metadata" Version="1.8.1" />
</ItemGroup>
Is it something doable or thought through or am I missing something here?
Do not use nuget packages for aspnet stuff anymore
This works for a class library where you want aspnetcore libs available:
Documentation
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

Razor view compilation does not publish AppName.PrecompiledViews.dll

TLDR;
Razor view precompilation on the full framework (net471) only seems to work if the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation nuget package is added directly to the project and not within another package. Does anyone know a way around this?
I have a .net core 2.0 MVC project running on the full framework (net471). According to the docs, in order to perform view precompilation on a full framework app, you need to include the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation nuget package. This seems to work ONLY if you have added the package directly to the MVC project. If you have this package within another nuget package, the AppName.PrecompiledViews.dll never gets published.
I spun up a new .net core MVC project in visual studio running on net471 with the following packages. All works great, the dll shows up and performance indicates the views are compiled correctly:
Packages Used for Reference:
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Session" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.2" />
I next created a class library, added the same packages and bundled it in a nuget package (let's call it CommonLib). I created a second .net core 2.0 MVC project running on net471 but instead included the CommonLib nuget package. Everything runs normally, except on publish there is no AppName.PrecompiledViews.dll:
If I then add just the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation package to directly to the project with the CommonLib package, the PrecompiledViews.dll shows up:
I am trying to create a common class library project that contains dependencies for my projects (including .net core components) to simplify upgrades across all common micro projects. Has anyone had luck with doing this?
In order for Razor view compilation to run, you need to include special MSBuild targets that will automatically run as part of your project’s build process. These tasks are included in the Microsoft.AspNetCore.Razor.ViewCompilation package.
Currently, the only way to expose additional MSBuild targets with NuGet is by explicitly referencing the package. There is no transitive property with build targets, so you will always have to explicitly reference the package in order to activate those targets for your project.
I just found this issue on GitHub which suggests that build targets already flow transitively to the top project, but I actually haven’t found a way to trigger this behavior.

No dotnet-cli excutable matched when placing <DotNetCliToolReference/> in <Choose/>&<When/> tags of .csproj file

I am migrating my web application from .Net Core 1.1 to 2.0, and has tried to make it more compatible by ensuring it works both under 1.1 and 2.0.
When it comes to making the project packages automatically adapt to the current switched version, I used <Choose/> and <When/> tags in .csproj file like this:
<Choose>
<When Condition="'$(TargetFramework)' == 'netcoreapp1.1'">
<ItemGroup>
<PackageReference Include="..." Version="1.1.2" />
<!-- Some package references -->
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.1.0-preview4-final" />
</ItemGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>
</When>
</Choose>
This works fine with <PackageReference/>s, with application well compiled and run under specified $(TargetFramework).
However, the dotnet cli tools seems to be "missing" from the project by this action. After executing dotnet restore command, I tried dotnet ef database udpate command, end up receiving this message:
No executable found matching command "dotnet-ef"
Yet when I took the <DotNetCliToolReference/>s out of <Choose></Choose> tag and run dotnet restore, everything behaved well as before.
So, What's the matter with these tags when running in dotnet-cli? Is there anything I can do to make my dotnet-cli ItemGroup automatically changes according to $(TargetFramework)?
DotNetCliToolReference's are independent of the target framework(s) in the csproj file. You can only have one version of Microsoft.EntityFrameworkCore.Tools.DotNet per csproj file, and it can't be conditionally included. Remove the Choose/When to make dotnet-ef work.

Installed NuGet package, Visual Studio claims assembly not referenced

you can see that I have referenced it through nuget, but is still complaining. This is in a .net 4.6.1 framework class library in an embedded view component.
I'm also using a .net framework asp.net core web app.
I'm having a bunch of issues trying to get razor to work, but this one is a new one. MenuViewPage inherits RazorPage and is located in another assembly.
I think I should just install .net core 2, and aspnetcore.all ;)\
Anyone have any ideas why this is happening?
So after hours of trying to sort this issue out I've come to a solution:
When creating a web class library, whether you are using it for application parts or you are creating your core project with base classes I advise you covert it from a normal .net class library to a web enabled one.
To convert it to a web class library you need to change the project to use the following .csproj, then make sure to run dotnet restore.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<PreserveCompilationContext>true</PreserveCompilationContext>
<ApplicationIcon />
<OutputTypeEx>library</OutputTypeEx>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile></DocumentationFile>
<NoWarn>1701;1702;1705;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Session" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Razor">
<Version>1.1.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Razor.Runtime">
<Version>1.1.2</Version>
</PackageReference>
<PackageReference Include="System.Net.Http" Version="4.3.2" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
</ItemGroup>
</Project>
Make sure you are making the output type a library.
I ran into issues with the assembly info file, it seems to be generated during build now, so I commented out the assembly.info stuff by double clicking "Properties"
I hope this helps someone in the future.