I’ve been trying to keep up with ASP.NET 5 and the various beta releases that have come out over the last months. It looks like we’re in for at least a couple more more beta releases (there are 8 planned and we’re currently on Beta 6 in mid-August). Of all the things that have been frustrating about ASP.NET 5, updating between versions has been the most painful for me. Every update - even after updating packages and runtimes has resulted in over 1500 errors between updates which when you first see it can be daunting. To be fair most of those errors are fixed by a fixing a couple of package dependencies but still it's quite a shock to open a project that just worked before updating to a new version and seeing thousands of errors :-).
In this post I'll describe how I've been updating projects between betas. It's not been painless by any means, but following a few basic steps will make the experience a little easier.
My AlbumViewer Sample Project
For context, I've been experimenting with ASP.NET 5 using a small sample project that I've been working on. I've been using this same sample for a variety of different implementations and platforms for a few years now. Those of you who read this blog have probably seen my Cordova AlbumViewer sample, or my MVC AlbumViewer sample that's part of the West Wind Toolkit. Using the same sample for a number of platforms makes it easy to compare features, lift related code and also compare performance which has been very useful in many ways.
Here's what the VNext Client Side app looks like:
The app is also fairly mobile friendly and re-arranges itself a bit for phone and tablet operation.
If you want to check it out you can go to:
It’s a small API app with an Angular Client Side front end. It’s set up with multiple projects which has made the migration process more complex as I have to update 3 separate projects first to get them to run then to make them coordinate and run together. But I explicitly decided to do this to see what the update process and dependency management for multiple projects looks like which is a little different than the many simple ASP.NET 5 samples you find out there.
Here's what the project structure looks like:
The 3 projects are:
- Westwind.Utilitities
A small subset of my utility library classes ported to .NET Core compatible operation. - AlbumViewerBusiness
The business layer that contains the Entity Framework Models and Context as well as a Business object that wraps the classes. This project also contains the base business layer. Normally I would move that out into another separate utility project but given the troubles with updating projects I - for now - am keeping that code as part of the same business layer project. - AlbumViewerAspNet5
The actual Web front end project. Contains the ASP.NET and DI configuration and controllers for both the main API backend for the Web applications as well as a very limited MVC controller to display a few pages as server rendered HTML.
These projects are pretty small but they represent what for me at least is a typical project layout. It would be a lot easier to maintain all of this in a single project, but my goal was to create support libraries and at least one toolset project (Westwind.Utilities) that simulates low level features that don't have high level dependencies that automatically pull in a raft of libraries. When you add something like EntityFramework or ASP.NET Hosting or MVC packages into your projects, you are automatically pulling in a ton of Nuget packages that satisfy most common dependencies (ironically in the same way that big libraries standard libraries in full .NET would do). But if you build a low level library that deals mostly with base component, you have to manually pull in all of your own low level .NET core dependencies that used to live in mscorlib.dll or system.dll.
You can see the differences in the references for full runtime and .NET core projects here:
I seriously question that all of this micro-management of 'breaking out of packages' into tiny little dependencies will have any value in terms of footprint - especially since most applications will automatically reference a shitton of these things by way of their top level dependencies like ASP.NET or EntityFramework. Worse though I can see one bad apple pulling in lots of dependencies that aren't even used. All it takes is a lower level component referencing EntityFramework and you now pull in a hundred packages. I suppose this is the equivalent of referencign mscorlib, but it feels a lot worse when you look at a cluttered package folder of over a hundred NuGet packages. Curious to see how that works out in terms of actual memory/footprint savings in the end.
I've been sticking to the major Beta releases and the main NuGet feed that provides the package references. For the really bleeding edge you can switch to the dev feed, but I've found that to be too intense to keep package relationships intact. Unless you are working on the ASP.NET source code itself, stick to the major beta releases.
Beta Upgrade Steps
I’ve been roughly following these steps for each update:
- Update the Visual Studio Tooling (this link is for Beta 6 - it'll change for later versions)
- Update the DNX Runtime
- Check the ASP.NET Announcements Page for changes
- Update your References in your Projects
- Fix any changed types based on Compilation Errors
- When in trouble: Compare Web project startup to a new Project
- Run
Even using these steps the updates – for this small project – tend to take easily a couple of hours of hunt and peck debugging and troubleshooting. To be fair this troubleshooting in many ways has helped me understand how things work behind the scenes but it is disconcerting to see how much is changing between these ‘beta’ releases.
Update the the Visual Studio Tooling
The first step you need to do if you’re using Visual Studio when a new beta rolls around is update your Visual Studio tooling (thank to Damien Edwards for reminding me). The tooling is synced with the latest DNX changes and is required to make sure your projects use the proper command line options etc when compiling code. Since those tools are still changing that's one requirement. The other is that there are some dependencies on the core libraries in the tooling and since those core libraries are also still changing the updated tooling is required.
The tricky part about this is that it's easy to forget. I didn't do it on my Beta 6 update and had a number of weird compiler errors that didn't make sense (even after updating references in the next step). Installing the new tools fixed a number of bogus compiler errors.
Update the DNX Runtimes
This is pretty obvious - once a new beta becomes available you'll need to install the new runtimes and DNX tools. Go to the command line and do:
dnvm update-self
to update the actual dotnet version manager binaries.
Then update the runtimes to the latest versions:
dnvm upgrade
Here's what you should see from the Windows Command Line (using
ConEmu in case you're wondering):
Check the Announcements Page
The announcements page shows breaking changes and a few other useful things that you probably will have to address in your code. It's by no means complete and not easy to see how it relates to existing code sometimes but it's a good place to start. Check this first then update your references and make code changes accordingly.
Update your References
For me this has been the most troublesome part of the update process. When I opened my small AlbumViewer project after updating references and runtimes I end up with over 1900 errors in my projects! Yikes. For example here's what my compile output looked like.
When looking at the error list it's easy to see that most of the errors are related to base types that are not referenced properly which is most of the time caused by bad references. So the first step is to update all references to the latest versions.
If you're using multiple projects like I am, compile one project at a time. Start with the one that has the least dependencies and then work outwards from that. In my case I fixed Utilities first, then the Business project, and finally the Web project.
Rename Assemblies from Beta5 to Beta6
So for example in my Web project I have the following packages defined in project.json:
"dependencies": {
"EntityFramework.Core": "7.0.0-beta6",
"Microsoft.AspNet.Diagnostics": "1.0.0-beta6",
"Microsoft.AspNet.Mvc": "6.0.0-beta6",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta6",
"Microsoft.AspNet.Server.IIS": "1.0.0-beta6",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta6",
"Microsoft.AspNet.StaticFiles": "1.0.0-beta6",
"Microsoft.AspNet.Tooling.Razor": "1.0.0-beta6",
"Microsoft.Framework.Configuration": "1.0.0-beta6",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta6",
"Microsoft.Framework.Logging": "1.0.0-beta6",
"Microsoft.Framework.Logging.Console": "1.0.0-beta6",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta6",
"AlbumViewerBusiness": ""
},
All of these have the Beta6 postfix so in order to update them I could simply rename them by doing a search and replace on beta5 to beta6. That part is pretty straight forward and as it turns out most of those assemblies are staying the same.
However, things are potentially a little more tricky for updating .NET Core references to core runtime files since these are not tied directly to the BetaX designations. For example, my Westwind.Utilities project.json looks like this:
"dependencies": {
},
"frameworks": {
"dnx451": {
},
"dnxcore50": {
"dependencies": {
"System.Runtime": "4.0.20-beta",
"System.Runtime.Extensions": "4.0.10-beta",
"System.Collections": "4.0.10-beta",
"System.Linq": "4.0.0-beta",
"System.Threading": "4.0.10-beta",
"Microsoft.CSharp": "4.0.0-beta",
"System.IO": "4.0.10-beta",
"System.IO.FileSystem": "4.0.0-beta",
"System.Text.Encoding": "4.0.0-beta6",
"System.Text.RegularExpressions": "4.0.10-beta6",
"System.Reflection": "4.0.10-beta",
"System.Reflection.Extensions": "4.0.0-beta",
"System.Reflection.TypeExtensions": "4.0.0-beta",
"System.Threading.Thread": "4.0.0-beta",
"System.Globalization": "4.0.10-beta"
}
}
}
Notice that all of these point at -beta, but not -beta5. But what really sucks about this I that the version numbers on some of them are .0, .10, .20 and they've been known to change. It's easy to get in trouble here and get the wrong package. In this round from Beta 5->6 the only change I had was System.Runtime.Extensions which went from .0 to .10, but it's a good idea to go through each of these references and use the editor Intellisense to find the latest version:
and then drop of the actual build number. The 'safe' NuGet feed should have the latest version in there for the current Beta.
Entity Framework Changes
In Beta 6 there were a few updates again in Entity Framework that caused me issues:
EntityOptions and EntityOptionsBuilder to DbContextOptions and DbContextOptionsBuilder
If you're doing any custom configuration in the overridden OnConfiguring() you'll get a DbContextBuilder passed and that needs to be updated.
.Table() changed to .ToTable() in EntityBuilder
protected override void OnModelCreating(ModelBuilder builder)
{
//builder.ForSqlServer().UseIdentity();
// Pluralization and key discovery not working based on conventions
builder.Entity<Album>(e =>
{
e.Key(et=> et.Id);
e.ToTable("Albums");
});
builder.Entity<Artist>(e =>
{
e.Key(et => et.Id);
e.ToTable("Artists");
});
builder.Entity<Track>(e =>
{
e.Key(et => et.Id);
e.ToTable("Tracks");
});
base.OnModelCreating(builder);
}
Suprisingly there were no changes required for any other code in this beta 6 update for which I am thankful. Troubleshooting start up issues due to renamed or moved components can be a royal pain, especially if said components and dependency injected. The errors emanating from injected components tend to be less than conducive to finding the real problem.
When in Trouble: Compare to a working Project or ASP.NET MusicStore Sample
The Beta5 to Beta6 so far was probably the smoothest upgrade for me. I only had to make a few changes related to Entity Framework - no code changes to anything else. However, beta3-4 and 4-5 were drastic with lots of changes. The only way I could get things to work was by creating a new project and then comparing the start up code and basic config code to my own project. For startup code a new project probably works fine, for other things like Entity Framework Configuration and and Controller operations I recommend looking at the MVC MusicStore sample. For me this has been the best place to see working code for each beta cycle as there's good effort to keep these sample apps up to date. I've been using the SPA sample since that's the closest match to what I'm doing in my sample.
It's a lot of Trouble Still
Updating between versions is still a major pain, but - I guess this is to be expected when working with pre-release bits. However, these 'betas' continue to feel more like CTPs or prelease alphas as there is still so much churn. Hopefully the minimal change pace for the Beta 6 update signals a more stable update cycle coming up so we can actually start building stuff without constantly getting the rug pulled out from under us. I have a bunch of stuff that I'd like to port to vNext, but I'm not going to go down this road until I have some confidence that things won't massively change. In the meantime I'm sticking with my simple play example to see things working and experimenting around the fringes…
Other Posts you might also like