Include un-referenced projects into nuget package - visual-studio

I'm having issues creating a nuget package for a repo I've recently taken over (with no helpful input from the previous owner). The problem I'm having, is the VS nuget package creation doesn't seem to have any clear way to include other projects into the package. The way the package was built previously, was there's a base nuget package (package), that also included several other dlls from package.iOS, package.Droid, etc... But I can't figure out how to built it that way. The only other solution I can think of (which if I'm reading the nuget documentation on Microsoft correctly, it's the more correct way) is to create a separate nuget package for each of the projects, instead of including them all in the base package.
Please advise.
I am fully comfortable with creating multiple more specific nuget packages, but the people using this library are used to only downloading the base one, and it having everything they need.
I've looked into the documentation, and as far as I was able to tell, I could include referenced projects, but the base project doesn't rely on any of the other ones.
Just for reference, the project structure is similar to:
project
project.forms
project.iOS
project.Droid
project.macOS
project.Uwp
Where previous versions of the nuget built from project also included project.iOS, project.Droid, project.macOS, and project.Uwp, which in turn, depend on project.
Logically, to me, it seems that each of the project.{}s should probably have their own package, as they all may not be needed in someone's utilization of the package. Just wanted to see if there was an easy way to continue existing patterns without a load of work.
Scratch that
Turns out I can't make individual packages out of the project.{} projects through VS.

Okay, found it, just had to make a .nuspec file, and reference that file in the nuget pack command.
In the .nuspec file, you need a <files> node with a <file src="...thing.dll" target="lib\..." /> for each of the dll's you're needing in your project. Simple as that. Just wish there were a way to do it in the VS interface, instead of having to use a .nuspec file.

Related

How to properly reference a library in nuget-based architecture

I'm trying to create couple nuget packages for internal company use:
OurCompany.Infrastructure.Logging.Interfaces and just OurCompany.Infrastructure.Logging.
So I created two class library projects in the same solution, provided an implementation for OurCompany.Infrastructure.Logging.Interfaces and created a package.
Now I have a question: how to properly reference the OurCompany.Infrastructure.Logging.Interfaces library in OurCompany.Infrastructure.Logging project?
Should I add it as a nuget package or simply add as a project reference?
There is no perfect solution.
When you use a NuGet package but need to make a change in the library while working on an app that uses it, you need to make the change in the library, publish a new version of the package, update your reference in your app, then hope the change you made in the library worked as needed. Particularly when working on a new feature this is very slow because your software design often changes multiple times between when you first start to when you finish, and debugging is more difficult. If your company doesn't have tooling to check for updates and remind teams that updates are available, then you can get into a fragmentation situation with some teams still using very old versions of the library and if they try to upgrade their app breaks and need extra time to adapt to the breaking changes in the shaed library.
On the other hand, if you use project references, debugging and implementing new features is easier, and breaking changes are detected immeidately, assuming you have adequite automated tests, but it requires all the code to be in the same repository, or to look like it does (maybe using git submodules, or have a convention where multiple repos are always clonsed in the same relative path).
Both Google and Microsoft had to implement their own source control system tools to deal with massive repos that are too big for a single developer machine to work with, plus speed up compile times both of dev boxes and on CI agents, because you don't want changing 1 line of code in one app causing every single app the company has being rebuilt and tested. But unless your company wants to dedicate engineers to working on the build system and not contributing to customer applications, this is infeasible.
So, the submodule, or multiple-repos with relative path conventions sounds appealing, but it still requires the library to be recompiled on every CI build that uses the library. Not a big deal, but if the frequency of changing the shared library is very low, there's little benefit to making code changes to the library easy. Plus when someone else updates the library, how will you know that you need to update the submodule? The NuGet tooling is probably better for checking for updates and actually updating.
Personally, I always use project references references for projects that are already in the same solution and nuget references for everything else. What I've done in the past is when I need to either bug fix or add a new feature to the packaged library, I clone both repos side, temporarily add the library's project(s) to my app's solution and change the nuget references to project references. Then I develop as if they're all in one repo. Finally, I need to manually undo the solution/project reference changes and increment the package reference version number before check in. Since it's manual it sometimes goes wrong. But it's the best balance I've found so far. You need to decide on what's best for yor own situation.
The best solution is: Do Both!
With the Choose directive, you can set conditional referencing:
<Choose>
<When Condition="'$(Configuration)'=='Debug'">
<ItemGroup>
<ProjectReference Include="Path\To\Your.Awesome.Package.csproj" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="Your.Awesome.Package" Version="1.0.0" />
</ItemGroup>
</Otherwise>
</Choose>
In this example, your project will use the direct project reference while running in Debug mode, then, the rest of the time it will use the NuGet package reference.
Even though you are still responsible for maintaining the proper NuGet package version, nothing is perfect.
I hope this would help somebody.

