Skip to content

Instantly share code, notes, and snippets.

@FransBouma
Created September 21, 2015 18:30
Show Gist options
  • Save FransBouma/efc7b8b5e3e2b4577ee1 to your computer and use it in GitHub Desktop.
Save FransBouma/efc7b8b5e3e2b4577ee1 to your computer and use it in GitHub Desktop.
Nuget and restore
What I'm doing:
- I work on LLBLGen Pro, an entity modeling system
- I generate for an entity model two codebases: one with the entity classes (A) and one with code-first entity framework code (B).
- I generate csproj files with references to the files in the projects, one for A and one for B. A and B are in separate folders, the
csproj files are in the folders of the projects, just like when you'd create them manually.
- What I want now is that B, on build, pulls the entity framework v6 assembly from nuget.
What I have tried:
- I generate the packages.config file with proper xml which defines a reference to the EntityFramework package, v6.1.3, for net45.
- This packages.config file is added to the csproj file of B.
- I add references (<reference /> elements) to B for EntityFramework dll and the Entity Framework SQL server dll, the full assembly name
like it should, but no Hintpath element.
First this failed, due to a bug in my code which generated 'package.config', instead of 'packages.config'. After this was fixed, it worked
and nuget was happily restoring the dlls on disk in the packages folder of the solution, but the references in the csproj of B weren't
loaded by VS.NET: the hintpath is empty so it's not aware of any location of the dlls.
So I miss a piece of the puzzle: the hintpath in the csproj of B has to be updated by nuget at package restore (it knows what to update
as it knows the packages.config file, and can see which assemblies are references in the csproj referring to the packages.config file), so
when the files are restored by nuget, a build succeeds. It now still fails.
I can only make this work if I add a valid Hintpath to the csproj file, but that's impossible as I don't produce a sln file, just csproj
files and I don't know where the sln file is when the csproj files are added to it.
Is there a way to do this?
TIA!
@yishaigalatzer
Copy link

My understanding

Yeah, you need the hintpath. Here is how NuGet works in this case

  1. NuGet does not change your project on restore (that's a most basic principle)
  2. NuGet Does not add hintpath to the references, it is visual studio that does it when NuGet calls the DTE method addreference on install.

So it appears that you do need a hintpath (or at list a direct link to the packages).

What I assume you are doing:

  1. You have a vsix or vs extension that generates the csproj?

What could be done

You can use a template wizard for that (it is a bit less efficient than what you are doing but will do the job).

See this doc - http://docs.nuget.org/Create/Packages-in-Visual-Studio-Templates

@FransBouma
Copy link
Author

The csproj is generated by a standalone designer which can also be integrated in vs.net using a vsix, but that's optional. The vsix can grab the sln folder path and use that to generate the hint paths, so that's one way to get out of this (but only when the code is generated from within vs.net). The template wizard templates aren't an option, as we're not generating through vs.net, so the wizard isn't involved.

Point 2 you mentioned is I think the heart of the matter. If it could add hintpaths to the references in the csproj in vs.net, it would all work. This then would also solve the problem where a person has moved the project folder (+csproj) or adds an existing one to a sln: restore then also doesn't work at the moment, as the hint paths likely won't match what's on disk.

I'm not sure if this is feasible or whether you want to make this change; The thing is that, in the case of a moved csproj / adding it to another sln, if you don't alter the hintpaths, references in the csproj file won't get resolved after a restore and the user has to manually remove the references and re-add the references through the nuget interface, and as the references are missing, the project won't build, so I don't see a reason why one would want to keep this situation (other than: "it doesn't build and I want that, so I can manually fix the situation on disk", but as we're talking nuget, that's not really a real-life scenario, as people don't move files around on disk to satisfy package managers)

So while my situation is edge case (not a lot of people are generating project files) the situation also pops up with a moved csproj file / adding it to a different sln file in another folder. Fixing hint paths is then making restore work properly in that situation as well (and the side benefit it will fix my situation as well ;))

@yishaigalatzer
Copy link

An alternative solution to your issue it to use IVsPackageInstaller to install packages into the newly generated project, instead of hand authoring it.

Would this work: http://docs.nuget.org/Create/Extensibility-APIs ?

Aside: Hint paths are relative, so you can freely move the project around with the solution. The only thing you can't do is to move the project without a solution, or to a different location in the solution folder.

NuGet will not change the project on restore, that's just not something it should do. So that's just not an option.

@FransBouma
Copy link
Author

Ok. Thanks for the pointer to the IVsPackageInstaller interface, we'll look into that. It's a long shot though, we want to produce code without vs.net if necessary which is then usable without vs.net, but if it takes this step for some people, it can help.

Thanks for your time :)

@yishaigalatzer
Copy link

At that point you can just assume that the relative path it to ..\packages it will work in 99% of scenarios. This will fail for the scenarios where the project is not right under the solution, and where the packages folder was reconfigured.

You could work through these issues by somehow finding the sln the project belongs to (tough one, but doable with some msbuild magic in default scenarios where the sln is in a parent folder), and use nuget.core to read nuget.config hierarchy and figure out the packagesfolder.

Seems like a big effort to go through, and an alternative would be to provide some user input to where the packages folder is.

@FransBouma
Copy link
Author

We decided that if we can't guarantee it's ok for 100% we can better leave it to the user (as it's not a lot of work for the user to add a package reference to EF in vs.net) as the work needed from the user to get the input to produce valid hintpaths is as much work as typing install-package entityframework in the package console.

Thanks for your time and help on this. With project.json I figure this is all solved anyway, but till that's the way to go, the user has to live with this inconvenience. But alas, there are bigger problems in life than this ;) Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment