TFS Agent Build Reference errors - asp.net-mvc

I am attempting to create my first ever agent build using on my my asp.net mvc projects. The agent is on my own computer. Everything appears to work fine up until after the nuget restore.
Picture:
It is telling me that my System.Web.MVC assembly could not be located. Since this is of course my first build I am unsure of what to do or what could cause this issue especially since it builds fine locally in VS.
Any help would be greatly appreciated:
TFS Version: 16.122.27102.1

You can follow steps below to locate the cause of the issue and resolve it:
1.The Nuget 4.3.0 you're using is too old. Instead you should use recommended 5.7.0. (Modify your Use Nuget Task)
2.Check log of your restore step.
The missing System.Web.MVC comes from Microsoft.AspNet.Mvc nuget package, so you should make sure this package is actually downloaded/installed. And make sure the hintPath in your csproj is correct compared to the installation path of the nuget package.
Also make sure you're restoring for whole solution instead of one specific project.
Check whether you added packages folder into source control. The packages folder in SolutionDir should not be added into source control! It will affect the restore stop.
3.Check MSBuild arguments of Build task, you can share the arguments and build logs here if convenient.

Related

Can I use EF6 migrations in a separate project with a ASP.NET Core Web Application (.NET Framework)?

I've been trying to work this out for a little while now and I can't see how it's possible, which seems odd given that .NET Core is properly released and EF6 is still recommended for some mainline cases. However, I'm new to .NET Core, so hopefully I'm just missing something obvious.
I have a ASP.NET Core Web Application and have been trying to add EF models and migrations in a separate project. I've tried two main paths and both have hit different road blocks.
Attempt 1: Create the EF library as an old fashioned class library
This works OK within Visual Studio (although you have to mess around with the start-up project), but when I try to use "dotnet restore" to build things from the command line (so I can get my CI set up) I get:
Errors in C:\MyProject\src\My.Website\project.json
Unable to resolve 'My.DataModel' for '.NETFramework,Version=v4.5.2'.
Using the "dotnet" command appears to be the new way of running command line builds, but perhaps it's not the right way for this case?
Attempt 2: Create EF library as a .NET Core class library
This way fixes the error when running "dotnet restore" but has the rather more fatal flaw of breaking the package manager console commands for creating migrations (they appear to require a .csproj file to work). This answer looked like it might be a solution, but I couldn't get it to work for me.
I think that my attempt 1 is more likely to be the right way to go. In which case this question may boil down to "how do I use 'dotnet restore' with non-.NETCore libraries?"
I've just found this thread, I've tried a few things from there and they haven't worked yet, but I'll keep looking at it.
As far as I can tell the answer is "No" if you want what I would consider a sensible CI set up. If you can run a full install of VS2015 on the CI server you may be able to get this to work somehow.
I got further with my attempt 1 but ended up at what looks like a terminal (at the moment) road block. Currently Visual Studio 2015 will create lock.json files that correctly include my EF project. However, running "dotnet.exe restore" will then remove the lines referencing my EF project and break the build.
I hope that eventually dotnet.exe will catch up with Visual Studio and correctly handle project dependencies but for now this seems like a terminal issue. Even if I commit the lock.json files to source control the CI server needs to run dotnet restore to pull down dependencies and so will break the lock.json files.
I had to jump through quite a few other hoops to get this far, so I'll document them below in case it helps anyone else.
Nuget
You need to install nuget onto your build server (or have your build download it). This is probably fairly common, but our build server didn't have nuget already on it. I have tried nuget 2.8.6 which appears to only download the .csproj dependencies, and nuget 3.5.0-rc1 which appears to behave very similarly to dotnet.exe.
Dotnet
Again you need to install this on the build server (not unreasonable). However it will produce an error when trying to handle the project dependency so you may need to ensure that your build doesn't fail at that point (e.g. by doing this)
Msbuild
At this point my local Msbuild complained about the EF project with:
Your project.json doesn't list 'win' as a targeted runtime. You should add '"win": { }' inside your "runtimes" section in your project.json, and then re-run NuGet restore.
That project didn't have a project.json file at all at that point so I added one with the following contents:
{
"frameworks": {
"net452": {
}
},
"runtimes": {
"win": {}
}
}
As hinted at on this thread. Although I've just noticed that the presence of this file stops nuget 3.5.0-RC1 from downloading the Entity Framework dependency for my EF project at all (Nuget 2.8.6 ignores this file and downloads EF fine)
The end
At this point my local msbuild will build the project as long as I've opened it in VS2015 so that VS2015 has had a chance to build the correct lock.json files.
On my CI server if I comment out the "dotnet restore" step and commit my lock files to source control my EF project reference isn't a problem any more (I still have an issue with the reference to Entity Framework itself, but that's probably a separate issue). However, leaving out the dotnet restore step is not a viable solution - things are only working because that step was there before and has already downloaded the relevant dependencies.
Note that if you're going to try to reproduce this, VS2015 will notice and re-write the lock.json files back to a working version immediately if you run "dotnet restore" so you need to close VS2015 or have a separate checkout to see the issue.

using tfs build pull a prebuilt common components into another build

