Nuget package copy across projects - .net-core

Is Nuget package copy feasible in .Net Core?
I'm worried since, there is neither project.json nor package.config. Does it mean manually editing .csproj is the only way to go forward.
There has to be more efficient way, IMHO. Am I missing something.

I use a shared Directory.Build.props file to build same packages across multiple projects for .NET Core 2.0. So if you put this file in a shared folder for all your projects and simply import it after you create a new project, it does save a lot of time.
First create a shared Directory.Build.props file. Below I am adding NLog package for all my projects. Sample content for file:
<Project>
<ItemGroup>
<PackageReference Include="NLog" Version="4.5.6" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.5.4" />
</ItemGroup>
</Project>
Now import this file to root of your projects by right clicking the project 1 > Add > Existing Item > Directory.Build.props. Repeat the same for your other projects; project 2, project 3, etc. Notice that when you add the file each to your projects; NLog packages from Directory.Build.props file is automatically added as Nuget package.
Simply edit the XML and more package references under <ItemGroup></ItemGroup> for your packages. I hope this will be more efficient solution for you. It certainly saves me lot of time for new .NET Core projects. You can read more about customising build here.

Related

How to use my own DLLs instead of the one referenced by a dependent package

I'm using a nuget package (let's call it A) which has dependency to another package, let's call it B.
To include A in my project, I changed .csproj file to:
<ItemGroup>
<PackageReference Include="A" Version="2.0.5" />
</ItemGroup>
When I run nuget restore package B is consumed from some nuget source too.
I want to replace dlls of package B with my own DLLs, I've created myself.
I can do it on my local machine by just copy pasting the desired dlls in bin folder. But how can I do the same on Azure Websites? Is there anyway to automate this process?
Is there any way to tell nuget not to fetch DLLs of B from nuget source and instead use my desired ones?
Update:
Thanks to Shahryar's contribution, we can also choose to add the dll file and set it to be copied to the compilation folder for implementation (define properties in the .csproj file).
In fact, it is mainly to change the content of final compiled files, because after the final deployment, it runs according to the compiled files.
Original Answer:
You can compile the web app locally first, and then replace your dll file with the corresponding file in bin. Use zip to package the entire compiled file, and then use zip deployment to directly upload the final compiled file to Azure (the operation of the web app deployed to Azure depends on the file uploaded in this way)
Have a look of Zip Deploy.

Including Unmanaged DLL in NuGet Package Using csproj

I'm developing a .NET Core 2.1 library that depends on an unmanaged DLL. I'd like to include the unmanaged DLL in the NuGet package as well. The problem that I am running into is that if I try to specify all of the information in the .csproj file, the dotnet build process throws the following warning:
warning NU5100: The assembly 'content\lib\subdir\somedll.dll' is not
inside the 'lib' folder and hence it won't be added as a reference
when the package is installed into a project. Move it into the
'lib' folder if it needs to be referenced.
I know that I can embed the unmanaged DLLs by writing a .nuspec (in fact, I have). However, it seems like I shouldn't need to write one with the latest .csproj file format.
Question: How can I use the .csproj file to embed unmanaged DLLs in a NuGet package?
Specifying <ItemGroup><None> in the .csproj file seems to include the files in the output directory but they do not make it into the NuGet package.
Specifying <ItemGroup><Content> in t he .csproj file will get them added to the NuGet package but in the Content directory instead of in the Lib directory.
If I really have to have both a .csproj file and a .nuspec file, what is the best practice for where to put the metadata? In t he .csproj file? In the .nuspec file? Maintain and sync both? Is there a something in the tool chain that can do this for me?
I'm working in Visual Studio Code V1.24, and .NET Core/dotnet V2.1.
You need to specify explicit package path metadata on the element so that the dll/so/dylib file ends up at the right place in the package so that it is recognised as runtime-specific native DLL:
<ItemGroup>
<None Include="unmanaged.dll" Pack="true" PackagePath="runtimes\win-x64\native" />
</ItemGroup>

Adding reference to another project from visual studio code

