I've seen this blog entry (https://blogs.msdn.microsoft.com/dotnet/2016/10/19/net-core-tooling-in-visual-studio-15) that details moving the dependencies to the XML inside of csproj and I think this is a really bad idea. I am for moving most of what is inside project.json to csproj, but the great experience of editing the project.json for dependencies is going to slow people down, even if you do support intellisense. It's just going to push people to use the PowerShell extensions or the VS Nuget UI both of which are a big step back.
This means we're going from the simple and sublime:
"Microsoft.AspNetCore.Mvc": "1.0.0"
to:
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.0.0" />
This is even a step back from the XML file from prior versions since the csproj has to be reloaded to make these changes. Please reconsider this.
My suggestion is to keep the dependencies as a nuget.json or packages.json instead.
I have 2 projects, same output path.
Is there something to prevent me from adding 2 different versions of same lib? Like Paket which does global dependency resolving (with support for groups where I explicitely have to state that I need that).
@shawnwildermuth VS 15 is finally going to be able to edit the project file without unloading. https://twitter.com/davkean/status/787038131656589312
@dasMulli I don't think that mitigates the other downsides...
never claimed it would. but it unblocks the dev workflow for working without ui and custom msbuild work which is all i need.
@shawnwildermuth good catch and agreed. Definitely a step back, .NET Core is supposed to be cross-platform and the json format is definitely the winner there and in terms of brevity.
@TheOnlyRealTodd
.NET Core is supposed to be cross-platform and the json format is definitely the winner there
The old project.json could be used on Windows, Linux and Mac. The new MSBuild-based csproj will be usable on Windows, Linux and Mac. I don't see how does that make the old format any more cross-platform than the new one.
Personally, I'm happy to see NuGet finally become a first-class citizen in the .NET project/build system. The real issue is that MSBuild needs to support additional file formats besides just XML...
Typing a version number in an XML file is no more a "bad idea" than typing a version number in a JSON file. There is no significant difference, and the semantics of how to use this functionality in a text editor or VS2017 are identical to how you use project.json in a text editor or VS2015.
May be spam but let me just dump my thoughts on this here.
Background: When the news broke on moving away from project.json (april/may?), i was devastated. Loved that thing and somehow still do. Now to the "yes, but" arguments that i have run into:
Language and format preferences are highly subjective. There are many reasons to favour YAML, JSON, XML, F#/C# build scripts, Package.swift ore something completely different for various scenarios. It doesn't _really_ matter and there are many up- and downsides for each approach (e.g. i had a few merge conflicts in project.json
files just with comma needed when adding a new line to a json object).
I don't think there can ever be a _logical_ / deterministic decision on this.
Build frameworks usually fall somewhere between "we define what you can choose from" and "we give you some tools to build your own".
Project.json is definitely more the first one. It has _some_ capabilities and ways you can configure it. It's only extension points are script invocations. While that is ok for a lot of tasks, it has two major drawbacks: It relies on the shell of the platform so you need to work with the minimum intersection of cmd/bash/zsh/etc and you have no integration with the build itself while running the commands - you have no access to the build system's model and can't communicate back to it other than a success/failure state via exit code.
Frameworks like gulp or grunt on the other hand let you run your own code to set up the build pipeline and inject custom actions on the way. Want to analyse all JS objects, parse the parameter names of all constructor functions out and append DI metadata to the build output so minifying won't kill you? no problem. just insert a step where appropriate.
Project.json can't do stuff like that. But MSBuild can. I can easily write before-build targets that can emit <Compile Include="obj/$(Configuration)/AutoGeneratedAwesomeness.cs" />
elements. Or embedded resources, simple files to put next to the output or whatever else i can think of to scare my coworkers. See CoreCLR/CoreFx: they have logic to decide between including Foo.Windows.cs
and Foo.Unix.cs
based on custom build arguments.
The interesting part is that i can get extensions via NuGet now. Just like Microsoft.NET.Sdk
is just a NuGet with *.targets
and *.props
files, i can just as easily make my own or consume 3rd party packages to get awesome build and deployment targets. Some have complained about missing publish-to-azure / webdeploy functionality in the dotnet
CLI. such features could easily be brought in via NuGet. Also, the VS docker integration just adds targets and props files to your project and adds them to your solution. Some of that could also be moved to a NuGet.
My best example for this is the current CoreRT integration. It basically is "add this line to your csproj and then call dotnet build3 /t:LinkNative
". Previously, the CLI had to know how CoreRT works and implement the necessary logic for dotnet build --native
.
NuGet and MSBuild haven't had much integration until now. It worked somehow if you build with devenv
thanks to NuGet's vsix package. If you built project.json based things with it, you have probably run into restore.dg
. This temporary file is a manifestation of all the problems a separated package / build system can have. I don't fully understand the internals and i don't really care. I want things to just work.
For JS, there are npm and bower. Both specific to what you want to do with either the library you're pulling or the code you're writing. Can be a bit of a mess when you are new to web / node development.
For Java development, people mostly use maven or gradle. Both have a deep understanding of and integration with package management. It is fairly easy to add a dependency and have it build.
How does that work with NuGet and csproj? If you install a NuGet package in the packages.config
world, it's a mess. NuGet will add the package you need to your packages.config
, install the dll-references / targets / custom stuff into the csproj. If packages use a custom install script, it may be impossible to completely uninstall a packet. The migration guide for packages.config to project.json has just too many manual steps including editing your csproj files.
At build time / CI server, you then need to figure out how to actually restore the packages. Turns out the best way is to have a nuget.exe
somewhere and point it to the packages.config files or the solution file. MSBuild itself can't do "restore on build", that's again a VS feature you'd have to use via devenv.exe
somehow (tell me if i'm wrong on this!).
In the new world (current CI builds of the dotnet cli), msbuild does everything. dotnet restore
has the same effect as dotnet msbuild /t:Restore
. It just translates the arguments.
So, if NuGet packages are a primary development tool and the build pipeline shall handle it, it makes sense to merge the files and not have NuGet edit the other.
Building large project is a pain in the a*, independent of the languages / tools used. Setting up complex msbuild "solutions" isn't easy but if you have that running, it's awesome. And most of the infrastructure in .NET is msbuild-based. If I want to build an installer for a windows app, i create a .wixproj
project. That references a csproj as <ProjectReference>
, allowing me to use the output information for that project that MSBuild provides to create an installer configuration. If any new project type comes out i can add it too, as long as it is msbuild-based. I can't reference a project.json
out of a .wixproj
.
Btw, how do you currently build a project containing 20 project.json-based projects? Either call dotnet build
20 times or have an msbuild solution that includes all 20 .xproj
files. That will also get better if it's just a csproj and the dotnet cli is able to build .sln
files.
At our company, we moved some libraries and application to project.json just to get the integrated NuGet pack support and transitive package references. Much easier that maintaining .nuspec
files. That is one example of features that all C# solutions instantly get with the move from project.json to msbuild.
While csproj files are getting a lot better with all the recent updates (more defaults, less clutter), there are still additional options that have been suggested to "make msbuild great again":
*proj
file as XML and JSON, use whichever succeeds).Ok i went a little too off-topic..
TL;DR, msbuild and nuget are now two integral parts of the same thing - a C# library or application. As such, i think they should be in the same file. Whatever the format of that file.
@llehn I was intrigued by your question and blogged this post.
For the record, it is possible (just tried it out) to move all package references to a separate file. Not sure how tooling is going to like that when managing references via UI but it restores/builds/runs just fine like this:
packages.props
:
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" />
<PackageReference Include="Microsoft.NET.Sdk" Version="1.0.0-alpha-20161024-1" />
</ItemGroup>
</Project>
TestProject.csproj
:
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp1.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
<Import Project="packages.props" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
With upcoming dotnet ref [add/rem]
command (#4521), the general experience of dealing with references (and not needing to edit the csprojs) would be improved IMO.
A related thread is here dotnet/roslyn-project-system#639 (ability to add reference from nested directory via glob).
Dotnet Ref is interesting but not a solution. Not all dev's want to keep a console open to run commands if they can just edit a simple file.
I've started implementing project.json and several other methods of specifying references over at https://github.com/aL3891/CustomPackageReferences if you're interested. Early days but the concept works at least :) its a bit rougher than the "real" thing but its close. also, intellisense still works for project.json in the current vs builds, so that's kind of nice
XML versus JSON is a personal preference, it's not a flaw in the design of anything.
I personally like both approaches, they are both compact and get the job done.
Liking is valanced familiarity. XML has gotten a bad wrap and thus we're projecting that negative perception of XML onto this being a "bad" way to reference packages. If you give it a chance and think about the benefits (that this accomplishes the same thing and is still compact) - you can learn to like either approach.
Neither format is "better" - JSON for example doesn't support commenting, and instead of angle bracket soup, it's curly bracket soup.
In either approach I'm happy that we:
These are marked improvements, so kudos and thank you to the developers behind all of this, you've truly eliminated things that are a PITA.
Personally, I'm happy to see NuGet finally become a first-class citizen in the .NET project/build system. The real issue is that MSBuild needs to support additional file formats besides just XML...
@bricelam What is the value proposition for additional formats? Seems like a giant investment just to appease people that don't want to get over personal biases.
Don't know/don't care. Syntax is irrelevant to me too.
But it's theoretically possible. The input to the MSBuild engine is just an object model, so however you can instantiate those objects will work.
The csproj file editing wouldn't be bad if two things happened:
@shawnwildermuth In the meantime, open up the Environment > Keyboard settings and create a shortcut key to Project.EditProjectFile (i used CTRL + SHIFT + E, CTRL + SHIFT + P). Then just select the project file and use your shortkey.
One of the biggest confusion points for me right now is how to persist nuget dependencies to a file without wanting to compile any own C# code. I want to use a DLL from a nuget dependency in a PowerShell module on PowerShellGallery. I have no C# code, I just want dependencies. With any other package manager like npm, I can create a package.json and run npm install
. It seems like project.json and packages.config worked the same. Now it seems like I have to introduce the concept of a C# project and use the dotnet CLI, which then compiles an empty project, creating trash files everywhere. Should I just continue to use packages.config?
For IntelliSense for PackageReference, install this extension: https://marketplace.visualstudio.com/items?itemName=ms-madsk.ProjectFileTools.
install this extension
Will it get OOTB support?
I personally favor PackageReference over packages.config for the following reasons (note that these are not necessarily technical constraints, they're defaults from VS):
I must say I really like the .props solution to keep packages (/ package configuration) in a separate file, would be nice if VS would support this OOTB.
@shawnwildermuth I agree with you no more. I still can not see a justified reason for using XML over JSON in the official documentation. My reason for JSON is quite simple : JSON format is more web friendly. I sincerely hope the @.NET Core team will consider to turn it back to project.json again in .NET Core 3.0 in which I do not mind to do the migration again no joke no scam no sarcasm at all.
Sorry folks, we have no intention of moving back to project.json. PackageReference is here is to stay.
For those using the new bits, having <PackageReference/>
as items is quite powerful. Here's a few of the things you can do with them:
Share package references across a solution
Condition them
Unify package versions across a solution
@davkean, this is awesome, thanks!
Small feedback:
What would be really nice is if the package management UI also works with version sharing feature.
With Maket solution, when we update EntityFramework package using UI (in both projects that are referencing it):
it should update Directory.Build.targets, instead of csproj.
Moreover, as long as we have <PackageReference Update="EntityFramework" Version="6.1.2"/>
in Directory.Build.targets, package manager UI doesn't realize that csproj now explicitly has version 6.2.0
and keep showing if there is an update available (for both projects).
I am going to go ahead and close this issue as, as @davkean stated above, we have no plans on rollback on it.
Most helpful comment
Personally, I'm happy to see NuGet finally become a first-class citizen in the .NET project/build system. The real issue is that MSBuild needs to support additional file formats besides just XML...