How to add TypeScript Definitions to .NET Core Nuget Packages

We have an internal NuGet Package that consists of some .NET Code and a TypeScript Definition File (*.d.ts). This is the content of the package:
After installing the package into a new .NET Core project, the folder structure in the solution explorer looks like this.
So far, everything went as expected. But note the small arrow symbols on the "i18n" folder and the "Index.d.ts" file. It looks like they're just links to the actual file. When I click on the d.ts file the content seems correct. But Visual Studio fails to recognize the declarations in it, so I can't use it in my TypeScripts.
One idea was to include the path to the packages in the tsconfig.json, but that can't be the solution... Any other ideas how to do that?
How to add TypeScript Definitions to .NET Core Nuget Packages
As far as I know, Definitely Typed packages are not compatible with .NET Core projects. That because the script files should be included in <contentFiles> element. You can refer to the Including content files for more detail info.
Besides, just as Martin comment, npm is the recommended method of installing Definitely Typed packages:
https://github.com/DefinitelyTyped/DefinitelyTyped#how-do-i-get-them
So, after seeing the replies here and not giving up, I have to put in my approach to this.
As I'm working on a large solution with over 100 subprojects - many of them fast moving NuGets, I couldn't give up. I wanted to have my .NET object models including their interface/class representations in TS, being able to have both imported by including one NuGet (and thereby reduce dependency hell a little bit). I have to mention, I tested this only with my own object model, which has no external dependencies - and I tested only on VS2022.
But in this restricted scenario it works without any issues.
On the project containing the TS definitions
Set the build action for the ts definitions you need to be included in the NuGet to "content". This will include them into the NuGet package.
On the consumer side
Adjust your package reference, add the following property/value:
<GeneratePathProperty>True</GeneratePathProperty>
This will create an MsBuild property/variable referencing the path to the local presence of the restored NuGet file (important if your building on multiple, different machines - like on CI pipelines, build servers etc.) and allowing you to avoid any hardcoded absolute paths.
The generated property has the following format
$(Pkg<PackageNameWithDotsBeingReplacedByUnderlines>)
So a package named "MyPackage.Hello" would result in the variable $(PkgMyPackage_Hello)
Now we create a new build target to copy the files from the restored package's contentfiles folder (as it's restored, and we have the restored and thereby extracted path, we can finally target them).
<Target Name="CopyImportedTypes" BeforeTargets="Build">
<ItemGroup>
<TsTypesToCopy Include="$(PkgMyPackage_Hello)\contentFiles\any\net6.0-windows10.0.20348\*.ts" />
</ItemGroup>
<Copy SourceFiles="#(TsTypesToCopy)" DestinationFolder="$(MSBuildProjectDirectory)\AnyProjectSubFolderIfDesired" SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" />
</Target>
Make sure to adjust the "Include" path to your package (TFM, Platform etc.). An easy way to get the relative path is to open up the solution explorer, expand your consuming project, expand dependencies and then packages, expand the package with your ts definitions and open up the properties of the contentfiles.
This target is being executed before the actual build (so we can use the imported types on the build being happening right this moment) (BeforeTargets property). The ItemGroup is nothing else than a definition of items (in our case, source files) we want to use, being stored into #(TsTypesToCopy) which is being used by the copy task.
Thankfully, VS does automatically set new files to the right build action (in most cases), so the brand new ts files should be in the right mode automatically - so we don't have to tweak anything manually.

.Net Core project keeps referencing other project instead of Nuget package of same name