If a library (eg, on github) doesn't distribute itself via a nuget package, I'd have to manually include it as a reference, correct? I see a lot of reference posts for how to add a reference to a project for Visual Studio, but I can't seem to figure out how to do it on Visual Studio Code.
In this case, I've downloaded the library's zip, and moved the expanded folder into my project, and then tried using <namespace>, which did not work.
EDIT:
I noticed that this downloaded zip contained a .nuspec. Is there something I can do with this file extension to import it in my project?
Let's say you have two projects:
1) Project1.Api
2) Project2.Executable
Command line syntax for dotnet add reference:
cd Project2.Executable
dotnet add reference ../Project1.Api/Project1.Api.csproj
If you check the Project2.Executable.csproj file, you will see the following entry:
<ItemGroup>
<ProjectReference Include = "..\Project1.Api\Project1.Api.csproj" />
</ItemGroup>
Add "vscode-solution-explorer" Extension. It will folder structure as visual studio.
Right click on project --> Add Reference --> Select the reference project from the list.
You can open .csproj file of the project you want to add reference to and add project reference like this:
<ItemGroup>
<ProjectReference Include = "<RELATIVE_PATH_TO_REFERENCE_PROJECT>" />
</ItemGroup>
If the ItemGroup for ProjectReference already exist then you can just add to it.
Example:
<ItemGroup>
<ProjectReference Include = "../MyLibrary.csproj" />
</ItemGroup>
In visual studio, in the solution explorer, expand the project that will reference this other library. You will see "References", right click and choose "Add". Then choose browse on the left. Find your dll in your file system. If vs can't find the library you may need to unzip it. I've read where you may need to copy the dll into the bin folders, I recommend trying it without doing that, then copying it in to them if it fails without them.
Btw Googling "visual studio add reference" comes up with A LOT of great results.

Force external files to be copied to bin folder on publish

I have a web application project that references a third party assembly, which in turn uses some native dlls that it needs to find at runtime.
Because of that, I wanted to add these dlls to the bin folder of the project, so that they can definitely be found.
However, if I add the files to the project in /bin/, select "copy to output", the files are compiled and published into /bin/bin. Adding them to the root folder works, but can hardly be the right solution.
Adding them to the build target "AfterBuild" has no effect when publishing (e.g. "build deployment package")
It also has to work when building the solution via TFS, where the MSBuild target _CopyWebApplicationLegacy is invoked.
The solution was a combination of the things I had tried already:
Include the "Bin" folder in the project
Add the needed files (I added them as a link due to our development structure)
Set the following properties: "Build Action = Content" and "Copy to Output = Do Not Copy"
The files are now copied to the bin folder when publishing, even when automating the builds on TFS.
The component that needed this was GdPicture, which uses a couple of native DLLs during runtime.
It's common to have a lib folder in either your solution or workspace to put your third party dlls within. You would then add a reference to this location from your project and ensure this location is under source control.
You could also look at using NuGet to package this for you, which uses a solution level packages folder automatically.
Based on this article http://sedodream.com/2010/05/01/WebDeploymentToolMSDeployBuildPackageIncludingExtraFilesOrExcludingSpecificFiles.aspx. It's possible to define the msbuild target into main (lastest in order of solution's build) project file that will capture all files of the bin folder. Like this
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="$(OutDir)\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>$(OutDir)\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
And place it before closing root project element.

MSDeploy Package has Missing Files

