I have build NuGet package consisting of Razor Class Library (RCL) project at .net core 2.2. Once packed I see that it contains static assets that I have configured:
When I install package inside target project, assets refs are visible inside project structure:
But when I try to access them at runtime - i get 404:
https://localhost:44312/localizer-assets/lib/vue/vue.min.js
I see that those files are not "physically" placed inside wwwroot folder (they are iniside package folder).
Is there any way to serve those files? How this should be configured?
So far I have been using those approches:
https://www.learnrazorpages.com/advanced/razor-class-library
Can Razor Class Library pack static files (js, css etc) too?
They work fine when I directly reference RCL project, but when packed with NuGet and installed does not work any more.
They work fine when I directly reference RCL project, but when packed
with NuGet and installed does not work any more.
As far as l know, when you use nuget and choose PackageReference nuget management foramt, the files which targets to import into the main project are introduced into your main project as links(The corresponding files will not exist in the physical path of your solution , but will be linked to the corresponding file address in the %userprofile%\.nuget\xxx). It is the feature of PackageReference nuget management format.
Solution
To solve it, l think you can add a custom build target in the nuget project(Include MSBuild props and targets in a package). With it, you can copy the files from nuget package into the main project.
1.add a target file like .targets or .props(must be the same as the package id) into the \build folder(must be created under the project root directory) of the project. All of these are based on nuget packaging mechanism.
2.add these codes into the target file
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SourceScriptFiles Include="$(MSBuildThisFileDirectory)..\content\xxxx(relative paths in the current project)" />
</ItemGroup>
<Target Name="CopyScriptsToProject" BeforeTargets="Build">
<Copy SourceFiles="#(SourceScriptFiles)" DestinationFolder="$(ProjectDir)\wwwroot\xxxx\"
/>
</Target>
</Project>
Use a target to copy the file #(SourceScriptFiles) into the main project.(The DestinationFolder is just the destination address).
3.If you use nuspec file to pack your package. You should also add these files under the files node in it.
<files>
<!-- Include everything in \build -->
<file src="build\**" target="build" />
<!-- Other files -->
<!-- ... -->
</files>
In addition, such operation is a pre-build event and when you install the package, you should build your project first and then you will find the file under the destination folder.
Besides, here is a good sample in the github and l hope it can give detailed information and steps.
Hope it could help you.
Related
I have .NET452 project - lets call it Consumer.csproj that I want to consume nuget lets call it SharedTargets that contained some custom targets files (SharedTargets.targets) from msbuild.
I'm using PackageReference format and now (compared to what it used to be) nuget packages are being restored to shared folder (%userprofile%.nuget\packages), and I'm not sure if it is good idea to reference it via that (doesn't feel right).
Eg:
<PackageReference Include="SharedTargets">
<Version>1.0</Version>
</PackageReference>
<Import
Project="$(USERPROFILE)\.nuget\packages\SharedTargets\1.0\SharedTargets.targets"
/>
Also this works only in VS, running this from command line (msbuild) I'm getting chicken-egg problem:
Confirm that the path in the <Import> declaration is correct, and that
the file exists on disk.
Obviously since I need to restore nuget first before I can use it :)
So question:
is there some more elegant way how to resolve path to the nuget package inside project file
is there a way how to make msbuild succeed (i.e. restore packages before SharedTargets.target is imported)
You shouldn't try to manually import targets distributed via NuGet.
Put your .targets file inside a build subfolder inside the package and name it SharedTargets.targets (package id + .targets) and NuGet will automatically include the targets - for packages.config projects it will modify the project file on install and for PackageReference projects the targets will be imported by modifying an implicitly generated targets file in the obj\ directory.
I am creating nuget package which should contain also config file. Problem is that if I want to use csproj for nuget package definition, I don't know how to specify that config file should be copied and "copy to output directory" on file set when package is being installed.
https://learn.microsoft.com/en-us/nuget/guides/create-net-standard-packages-vs2017
Previously I used nuspec and for install.ps1.
Thanks
(https://learn.microsoft.com/en-us/nuget/guides/create-net-standard-packages-vs2017)
To include a file, you need to add / modify an update item for the file. If you have set "copy to output directory" to "preserve newest", you might already have one in the csproj file. To include this file into the resulting nuget package, you need to set the Pack="true" metadata:
<ItemGroup>
<None Update="config.txt" CopyToOutputDirectory="PreserveNewest" Pack="true" />
</ItemGroup>
Note that depending on your project type (=> web sdk or "normal" sdk is being used) you may see different item types (None, Content) for files.
I have a solution composed with different projects from different path. We use foundation projects from a vanilla folder and then project specific projects from specific directory. Example:
specific project directory: c:\proj\specific
vanilla project directory: c:\proj\vanilla
vanilla project x path: c:\proj\vanilla\repo\src\project\x\code\
In each vanilla project we have a publish profile that points to the root directory and includes a publishsettings.targets file that has the actual target where the project should be published. By using this structure we can have a lot of projects and publish them using a single target so we don't need to change that target in all projects.
We discovered now that we have a problem when using these vanilla projects as the path used in publish profile is relative to vanilla directory and actually we need it to be relative to the specific project directory (solution directory).
In our publish profile we have:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\..\..\publishsettings.targets" />
<PropertyGroup>
...
</PropertyGroup>
</Project>
So we need a way to specify the actual sln directory to this path so we can include the correct target so when we do the publish from visual studio it will publish to the specific project and not vanilla one.
I tried finding a "MSBuildSolutionDirectory" but it only seems to be a "MSBuildProjectDirectory" variable that can be used.
Does anyone knows a way I could get the path
Project="c:\proj\vanilla\publishsettings.targets"
to actually be
Project="c:\proj\specific\publishsettings.targets"
by using some msbuild or custom variable and not hardcoding it?
I need it to work both with vanilla (as I have a vanilla.sln) and also with specific project (as I have a X.sln).
Here is a way to make your own version of the MSBuildSolutionDirectory you were hoping to see built in:
<PropertyGroup>
<SolutionDirectory>$([MSBuild]::GetDirectoryNameOfFileAbove(`$(MSBuildProjectDirectory)`, `YOUR_SOLUTION_NAME.sln`))\</SolutionDirectory>
</PropertyGroup>
Notes on the GetDirectoryNameOfFileAbove MSBuild property function:
From http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx:
$([MSBuild]::GetDirectoryNameOfFileAbove(directory, filename) Looks
in the designated directory, then progressively in the parent
directories until it finds the file provided or hits the root. Then it
returns the path to that root.
From my own testing:
The returned path does not include a trailing backslash.
If the filename is not found, an empty string is returned.
I am deploying my packages using teamcity and octopus. I am creating packages using teamcity and then using Octopus to deploy to different environments. I have a Resources folder which needs to be copied as a separate step in teamcity. Now I want that folder to be included in the package so I can then deploy that package to remote servers on other domains. I have defined the following file to include resources folder into the content folder of main project. but what's happening is It just create a folder in the destination but don't copy other files with in the project. Please guide as All I want is to include the resources folder with in the package along with my publish website files. I just want the resources folder to be part of package. Please guide
<?xml version="1.0" ?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Services</id>
<version>1.0.0.0</version>
<authors></authors>
<owners></owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Services.nuspec build package</description>
<releaseNotes />
</metadata>
<files>
<file src="..\Resources\**\*.*" target="Content\Resources" />
</files>
</package>
Package contents after creating a package using the above code:-
. _rels
. package
. content\resources
. [content_type
. Services.nuspec
If you're using OctoPack, this behaviour is expected. To quote the documentation on GitHub:
If the <files> section exists, OctoPack won't attempt to automatically add any extra files to your package, so you'll need to be explicit about which files you want to include.
If you go this route, you'll need to specify all the other files you want included within the <files> section of the nuspec.
If you're not using OctoPack, a similar rule applies. See documentation on nuget.org
If you follow the conventions described in Creating a Package, you do not have to explicitly specify a list of files in the .nuspec file. Note that if you specify any files, the conventions are ignored and only the files listed in the .nuspec file are included in the package.
Update
One hybrid method I've seen used is to use the MSBuild Publish target to build & publish the website to a local folder, (to filter out all the compile time files like .cs source), drop in the additional files, and then simply include a <file src="**/*.*" /> to pack everything under the root publish folder. Requires a bit of customisation with root paths / nuget.exe, but it may make the process it a bit neater and slightly less maintenance.
Useful information here that may help you get started.
I'm in the process of creating a web deployment package through an automatic build trigger on the server.
The package should take care of everything (including creation of a specific website, apppool, and the latest code) on any server desired.
I extracted manually a deploy package from a configured local IIS site, containing all information needed by MsDeploy to create the site, apppool, etc...
They are present in following files
archive.xml
parameters.xml
systeminfo.xml
The idea is now that I would create automatic a deploy package on the build server, that contains the new compiled code, but with the above xml files in the .zip package.
Right now, I'm building the application, after which I execute a PowerShell script that will manually overwrite the files in the .zip with the ones I have.
However, I know you can extend the Target file (with a .wpp.targets file in your project) to plug into the pipeline and modify things along the way.
Unfortunately I'm getting a little lost with the information I found.
I'd like to:
1) configure the creation of the deployment package to use my existing .xml files.
2) if that's not possible, overwrite the files with my own files after the package creation.
My goal is to have a full executable deploy package after the build is finished, so I won't need to PowerShell script anymore.
Any information that will point me closer to a solution or helps me to understand more clearly msbuild targets and/or webdeploy is very appreciated.
I managed doing this by extending the Package MsBuild target.
Adding a .wpp.targets file in the root of the web project with following content.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSBuild.ExtensionPack.4.0\MSBuild.ExtensionPack.tasks"/>
<PropertyGroup>
<DeployFilesDirectory>$(MSBuildProjectDirectory)\Deploy\</DeployFilesDirectory>
</PropertyGroup>
<PropertyGroup>
<OnAfterPackageUsingManifest>
$(OnAfterPackageUsingManifest);
CopyDeployFiles;
ReplaceSetParametersFile;
<!--ZipDeploymentFiles;-->
</OnAfterPackageUsingManifest>
</PropertyGroup>
<Target Name="CopyDeployFiles">
<Message Text="Copy Deploy Files"></Message>
<ItemGroup>
<Files Include="$(DeployFilesDirectory)*.xml" Exclude="$(DeployFilesDirectory)setParameters.xml"></Files>
</ItemGroup>
<MSBuild.ExtensionPack.Compression.Zip TaskAction="AddFiles"
CompressFiles="#(Files)"
ZipFileName="$(PackageFileName)"
RemoveRoot="$(DeployFilesDirectory)"/>
</Target>
<Target Name="ReplaceSetParametersFile" DependsOnTargets="GenerateSampleDeployScript">
<Message Text="Replace Default SetParameters File"></Message>
<Copy DestinationFiles="$(GenerateSampleParametersValueLocationDefault)"
SourceFiles="$(DeployFilesDirectory)setParameters.xml"></Copy>
</Target>
</Project>
The first target is executed after MsDeploy has created the package and will replace the .xml files within the .zip file. I'm using the MsBuild.ExtensionPack Zip support.
The second target is executed after the build has created the sample .cmd and setParameters files and will overwrite the setParameters.xml with my own as well.
It takes a while to understand the concepts of MsBuild targets etc, but once you understand it becomes indeed very powerful.
Creating the package is now as simple as just launching the MsBuild
msbuild "D:\Projects\MyWebProject.csproj" /T:Package /P:Configuration=Release;Platform="AnyCPU";PackageLocation="D:\DeployPackage\package.zip";PublishProfile=MyProfile
And deploying is the same as before
package.deploy.cmd /Y –setParamFile :myParameterFile.xml
Assuming your paths stay the same, you can achieve this by specifying the existing zip as your -dest:package=package.zip. MSDeploy will automatically overwrite the files inside the zip.