I seem to be having the same problem as this unanswered question.
NOTE: Ordinarily, I'd avoid the repost, but the lack of an answer and the low traffic seemed to warrant a refresh into the SO feed.
The setup
Create two .Net Core projects (A & B) in two separate solutions in the same folder. From A, create a Nuget package. (You can upload it to Nuget, MyGet, or just keep locally. Just make sure the source is configured.)
In B, add the Nuget package.
The result
Project A has now been added to the solution for Project B.
The questions
Why is this happening?
How can I get VS to recognize that it should be referencing the Nuget package, not the project?
Other stuff
I'm running VS 2015 Pro Update 3 on Windows 10.
In my real scenario, my Nuget package is at a later version. When I open the project.json file, I get a compiler warning on the ProjectA dependency that says I'm depending on version 1.1, but version 1.0 is found.
I've created an example on GitHub for you to play around with.
You must place the solutions into separate directories as .NET Core Projects in VS2015 has unique file system requirements, and will behave poorly when you put them in the same directory (each solution will generate a hidden .vs folder, and they will end up overlapping).
For example you could change the directory structure to this:
.\Solutions\A\ <-- Directory for Solution A
.\Solutions\B\ <-- Directory for Solution B
.\A\ <-- Project A
.\B\ <-- Project B
This would mean that the hidden .vs folders for each solution will no longer overlap (ie, the solutions do not share this)
.\Solutions\A\ProjectA.sln
.\Solutions\A\global.json
.\Solutions\A\.vs\
.\Solutions\B\ProjectB.sln
.\Solutions\B\global.json
.\Solutions\B\.vs\
Local projects take precedence over NuGet packages. I don't know at what level this is baked-in, though.
The solution is to explicitly specify in your project.json that you want to reference a NuGet package and not the project in the same solution.
"YourNuGetPackageName": {
"target": "package",
"version": "VersionOfYourNuGetPackage"
}
You can have a look at an example here.

How to add AngularJS with different modules to a Visual Studio project?

So far I thought that using Nuget to add the AngularJS modules is the way to go. But nuget adds the packages to whatever directory it is configured to. For example it adds the angularjs.core package to my main Scripts folder. It adds the angular-ui-router module again to my Scripts folder. But the angular-ui-bootstrap module is added to Scripts\angular-ui. If I am to use Nuget and keep the packages up to date, etc. I need to stick with this, which is inconsistent. Not to speak that I want to have all my angularjs scripts in a Scripts/vendors folder.
Can I somehow work around this problem or just ditch Nuget for this?

ASP.NET MVC folder structure and NuGet

I want a custom directory structure for my Content in my MVC project for example:
\Content
--\js
--\css
--\img
Is it possible to tell a NuGet package to install scripts in the Content\js folder? For example the jQuery package so that the jquery-1.6.js file is installed in the Content\js folder?
A workaround is to use the Nuget Package Explorer and download the package you want into that. You can then edit the folders within the package using Package Explorer to suit your taste and save it into your own Nuget repository. This can be a file system folder or you can get more sophisticated here: Hosting Your Own NuGet Feeds.
Of course this means that you have to keep the packages in your private repository up to date. Clearly if you have a lot of packages to deal with this could become a problem. However it seems quite likely that a future release of Nuget will deal with the issue of local feeds because it's an issue for companies that 'restrict which third-party libraries their developers may use' as mentioned in the Hosting your own NuGet feeds reference above.
I believe the answer to that is "No." There are, however, some references to be able to set the root folder NuGet installs things into: http://nuget.codeplex.com/workitem/215 (see the comments)
How jQuery gets installed is determined by the package producer, which is the jQuery team in your case.
Where the jQuery package gets installed is up to you.
However, the where can only be adjusted in terms of the location of the installed package ($(SolutionDir)\packages folder is the default), and the target project where you install it into. From then on, the package producer takes over and decides where each piece of the package content ends up.
There are some good conventions for ASP.NET MVC, such as a Content folder, a Scripts folder, an App_Start folder (for WebActivator), etc. Think about the risks and extra effort involved of trying to move away from these conventions. Do they outweigh the benefits?
Now if you really want to use your own conventions, you could create your own package with your desired content structure and put the jQuery scripts where you want them in the consuming projects.
This means you would be using your own package with that specific version of jQuery. You just have to be careful to respect the licensing policy of the original package, and not to break any specific installation steps or requirements from the original package, which is fairly easy to do if you manually start changing package structure.
The answer to this is "no" because the "Content" folder is one of the Nuget's convention folders. However, if you rename your Content folder to, for instance, public and then have Nuget pack your public/js folder then when you bring the package in it will extract the files to the public/js folder.
Since I started to use Nuget I switched to using public for my public content instead of Content and rather use Content for files that I want to bring in untouched like source files (see here one usage of Content).

Resources