I'm using MSBuild to build a web application project and adding parameters to create the package file. All of that is good. I get two folders in the _PublishedWebSites output:
AppName
AppName_Package
In the ApplicationName folder, the entire site is there and I can simply copy this folder over to the website and it will run.
In the Package folder I've got the expected 5 files:
AppName.deploy.cmd
AppName.-readme.txt
AppName.SetParameters.xml
AppName.SourceManifest.xml
AppName.zip
When deploying the package however, the web application dll (AppName.dll) is missing, as are a few other important referenced dependencies.
Inspecting the package itself does reveal that the files are in fact missing from the web applications bin directory.
This is very odd, considering the files are all in the root AppName folder, but not in the package found in AppName_Package folder.
The only MSDeploy related modification I've made is that I am overriding the CopyAllFilesToSingleFolderForPackageDependsOn target to copy in some handlers from a library project, and this all works nicely.
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\Libraries\CodeLibrary1\**\*.ashx" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>$(ProjectDir)%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
So, I'm not able to determine why the web application's DLL, and only a few other (referenced)DLLs are removed from the bin directory during the package creation process (but not all - maybe 3%).
Any ideas what I should be looking for in the log file?
EDIT: (Response to Sayed):
I truly appreciate you answering my post. Unfortunately I’m not sure we are on the same page. Like I said, I might not have explained my problem well enough to actually clue others in on exactly what my issue is. Let me try once more to clarify
Getting external files copied into my web application was not the problem. I understand that scanning over my post and seeing the all too common “CopyAllFilesToSingleFolderForPackageDependsOn” element set off a few red flags, alarms, bells and whisles. . It seems to be a common thing people are struggling with, and as you point out, there have been some issues with it being executed. That worked OK for me.
My problem has more to do with project referenced DLLs, AND most importantly the application DLL itself not being copied.
More tweaking around today has revealed something I was not aware of. For instance:
Kicking off a Build on TFS outputs a couple things:
The source from TFS is output to the Source Directory (SourceDir)
This only contains the output what is checked into TFS
This does not include project or file references, only what is committed in TFS
The output of the build is into two folders
Binaries (includes project and file references)
Sources (only what is included/committed in TFS)
Inside Binaries I find the _publishedWebsites folder, as well as all project and file references, while inside Sources there are just the files that are checked into TFS.
My problem, or confusion, was thinking that when I pass in the following parameters to MSBuild Arguments, it would take the output from the build (_PublishedWebsites) and use those files to create the package. It does not do that.
The actual process builds a package based on the files in the SOURCES folder. So, here is my dilemma/confusion, because I did not commit my application dll into source, it was not being included in the package, and therefore was not being sent off to the test site on the test server.
/p:DeployOnBuild=True /p:DeployTarget=MsDeployPublish /p:CreatePackageOnPublish=True /p:MSDeployPublishMethod=RemoteAgent /p:MSDeployServiceUrl=http://<mytestsite> /p:DeployIisAppPath="<AppName>" /p:UserName=<domain\user> /p:Password=<mypassword> /p:SkipExtraFilesOnServer=false /p:AllowUntrustedCertificate=True
To wrap this up, once I “checkout for edit” my application DLL on my dev machine, and them compile the solution, and finally commit the application DLL to source control, then it is included in the package because it is included as just another source item.
So, I guess this becomes my fault for not understanding how to get the output of the TFS BUILD into the sources folder, and get that included into the package used by msdeploy.
There is probably something very fundamental that I missed or just skimmed over - and not understood, that the package creation is from the Sources folder and not the _PublishedWebsites folder. Nor do I understand how to get the MSBuild compiled application dll, and project referenced dlls, into my package – replacing the committed source items in source control.
I hope this isn’t a complete waste of your time because I missed a
source=<some-parameter>
somewhere.
I appreciate it you can direct me to any existing sources out that already explain this to where I should be able to get my head around it and get this working. Or if it’s so easy to just tell me here.
The issue here is that the CopyAllFilesToSingleFolderForPackage target itself is not getting called from the VS2012 targets. We made a lot of changes and this may be a regression on our side. I will look into this to see if there is anything that we can do. Fortunately it should be pretty straight forward to update this to get the behavior that you are looking for. Instead of using CopyAllFilesToSingleFolderForPackageDependsOn you should be able to use PipelineCollectFilesPhaseDependsOn as an alternative. You should be able to change what you have above to
<PropertyGroup>
<PipelineCollectFilesPhaseDependsOn>
CustomCollectFiles;
$(PipelineCollectFilesPhaseDependsOn);
</PipelineCollectFilesPhaseDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<Message Text="Inside of CustomCollectFiles" Importance="high"/>
<ItemGroup>
<_CustomFiles Include="C:\Temp\_NET\WAP-AfterPublish\MvcApplication1\additional files\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>additional files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
I just tried this for both VS2012 as well as VS2010 so this seems like a better to solution then the CopyAllFilesToSingleFolderForPackageDependsOn approach. Can you try that out and let me know what you find out?

Resources