UPDATE: Microsoft has reversed their decision. See What ASP.NET Core May Bring to the .NET Framework’s String Handling for more information.

Last Friday, ASP.NET Core quietly switched from supporting .NET Standard 1.* and .NET 4.* to only supporting .NET Core 2.0. This means that ASP.NET Core 1.0/1.1 applications running Mono or the full .NET Framework will not be upgradable to ASP.NET Core 2.0 when it is released in 2-3 months. Seen as a major breaking change to the platform without a public discussion or formal announcement, this has angered many prominent developers.

Cross-framework support was seen as a vital component for ASP.NET Core. The basic idea was that companies could switch to ASP.NET Core immediately while still using their existing service classes, repositories, and third-party libraries. Then once .NET Core catches up with .NET Framework, they can switch over.

Eilon Lipton, development manager on ASP.NET, explains the reasoning behind this:

Yes, for ASP.NET Core 2, most of the libraries will target .NET Core 2 in order to use new APIs that are not yet available in a .NET Standard TFM. Code that needs to target multiple platforms, such as Microsoft.Extensions.*, Entity Framework Core, and a few other libraries, will continue to use .NET Standard.

After questioning why Microsoft didn’t just create .NET Standard 2.1 with the necessary APIs, Kévin Chalet asked,

My question is simple: are you going to amend/revert these changes at some point before RTM, so people can use the ASP.NET Core 2.0 packages on .NET Desktop, or is ASP.NET Core 2.0 on .NET Desktop definitely dead? (which would be a major blocker for many people, including me).

We won’t quote them all, but many other developers are likewise concerned.

Scott Hanselman attempted to calm developers down by citing what he thinks are the main reasons for using ASP.NET Core on the .NET Framework:

AD – Totally, this is a gap IF you want to call LDAP directly. You can certainly auth against Windows Auth NOW. We plan to have specifically the DirectoryServices namespace for Core 2.0 around summer timeframe. Drawing – Totally, this is a gap. We plan to have this for Core 2.0 around summer timeframe. Until this, these netstandard options also exist ImageSharp, ImageResizer, Mono options, etc COM Automation – This has never been possible under Core 2.0, but you can certainly PInvoke if you want to hurt yourself. You could also local WebAPI to a net461+ process if you really want to hurt yourself. Sharing code with WFP Apps – YES. Totally possible with netstandard2.0.

Scott Hanselman then reiterates,

.NET Core is side by side and it’s moving fast. It’s WAY faster than .NET (Full) Framework can move which is good. By building ASP.NET Core 2.0 on top of .NET Core 2.0 (which, remember, is a SUPERSET of .NET Standard) that means stuff can be built faster than NetFx or even Netstandard.

While it is true that NET Core 2.0 is a superset of .NET Standard, it isn’t a superset of .NET Framework. Kévin Chalet writes,

Many of the "old" APIs re-introduced in .NET Core 2.0 are stubs that will never (functionally) work. Not to mention that there are still many missing APIs, and even entire areas that were deliberately excluded from .NET Core (IdentityModel, WCF server, remoting, complete AppDomain support, etc.). Trying to convince people that they can "safely" migrate their ASP.NET Core 1.0 w/ .NET Desktop apps to ASP.NET Core 2.0 w/ .NET Core is - IMHO [in my humble opinion] - a lie.

Regarding fast moving changes, he adds,

I don't believe that's what (most) people are looking for. Many people don't need fast-moving libraries, they need stable stuff that can gracefully integrate into their older stuff without taking the risk of breaking everything.

Several developers, including Allan Lindqvist, are concerned about fracturing the community.

A lot of devs that really pushed for asp.net core 1.1 are also going to feel betrayed that they now wont be able to move to 2.0 without core. That may or may not be justified but I’m just telling you, a lot of people are going to feel that way; they'll be the ones who have to answer to their more conservative colleagues Does any of that matter? Will asp.net core2/dotnet core2 "die" because of this? No, but it will slow adoption and fracture the ecosystem and that's really sad imo. I want people to be able to use all this great stuff coming in 2.0 and cutting cross compilation to net standard will impact that. Certainly, most people who hang out in these repos won’t have a problem, it's Joe and Jane dev and even more so, their manager that's the problem.