I'm looking for advice on how to have team build 2013 use a pre-compiled common that is not checked in or part of the workspace.
Everything we build is QNX based and we are refactoring out a common set of components to be shared across all projects. I've looked at Go and NuGet but that seems like a lot effort for something like this.
What is the best way to pull a prebuilt common into a TFS Team Build?
So you would nuget "publish" a package.
https://docs.nuget.org/create/creating-and-publishing-a-package
then your build would nuget restore using a packages.config file (aka, NOT a .sln file)
nuget restore [<solution>|<packages.config file>]
https://docs.nuget.org/consume/command-line-reference
What VS (in a .sln file) is auto-voodooing some of this for you.
But using command line nuget (especially for the restore)....is a way to get a package out of nuget if you're build isn't based on .sln file.
Another way to think about it is...when you run "nuget install" or "nuget update", VS is auto-voodooing you a packages.config file. While you might look at the file and find it interesting, you're not consumed on how it works in the background of VS. But if you want to manually pull nuget packages....you will be very interested in how it is created.
What I would do as a test would be:
Create a dummy .sln,csproj file.
Nuget add a few random packages (using "Manage Nuget Packages for this solution).
Take that packages.config that was auto-voodoo created for you.... and move it to a clean directory.
See if you can run nuget.exe restore on it, and get/pull the packages (aka, you're testing that you can do a pull... without a .sln file being involved).
If that works...than it becomes of matter of creating your own nuget repository..creating your own published-package...and repeating #4 above to get that package out.
Make sense?
So I have these files in a clean directory:
.\packages.config
.\.nuget\NuGet.Config
.\.nuget\NuGet.exe
.\.nuget\NuGet.targets
Then I run in the comamand-window:
.\.nuget\nuget.exe restore .\packages.config -PackagesDirectory .\MyPackages
And all the packages listed in "packages.config" will download to : .\MyPackages
Note, if you have a custom nuget repository, that will need to be configured...but cross that bridge when you get there.

How does TFS know about nuget?

From this article -
"However, there are cases where it’s not actually a person who’s doing the building and who therefore can’t provide consent this way. (And where Visual Studio isn’t even installed.) The prototypical example is a build server. In that case, NuGet will also look for an environment variable called EnableNuGetPackageRestore. To enable package restore for scenarios where the Visual Studio option is not practical, set this variable to true."
How does TFS even know how to call nuget? Do I install the nuget exe?
As you've stated in a comment, "Enable NuGet Package Restore" is no longer the recommended method for accomplishing this. The NuGet docs explain it best. Basically, because that method is integrated into MSBuild, packages that extend the build will be downloaded too late. While I'm not sure what packages do this currently it appears that there are big plans for the future of NuGet (the new ASP.NET vNext custom CLR implementation is one example of where it's headed).
The good news is that the alternative is really easy to set up. If you're in VS, you literally do nothing (unless you've disabled the automatic package restore in the past). If you have a build server you just have to make some small changes to your .proj file. If you're not familiar with MSBuild it may seem challenging but it's really quite simple. The secret is this chunk of code:
<Target Name="RestorePackages">
<Exec Command=""$(ToolsHome)NuGet\NuGet.exe" restore "%(Solution.Identity)"" />
</Target>
Again, the details are in the docs (this one specifically). If you have any questions don't be afraid to reach out: the SO community is here to help!
How does TFS even know how to call nuget? Do I install the nuget exe?
No, you should enable package restore for the solution which can be done from the context menu for the solution file in the solution explorer. This will add a folder named .nuget to your solution and in this folder you will find NuGet.exe.
If you add the solution to source control and build it on a build server the NuGet.exe executable will be used by the NuGet msbuild targets to restore packages from NuGet as part of the build.
So you do not need to install NuGet on the build server - it becomes part of your project and is placed under version control.
If you set your solutions to restore NuGet packages, and then on the build server with the build account, open vs and set Allow NuGet to download missing packages during build in Visual Studio. Your builds should restore packages ok.

Requirements for TFS Nuget Package Restore

I have set the option on my VS2013 solution "Enable Nuget Package Restore" and its not restoring nuget packages on a build server. Plenty of missing references errors to System.Web.Mvc and so on...
Everything is fine on hosted TFS - but I'm running into issues with a secondary CI server using TeamCity. I don't have visual studio installed on the build server by choice.
I'd like to know how do I enable package restore on the build server.
I don't want the packages in source control and I'd like to avoid hosting my own nuget feed for the System.Web.Mvc etc..
Cheers!
I came across similar issue some time back, was able to resolve this by updating RestorePackages condition value to True in Nuget.Targets file.

Recursively include Nuget DLLs via Gitignore

I am using GIT with a new ASP.NET MVC project. I have a line in my gitignore file to ignore dlls
*.dll
I would like to add something along the lines of the following to include (i.e. do not ignore) DLLs in my NUGET packages folder
!/packages/*.dll
The problem I'm encountering is that not all nuget packages are created equally and, depending on the package in question, DLLs may be nested an arbitrary number of levels in the path hierarchy. It seems that I simply need a recursive solution along the lines of:
!/packages/**/*.dll
!/packages/**/*
I have not yet found a solution that will work via mysysgit (or any windows distribution of git).
Does anyone know of a way to make this work???
Leave your top level gitignore alone by keeping *.dll in it.
Create another .gitignore file in the packages directory and put !*.dll in it.
Another option to consider is NOT including your NuGet dlls in your repository and instead only download them the first time you build your project. This is what we do with all of our NuGet dependencies.
UPDATE
Nuget handles this now without having to manually create your own build events. See the details on this page: http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
Original Answer:
We put the NuGet.exe application in a tools folder under our solution, and then add the following to our project pre-build event.
"$(SolutionDir)Tools\NuGet.exe" install "$(ProjectDir)packages.config" -o "$(SolutionDir)Packages"
The first time we build the app it will download all of the dependencies, but with subsequent builds, NuGet is smart enough to see that they already exist at the correct version and skips them.

Resources