Another concern is that this decision was made privately, whithout an announcement or public discussion period. Demis Bellot writes,

As there has been no prior official announcement, request for feedback, polling or rationale given, this decision "appears" to be have been done with zero community involvement or impact analysis to the existing .NET ecosystem and will likely fragment the entire ecosystem for many years to come. Removing .NET v4.x support removes a smooth migration path for many enterprises to be able to migrate their existing code-bases to ASP.NET's new development model. This won't encourage them to jump to .NET Core faster, it effectively prevents them from even attempting to, causing a massive fragmentation that will fracture the .NET ecosystem in two. I don't see how this will end up being any different than Python 2/3 which has been irreparably harmed by the fragmentation which it still hasn't been able to recover from in nearly a decade.

Going back the issue of library support, gulbanana lists some of the things he needs that aren’t on .NET Core:

We're totally fans of Core CLR and portability, and we've ported a bunch of our components to target or multitarget netstandard. We've got one app that's hosted on Linux so far and hope to have more to come. However, there's no way that everything is going to be ported any time soon! We have still-live, actively-developed code which relies on: NTLM authentication (including advanced scenarios around tokens and SPNs) System.Drawing as above (interesting wrinkle here: we need old image formats like TIFF, which new OSS libraries don't support) Connecting to WCF/SOAP apis - still tons and tons of these out there Windows crypto apis (including RSACng, ECDSA, and CSP for PKI tokens) WPF guis - our clients are not switching to windows 10 any time soon and even when they do they won't want Store apps Microsoft Office interop (particularly access and excel) for data import and export Visual Studio extensibility Third party plugins like the Oracle ADO.NET provider Some of these technologies are never going to be supported by Core CLR. But they are real technologies, which are the basis of new app development - we need a version of .NET which has access to this stuff. Right now our position is manageable: we isolate "legacy" (really: platform-specific) dependencies into their own components which are net461 specific. Specific business apps then take a dependency on netfx if they need these features, and not otherwise. I envisage a future where this is rare for new apps.. but it's hard to imagine it ever being 0%. You did all this work on csproj and the SDK because interop is important. ASP.NET Core is the carrot, the reason to want interop. I do not think it makes sense to take it away. And no, "you can load your references in one direction, but they will likely fail at runtime" is not interoperability.

Tim Miller adds some more:

We also use OData and SignalR in our current web application and that needs to be in ASP.NET Core before we can move over. However, the one thing I don't want to happen is to be stuck in limbo when support for ASP.NET Core 1.x is dropped and there is no migration path with the framework parts we are using that aren't currently supported. I foresee ASP.NET Core replacing ASP.NET wholesale. It may be somewhere on down the road but it is coming. Knowing that I'd hate to rewrite our UI now in ASP.NET MVC 5 (we have a few things there now but it is easy to move because it is small) only to a few years later rewrite it again in ASP.NET Core once the end of life for ASP.NET arrives.

Another concern that keeps coming up is Entity Framework. While EF Core exists, relatively few developers are using it over EF 6 because EF Core only supports a fraction of the features that the previous version had. In fact, the general consensus on forums such as Reddit had been that ASP.NET Core should be used for new projects, but developers should avoid .NET Core and EF Core until they are more stable.

Louis Lewis’s blocker is hardware detection:

For your list of items that we use which have not yet been ported, would be items in the system.management dll. We make use of the hardware identifiers specifically; this is used for automatic link generation for Azure Service Bus and our entire licensing server and client package. I imagine that with them not being the api currently, this would cause us some serious issues?

Christian Weiss adds,

Oh, and of course, the Azure Service Fabric libraries don't run on .NET core either - which is another blocker for us.

Revised Plan

In response to all of this criticism, Damian Edwards has posted a revised plan:

Support for ASP.NET Core 1.x on .NET Framework will be extended for at least another year (until July 2019). We will reassess this annually and commit to providing 12 months notice before ending support of ASP.NET Core 1.x (so by July 2018 we’d announce whether we’re extending for another 12 months to July 2020) (Side note: is anybody else freaked out by the fact we're talking about 2020 already? No? Ok, just me.) The new SignalR will target and be fully supported on ASP.NET Core 1.x (coming later this year). We’ll continue to update ASP.NET Core 1.x to support new language versions, etc. like we do for System.Web. ASP.NET Core 1.x running on .NET Core 1.x will be supported until July 2018 (no change). ASP.NET Core 1.x running on .NET Core 2+ will be supported as long as ASP.NET Core 1.x on .NET Framework is supported ◦This is to ensure there is always an overlap of a supported ASP.NET Core on a supported .NET Core while we support running on .NET Framework, allowing customers to port over time while staying on supported bits. .NET Core 1.x support (as a runtime) doesn’t change. Ends in July 2018. Customers running ASP.NET Core 1.x need to move to .NET Core 2.0 or be on .NET Framework at that point (or move to ASP.NET Core 2.0 on .NET Core 2.0). We will port System.DirectoryServices and System.Drawing to .NET Core this year (fully supported, cross-platform, preview for at least Windows in Summer) The list of things to port to .NET Core after that currently includes ServiceBase (to support .NET Core Windows Services). No timeline yet other than it’s next (timelines obviously get more concrete as we work down the list). We’ll build on this list as we go based on customer feedback. We have no plan currently to port System.ServiceModel (server-side WCF) to .NET Core. The WCF for .NET Core may continue to be enhanced and have features added based on feedback, e.g. HTTP message encryption.

In what may have reduced the amount of complaints if said earlier, David Fowler lists the reasons why Microsoft wants to break away from .NET Standard.

We've identified strings as one of the major things we'd like to try tackling in .NET Core; there are tons of ideas but one of them is to have string be utf8 by default (tons of compat problems but follow me here). Another thing we'd like to fix is the ability to take cheap slices of arrays/strings, any piece of contiguous memory. We've added Span<T> and are looking at Buffer<T> to represent this. It might mean that String and Array implement new interfaces that make it possible to take a slice that requires 0 allocation. This leads to new methods on String that allow splitting that doesn't allocate an array every time. This leads to overloads to Int, UInt etc (TryParse) that take Span<char> and Span<byte> . This leads to new encoding routines that take Span<byte> . Buffer<T> and Span<T> let you represent memory in a uniform way and we want to upgrade the networking stack to allow passing pre-pinned buffers that take Span<T> or Buffer<T> . Kestrel will implement HTTP2 in the 2.x timeframe (currently aiming at 2.1) and that requires new APIs on SSL stream to do ALPN (https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation). Http Client on .NET Core supports duplex streaming; it'll make it possible to implement streaming end points over http in signalr over a single, non websocket http request. We forked the header parser implementations from HttpClient and System.Net.Http and renamed them (https://github.com/aspnet/HttpAbstractions/tree/d1d9bceff56cb44a194ae36923ce687e5e353006/src/Microsoft.Net.Http.Headers) so that we could improve them and have them support both .NET Framework and .NET Core. .NET Core has a copy of these improvements haven't made it back because there no need to improve them (we couldn't consume them). There are a bunch of new threading primitives that require new API that will light up new scenarios if we're able to consume them (https://github.com/dotnet/corefx/issues?q=is%3Aopen+is%3Aissue+author%3Adavidfowl+label%3Aarea-System.Threading); those are just some of the things I've personally filed.

While this has mollified some, Stefan Olson summaries the thoughts of many developers:

It appears to me as though asp.net core is going to run .net core, not .net standard? So I'm still not sure of what the point of the .net standard is - if it gets abandoned virtually as soon as it gets created. It would totally make sense if asp.net core required .net standard 2.1 because there are things that they need that are not in the framework at the moment. So we had to wait till the full .net framework supported those additional functionalities before we could use the latest version of Asp.net core. That would work and make sense. But instead they are just abandoning the standard making the standard useless (if I'm understanding this confusing situation correctly).

The situation for .NET Standard isn’t quite so dire, as it is still a useful way to offer 3rd party libraries for both .NET Framework and .NET Core.

Frustration Continues

Nick Craver of Stack Overflow exemplifies the frustration that many teams have. After spending countless hours porting their code to ASP.NET Core + .NET Framework, they are feeling like it was a wasted effort:

There's still a huge fundamental gap here. The port to 1.x is almost entirely a lateral one, there are few features in it for us. 2.x is where some worthwhile upgrades are and we still have no guarantee we can ever make that move. There's a large chance that we spend a significant amount of time, money, and effort porting to 1.x only to be stranded there because of full framework dependencies. I will not make that gamble with our company. We may well end up with less support than we have on ASP.NET 4.x now. Unless that changes, our apps will not be making the trip to ASP.NET Core, and all of our libraries will be far worse off for lack of dogfooding on it. I sincerely hope you reconsider this decision. I hope one day we can make Stack Overflow take advantage of the thousands of personal hours we have devoted to help develop the .NET Core platform.

Quentin concurs,

Yep. I understand the reasoning, and I suppose I could say I should have seen this coming, but it's very frustrating to have this dropped on us with no prior warning. We have an application ecosytem, like many others, with shared libraries dating back a decade and more, multiple MVC 3, 4, 5 apps, console apps, windows services, hundreds of thousands of lines of code. We're not even in that bad of a situation to upgrade compared to some. We recently stood up a couple new web apps using ASP.Net Core 1.1, necessarily targeting the full 4.6.2 framework. These apps use large swaths of our existing shared libraries. We've burned an embarrassing amount of dev time dealing with project.json, then the new .csproj, trying to mix old and new .csproj's in the same solution, dropping back to VS15 to get things done with old .csproj types, broken System. dependencies, and a litany of assembly binding problems, build & publishing issues... the list goes on and on. And now we've been left hanging high and dry in a dead end. Do we throw away a few man-months of development or spend many times that trying to first just ascertain what might and might not work and then figuring out any way to upgrade, and then if that's even possible doing it. I can't say I disagree with the direction and necessity of it, but earlier communication would've been appreciated.

Undisclosed Intentions

Key to this whole conversation is the fact that Microsoft had always intended to make this change, they just never told anyone. David Fowler writes,

That's why ASP.NET Core on 1.1 's lifetime has been extended (though not permanently). We're going to make sure that SignalR works because that was stated as one major reason for using ASP.NET Core 2.0. At the same time, it's not where ASP.NET Core wants to be in the long run. The intent was always to ship as part of a unified .NET Core platform.

To this Scott Sauber replies,

I've literally seen every single minute of every single ASP.NET standup (including Hanselman and Glenn troubleshooting Docker for three hours... because I have no life), I read the blogs, I'm always on Twitter, I go to 2+ conferences a year, attend user groups, etc. and I've never once heard that communicated as the intent of ASP.NET Core. Instead, I've heard over and over and over "it runs on both platforms" and, rightfully, people feel like someone pulled the chair out from under them. I've even given talks about ASP.NET Core and said "it runs on both platforms" myself, and now I feel guilty for anyone I've led down this path. I would say the people ITT are likely to be on the bleeding edge and would be the most accepting of this kind of news, and there's a lot of backlash here. This seems like it's only going to get worse as this news trickles down to the developers and their managers who aren't as plugged in, and are likely more conservative than those ITT.

Added Concerns for .NET Framework

Another theme of this conversation is what happens to the .NET Framework. David Fowler writes,

Span itself has a portable version that runs anywhere, I'm not sure the fast implementation will ever be on .NET Framework. The APIs that will be added to .NET Framework that take advantage of Span may take a lot longer than Span itself, it's extensive. When's the last time we changed string and array in .NET Framework? The issue isn’t Span itself, but the implications for .NET Framework if it and other .NET Core enhancements aren’t carried over. Matt Nischan writes, Our thinking has always been, use the fancy new libs (such as Kestrel) if at all possible, but wait for .Net Core to stabilize (and I'm glad we did, if only for the tooling changes), or wait for the cool Core bits to make it back to Framework. I think most people's assumption has been that most, if not all, of the advancements corefx has been making would make it into Framework vNext or vNext+1. But, it looks like (from our 30k foot view) from this and other changes that Framework is not a platform of the future.

Frans Bouma adds,