How to use Angular 2 with ASP.NET 4.5+ / ASP.NET MVC 5

I got the following question in my ng-sydney AngularJS usergroup:

How to setup ng2 with Vs2015 for asp.net like mvc/web API?

While many blog posts answer the question for ASP .NET Core, very few answered it for ASP.NET 4.5 / ASP.NET MVC 5. So, here’s what I tried, and seemed to work.

Create a new project in Visual Studio

I found this online project template template Angular2 Mvc5 sample application, and it worked pretty well.

File -- New Project

Run the sample you get to see the output working.

Also, read the template page for workaround to potential issues with Node.

Upgrade the outcome

Unfortunately, the template only gives you Angular 2 RC1 work, with the deprecated router.

Luckily, it’s not too hard to upgrade it!

package.json

If you go to the official Angular quickstart, which you can reach by going to angular.io, and clicking “Get started”), you can find the package versions you need in 2 ways:

  1. Clicking “live example”, which takes you to the Plunker example page, you can get the latest versions of Angular 2 packages in the system.config.js file.
  2. Scrolling to Step 1 – b, which shows a package.json file you can just copy the dependencies section from.

Once you figure out the version numbers, you need to apply these to the package.json file in the root of the web project, here’s what the dependencies piece looks like for me, for Angular 2 RC 4:

  "dependencies": {
    "@angular/common": "2.0.0-rc.4",
    "@angular/compiler": "2.0.0-rc.4",
    "@angular/core": "2.0.0-rc.4",
    "@angular/forms": "^0.2.0",
    "@angular/http": "2.0.0-rc.4",
    "@angular/platform-browser": "2.0.0-rc.4",
    "@angular/platform-browser-dynamic": "2.0.0-rc.4",
    "@angular/router": "3.0.0-beta.1",
    "@angular/router-deprecated": "2.0.0-rc.2",
    "@angular/upgrade": "2.0.0-rc.4",

    "angular2-in-memory-web-api": "0.0.9",
    "core-js": "^2.4.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "systemjs": "0.19.27",
    "zone.js": "^0.6.12"
  }

Try running NPM from a command prompt, or go to Visual Studio output window and change “Show output from” to “bower/npm”. If you see errores complaining about a version not existing of some package, the message will tell you what versions are available, and then you can just pick the highest.

For example, I’m excluding replacing the deprecated router from this exercise. So I kept it, and it didn’t have a package for rc4. The error message about that told me that the max version available is rc2, and that seemed to work fine.

The new router also has its own version. You should be able to see that version in the config file like the other Angular files though.

Angular Forms

After that, since Angular forms became a separate module in RC3, this module was not included.

So, first you need to add it, it has a separate version as well. The plunker systemJS file will tell you what. And it’s shown in the above sample.

Then, you also need to add it into your own systemJS config file systemjs.config.js. Just add it to the packageNames definition. It should then look like:

var packageNames = [
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/forms',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router',
    '@angular/router-deprecated',
    '@angular/testing',
    '@angular/upgrade',
];

And that’s it. Run the application again. You should still see the demo Todo-list with routing working.

Look at the browser devtools console. You should see a warning that you are using the deprecated forms module (what is available by default), and shows you a link of how to override it.

This means the project is working well with Angular 2 RC4, and the deprecated forms and router.

Cleanup

Next, you should be able to start deleting the sample components to leave for your own application components.

Before you do that, you might want to see how the project template works, including the serverside ASP.NET MVC bits. This will give you some guidance on how to structure your own.

Once you are done, you can remove the deprecated router from application bootstrapping file and from NPM dependencies. Then start using the new router, which we already included in the previous steps.

You should also be good to disable the deprecated forms (those are not a separate NPM module, so that stays the same), by modifying the application bootstrapping code as the link in the browser console tells you.

Good luck :)

Angular 2 for Angular 1 Developers — Full Video of My DDD Sydney 2016 Talk

Whether you have been to my talk at DDD Sydney 2016, or we never met before, here’s the entire recording as I captured it on my machine.

I decided to just upload the raw file with minimum or no video editing, so that I can get it up as soon as possible.

Let me know what you think, and what you’d like me to talk about in future videos.

You can tweet at me — @Meligy, and I’ll reply back as soon as I see it.

How to use TypeScript Enum types, especially with Angular 2

Let’s assume you have the following enum in TypeScript:

export enum AgentStatus {
    available =1 ,
    busy = 2,
    away = 3,
    offline = 0
}

An enum is just an object. Your enum is written something like this in JavaScript:

{
    0: "offline",
    1: "available",
    2: "busy",
    3: "away",
    available: 1,
    busy: 2,
    away: 3,
    offline: 0
}

The benefit from typing is very limited in enums. Let me explain…

A very common thing you might want to do, is convert a string to an enum. This line is valid:

var value = <AgentStatus>"offline";

But it’s not useful, because

value == AgentStatus.offline // <- false, because it's "offline" == 0

So, you should always store your values as numbers, which you can obtain as follows:

How do you convert a string to an enum in TypeScript?

var value = AgentStatus["offline"]; // so value is now 0

// You can also use this, which only gives IDE hints, no runtime benefit
var value: AgentStatus = AgentStatus["offline"];

This makes the previous comparison work:

value == AgentStatus.offline // <- true, because it's 0 == 0

Now, a couple questions remain:

How to convert a TypeScript enum value to a string?

AgentStatus.offline // 0
AgentStatus[AgentStatus.offline] // -> AgentStatus[0] -> "offline"

How to get all the values of a TypeScript enum type?

var options : string[] = Object.keys(AgentStatus);
// The options list has the numeric keys, followed by the string keys
// So, the first half is numeric, the 2nd half is strings
options = options.slice(options.length / 2);

Gotcha: Undefined enum type in Angular 2 views

If you write this in your Angular2 template:

{{AgentStatus[myValue]}}

It will fail, because it doesn’t have access to imported types (it gets executed later by AngularJS).

To make it work, your component will need to have a reference to the enum type / object, something like:

export class MyComponent {
    // allows you to use AgentStatus in template
    AgentStatus = AgentStatus;        

    myValue : AgentStatus;
    // ...
}

Runnable Demo With All Solutions

Here is an example that explains everything I pointed in here:

(Click the button at the top right to see it in action)

This post was inspired by this StackOverflow answer.

Solving Common Angular 2 HTTP Pitfalls: No map() Method for respose.json() & No Http Provider

I had so much fun helping mentoring a couple dozen developers yesterday in SSW’s Angular Hack Day here in Sydney. It was an awesome day from organizers to students.

This post is about the Number 1 problem all students seemed to have, and how to solve it.

The Most Common Problem: map Not A Function

When you make an HTTP request to a JSON endpoint, you map the response text to a JSON object, like this:

getList() : Observable<ListItem[]> {
  return this.http.get(this._listUrl)
                 .map(response => response.json())
                 .catch(this.handleError);
}

When the students ran their own code, which more or less looked like the segment here, they got an exception like this:

angular2.dev.js:23925 EXCEPTION: TypeError: this._http.get(...).map is not a function in [null]

2016-04-24_13-31-23

The reason for this is that the result of the HTTP call is an Observable. An Observable has nothing defined by default except subscribe. You need to import any other operator manually like

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

If you rely on autocomplete in your editor, and it shows a couple of versions for every operator, remember to choose the with with “/add/” in it. As this is the file that add the operator to the Observable definition.

You cannot add * unfortunately.
Update: You can import all RxJS operators in one call like this:

import 'rxjs/add/operator/';

Single Include

You can also move the import(s) from every TypeScript file to the main entry point of your app, likely the file with the bootstrap() call.

Depending on how you set up your compilation and module loader, the entry file import might not work. It works with the SystemJS use you see it in the official Angular 2 quick start though.

Obviously, if you think the entry file include is a hacky way, just add the imports on top of the each file that uses them.

Update for gulp-typescript Users

I found a case where a user on StackOverflow had the same problem, even though he had the correct imports in the bootstrap file. The problem was after upgrading to Angular 2 beta 17.

In this particular case, the user reported that he was using gulp-typescript version 2.12.0. He reported that the problem went away by just upgrading to the very next version, gulp-typescript version 2.13.0.

Oh, and make sure you are using TypeScript 1.8+ also to be safe.

Another Problem: No Providers for Http

Some students also were getting a different error:

angular2.dev.js:23925 EXCEPTION: Error: Uncaught (in promise): No provider for Http! (CustomersComponent -> DataService -> Http)

2016-04-24_13-52-18

The forgotten part this time was adding the Http providers to the bootstrap. Something like this:

import { bootstrap }    from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';
import { AppComponent } from './app.component';

bootstrap(AppComponent, [HTTP_PROVIDERS]);

One last tip: Make sure you included the Http file in your scripts if you are starting from a quickstart start or so. As the Http module is included in a separate file in Angular 2.

A Quick Shoutout to Dan Wahlin

During the hack day, students asked me for a good example that shows the solution above. It was not in the official examples (the 5 minutes quickstart, and the Tour of Heroes).

The best I have found on Github is Dan Wahlin‘s Angular 2 JumpStart sample.

It’s named similarly to his Udemy course for Angular 1. I remember his AngularJS in 60-ish minutes YouTube video was a key block in building my Angular 1 learning when I first started it back in 2013.

Thanks for everything, Dan :)

Different People, Different Challenges

With various people hacking away, I got to see different problems that people had getting up and running with Angular 2.

For some people, just setting up Node was more challenging than it should be.

Some others had issues with the sample APIs they chose, because they didn’t have cross domain support (CORS), or returned XML by default and they needed to add an Accept header explicitly.

Some were wondering how to use RxJS to combine results form 2 separate HTTP requests (getting city weather from one, and information about it, or an image URL from another).

How About You?

All these variations got me pretty curious. What was the biggest blocker you had when trying to play with code in Angular 2?

What were your own challenges?

Tweet them to me on Twitter (just mention @Meligy), or just write it down in a comment below.

Fix TypeScript Autocomplete for RxJS Operators And Helpers In NodeJS

I have been working on a Node application, and wanted to use Reactive Extensions (RxJS). All previous interactions with it were in web apps that run in the browser after some SystemJS / Webpack massaging.

At first it looked OK. I could build an Observer, and subscribe to it. I tried to use some operators, and this is when I got stumbled.

The Problem

I had a sample Observable, and I wanted to call flatMapTo on it, but I couldn’t!

Autocomplete only showed the subscribe method, as below:

2016-04-19_07-05-23

Just importing the specific operator file (which modifies the Observable interface and adds the operator method to it) didn’t seem to get the operator autocomplete (or successful compilation at times) to work.

I didn’t want to have to add each operator manually anyway, and this is Node not browser, I don’t have to be picky about imports (and again, it didn’t work anyway).

Note:

I was specifically trying map(), which I was able to get to work with ES2015 targeting (I’m working with Node 5, which has fair ES2015 support).

But that’s because an Observable is also an Iterable object that you can loop over, like an array.

I was not able to get switchMap() (Rx v5), or even it’s v4 equivalent flatMapLatest() though, or any other operator than map() – before I noticed I was not even calling that as an operator.

The documentation suggested the following line.

<code>typings install rxjs-symbol-typings
</code>

But it only threw an error. Which was very weird, because I could find the typings registry entry with this very name.

There were other suggestions for other platforms, which didn’t work for me anyway!

I also struggled to find examples of using RxJS operators with even something like Angular 2. Hence I’m writing this blog post.

How To Get TypeScript Intellisense To Work With RxJS

The main key to working with this was using the “KitchenSink” Definition file. This was also confirmed by looking at:

Property ‘distinct’ does not exist on type Observable<CustomType>

I can use this no problem because I’m in Node and not much worried about the size of the code, etc.

However, this post was not enough to get it to work. I still had a lot to fiddle with. As I mention later, I tried many things, and everything I found working stopped working afterwards.

Until I could nail it down to the following steps:

Install From NPM

You can get that by

<code>npm install @reactivex/rxjs@latest --save
</code>

Make sure you got at least version beta.6, not beta.2.

Add Definition File

You can do this from your tsconfig.json, like:

<code>{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "noImplicitAny": false,
        "sourceMap": true
    },
    "compileOnSave": true,
    "files": [
        // Typings autocomplete file
        "typings/main.d.ts",

        // RxJS autocomplete
        "node_modules/rxjs/Rx.KitchenSink.d.ts",

        // Your other files come here
        "sample-files.ts"
    ],
    "exclude": [
        "node_modules",
        "typings"
    ]
}
</code>

Or in each TypeScript file if you choose to, at the top of the file:

<code>///<reference path="./node_modules/rxjs/Rx.KitchenSink.d.ts"/>
</code>

Gotchas

For the most part, the previous steps are going to be enough. However, I have found a few more gotchas in different editors, most of them are around WebStorm, which is crazy, as outside Rx, it seems to be an awesome TypeScript IDE.

I like WebStorm because it has the best autocomplete in strings (like paths and imports), and in tsconfig.json (which is outdated in VS Code).

Also, the gotchas sometimes happen in VS Code anyway. I have been going crazy between the two, as soon as I get something to work, undo it and repeat the exact steps, it doesn’t work.

Operator And Type inference

Sometimes type inference doesn’t work. I have found VS Code to be better at this than WebStorm.

<code>var sample1$ = Observable.create(observer => {
    observer.next("Non-proper autocomplete");
    observer.complete();
});
</code>

In this example, autocomplete for sample1$. will give autocomplete for any, which is OK as it’ll accidentally give autocomplete for RXJS operators.

But if you want proper autocomplete:

<code>var sample2$ : Observable<string> = Observable.create(observer => {
    observer.next("It works");
    observer.complete();
});
</code>

Note the : Observable<string> bit.

Observable Helper Methods

These are methods like like of, range, etc. I have found their autcomplete to the worst, it’s very flaky at best.

A few things seemed to help, like importing from "rxjs/onservable".

<code>import {Observable} from "rxjs/Observable";
</code>

(Vs from "import {Observable} rxjs")

I have also found that doing import {Observable} works better than import * as Rx.

When everything fails, going to TypeScript compiler in WebStorm and building current file, or even restarting WebStorm (Yes!!) helps fix autcomplete issues, especially if you changed your references and imports a few times. It just gets confused and doesn’t work well until an IDE restart.

Disclaimer

Just in case it’s not obvious for those not familiar with TypeScript. I have been doing JavaScript for so long. I’m not the person who can’t code without a fully-functional autocomplete.

But since autocomplete is an essential advantage of going the TypeScript way, and I have been loving working with RxJS from the demos I saw, I wanted to take it as a challenge more than anything else to see what it would take to get this working.

A Quick 10-Min Video To Start Writing Angular 2 With No TypeScript Setup

Hello everyone,

In this video, I share a very simple tip that I earlier shared with a few Newsletter subscribers and ng-sydney members, about the easiest way you can get to play with Angular2, without worrying about shims, SystemJS, TypeScript, or RxJS.

I also give you another hint for when you want to create a “proper” project, not just a playground.

Too Long; Didn’t Read (Watch)

  • To start a new Angular2 playground, go to angular.io, scroll down to the hellow world example, and click the “TRY IN PLUNKER” button
  • If you need a proper project, just google “Minko Angular2 Seed”, click on the Angular 2 Seed Github repository, and clone that (maybe with flag --depth 1 for clean history)

Let me know if you have any questions.

A Web Developer’s Macbook Pro 15 Wishlist

I’m due for a laptop update at the end of the year. I love to follow news about the laptop brands I care about though. Apple is on top of the list.

I only have one Macbook, as I use Windows very often. I got my Apple Macbook when I wanted a *nix friendly native OS for development, and I felt that Linux just doesn’t cut it.

Of course I realize that *nix tools are coming to Windows relatively soon, I’m not sure whether my next laptop will be a Macbook.

But there are things I definitely like about Mac OSX, and the laptop itself. Battery life is one, and the power available in the form factor and current weight is very cool as well.

So, if I’m going to buy a Macbook for my next laptop, this is what I wish Apple would include in a 2016-2017 Macbook Pro 15:

  • A touchscreen!
    C’mon Apple. You are seriously behind on this one

  • Non Retina screen
    The 1440×900 screen is lovely already.
    At least offer the option for those willing to take it for the battery benefit

  • Long lasting battery
    12+ hours, at least

  • An extra right-side “Control” keyboard key
    Eat a bit from the spacebar key. It’s OK.
    As a right-handed developer, with a lot of tools defaulting to using “Control” not “Cmd”, that key will be a saver

  • Same CPU class as before
    Don’t go to these “U” CPUs, keep the quad core CPU, just update to latest generation

And what could be a really nice bonus, although I’m not holding my breath:

  • 32 GB RAM :) :)
    Because, why not?!

  • Same size and weight, with better ventilation
    I don’t want a thinner or lighter Macbook. It’s perfect as it is now.
    I want one that doesn’t feel hot too often that it has a series of fan-controlling apps though!

It’s a VERY long shot to expect that Apple will read this, let alone listen, but who knows…

How To Include AbcPDF XULRunner Folder As Linked Item In Visual Studio?

I was working on some PDF generation for a customer that used AbcPDF in their ASP.NET MVC website.

The work was to move from basic MVC views written especially for PDF rendering, to reusing the same MVC views we send to the HTML browsers.

With more sophisticated markup, came more CSS styling. The default IE engine seemed to lack a few CSS features we used a lot (example, the :not() CSS selector). So, we decided to use the Gecko engine.

The rendering was much better, with a single exception, that the option to choose media type (screen, print) could not be switched. It had to always be print. I guess a few other browser settings were not applicable as well.

Installation

All I needed to do, to add Gecko, was to install the ABCpdf.ABCGecko NuGet package. Something like:

<code class="PowerShell">Install-Package ABCpdf.ABCGecko -Version 9.1.2.4
</code>

It took quite a while, and at the end, it showed me a message, saying that I need to manually (hate that word) copy a folder called XULRunner21_0 to the MVC project’s bin folder.

The Firefox / Gecko XULRunner Folder

The folder is needed for AbcPDF to connect to Firefox 21 (what’s used in v9, I guess it’s 38 in v10).

The folder, which has so many files and subfolders, was present in the root of my ASP.NET MVC project.

I didn’t want to have to commit this ~40 MB folder to our source control. The customer used NuGet package restore and didn’t want to keep binary files in source.

I know different people and different projects handle dependencies differently, and it can get interesting, but in my case, it was not wanted.

So, I modified the web project .csproj file, and added the following after a PostBuild <Task> in the file:

<code class="XML"><ItemGroup>
  <Content 
      Include="..\packages\ABCpdf.ABCGecko.9.1.2.4\content\XULRunner21_0\**\*.*">
    <Link>XULRunner21_0\%(RecursiveDir)%(FileName)%(Extension)</Link>
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>
</code>

This made the folder show up in the project web project root in Visual Studio, and get copied to the bin folder, but the actual files were pulled from the package folder, not left in the website root itself.

The approach in general is very useful for adding an entire folder as a linked item in Visual Studio. I hope that little trick has helped!

Death By (Any Of) A Few Thousand NPM Dependencies

You see a lot of weird things on the Internet, this one wasn’t the weirdest, but it’s worth talking about.

A very tiny Npm package, called left-pad (and yes, as you can imagine, just pads strings), caused both Ember, React Native, and Babel Npm installations to fail, also breaking any CI that depends on fresh Npm installs.

It All Started With A Kik

The packages were broken as the author of the left-pad package unpublished (removed) it from the Npm registry. The author explains why here. Allow me to quote a few parts:

A few weeks ago a patent lawyer sent me an e-mail asking me to unpublish “kik” module from NPM

Yes, another package the author published called Kik. Nothing about left-pad yet.

When I started coding Kik, didn’t know there is a company with same name.

This part is important. If you use a trademark name as a name of your public IP, whether you know it or not, you still use a trademark name.

After I refused them, they reached NPM’s support emphasizing their lawyer power in every single e-mail CC’ing me.

@izs accepted to change the ownership of this module, without my permission.

So, being a company, with some trademark name and legal team, they contacted the authority of the Npm registry to get the change enforced.

After that, the author decided to un-publish all his packages from the NPM registry, and let-pad happened to be one of them.

Oh No, NPM Is Evil (Or, Is It Really?)

So, based on the author’s side of the story, the company went to Npm with a trademark claim. The author does not deny the claim or mention an effort to avoid it when he chose the package name.

Then, Npm acts based on on the claim, and accepts it.

Which reminds us of a very interesting fact. While Npm tooling itself allows working distributedly, either via multiple registries or even git, the official Npm registry has an official authority!

Too bad for freedom, you might think. But does it ring a bell?

For me, it does. Github and Git.

Git is distributed by default. But see what happens when Github goes offline…

Welcome to the real world of 2016!
(Not that I’m suggesting this might not change)

What Was An Official Entity Supposed To Do In This Situation?

I don’t know for sure, but I wouldn’t expect Github, Google, Amazon, Microsoft, or any other hosting company to act differently.

Whether specified in T&Cs explicitly or not, no reputable host will allow customers (free or commercial) to use their services for anything illegal.

If they are convinced the trademark claim is valid. What are they supposed to do really?

Of course there is a bit of a grey area in here. Some might argue that other companies would only act if they get a letter from court or something like that.

But you do not suppose the company would protect the offender of a trademark offense, if they are convinced it is, right? Whether before or after court.

Even if you do not agree, it’s not that Npm is trying to do anything intentionally evil here, just acting the way they think safer, legally.

But There Is A New Risk Exposed In This Story

The fact that Npm is a company should not be that new to us. We already got introduced to similar facts with Github and others. That’s not the most interesting piece here.

When Node and Npm came out, many people raised their concerns about how a really small task in Node would often require you to pull down a huge number of Npm dependencies.

Some argued that small tasks require having very large repositories because of these dependencies. Some made (less compelling?) arguments that you don’t understand all the dependencies you have in your code.

That didn’t stop the ecosystem from being VERY successfully though.

But today, we have a new concern, that is also directly related to the number of dependencies we often have in Node projects.

Packages Might Just Disappear, And That’s Worse Than You Might Think!

If your project, or your Npm package, depend on many other packages, this means your CI process, if it starts with a clean environment and an npm install command, will fail badly when any of these packages just suddenly disappear.

We never thought of what could happen if packages like “connect”, “request”, or “lodash” just disappear some day. We never thought that this scenario could happen ever.

Today we learn that a massive impact can be caused by even a very simple ELEVEN LINES Npm package.

Of course, with the publicity the author is getting, and several developers agreeing with his view, we might also see more packages “just disappear”.

We’ll only hope they do it in less destructive manner (and I will not say “more responsible” manner), via a deprecation story or whatever. It will still be painful to witness.

The Future Is Unclear

Of course the obvious question is: Where will this take us going forward?

I wish I could predict the future. I’m horrible at even forecasting it.

But, we didn’t stop using Github just because it went down a few times, or had its internal culture questioned in a couple of occasions. I don’t know if we are going to use Npm less or not though.

One interesting observation about the specific let-pad package case, is that since the package is licensed under MIT, this might allow anyone else to republish it without license / legal worry. Or wouldn’t that be enough? Well, commenting on this can be a whole new post.

There will likely be more public Npm registries created. Maybe they’ll die slowly, or one of them will be the next big thing. Maybe the next big thing will be a completely different package manager, like JSPM, or a new one yet-to-be-created.

Let’s wait and see, for now, we just know it’s not the same in the Node world anymore. We learned how the dependencies graph is just a house of cards, where one card can break the whole thing. It won’t be 100% forgotten.

Update: The Story Details

For all the details you need, here’s all sides of the story:

Since writing this post, and especially after reading Kik’s side of the story (basically a copy of the entire email communication), I had a few extra thoughts:

  • Azer (the author) was right when he mentioned Kik’s poor communication. Not that his communication was much better, but theirs was really bad.
    They get a lot of heat for describing this as “polite request” before admitting their poor communication in the same post.

  • Kik is actually a registered trademark. I was thinking it might be. That is something I guess.

  • NPM mentioned that their decision was based on the confusion more than the trademark. On one side, this weakens their position in my opinion, a lot.
    On another, after learning that it is a registered trademark and seeing the emails, I’m not buying that this wasn’t a big factor anyway.

  • There is still the whole other problem of ownership of open source with permissive licenses like MIT, whether a single developer should really have such power in the NPM ecosystem.
    I learned also that NuGet for example (.NET package manager) does not allow unpublishing packages, only unlisting them. Makes total sense to me.

    There’s a good argument for a start that I also found.

Should Angular 2 Be Renamed Like ASP​.NET 5 » ASP​.NET Core?

TL;DR: No. It’s not exactly the same situation.

A friend asked in the Egyptian Geeks Facebook group in Arabic:

Is Angular 2 a suitable name, or does it need a new name? Or am I just not getting the big picture?

Because when I learned about it, I found a lot of different, removed, and new pieces.

As ASP.NET 5 became ASP.NET Core 1, is it a good idea to pick a new name to show the big difference from Angular 1?
Or is this just my problem and the difference isn’t that big?

I thought that it is a logical question. Here is my take on it, as a non Angular team official or affiliate…

My Answer

First, the question has a good point.

The “Core” naming came from Microsoft’s plans to make everything in the new ecosystem “Dot Net Core”-first.

Microsoft always tried to make the point for people that ASP.NET 5 is a “Version 1” product, that is neither neither as version-complete or as mature as ASP.NET 5.
This is way before the rename to ASP.NET Core 1.

Maturity And Meaning Of Upgrade

The Angular team has a different vision. They have confidence that they transferred all their lessons developing Angular 1 into the development of Angular 2. Which is why they really feel it is an upgrade.

They want people to move to Angular 2 automatically, not to feel that they are back into the “framework selection” process again.

I bet the Angular 2’s ideal world is one where they can stop Angular 1 support as soon as they release Angular 2. Except they definitely won’t, so that they don’t let they users down.

Naming Is Hard

As the ASP.NET team themselves always said, naming is a Marketing issue rather than a technical issue. It’s not simple. Everyone have different considerations when naming things.

Another example is Aurelia. Aurelia couldn’t be just “Durandal Next”, because the name “Durandal” has been related to failure in people’s minds (after a failed kickstarter).

It is the opposite situation in the Angular case. It’s hard for it to be called anything else (even something that has the word “Angular” in it), because it needs to be interpreted as an upgrade.

This is, again, not what Microsoft wanted to communicate. They wanted the new name to convey their message that the new ASP.NET framework is NOT an upgrade.

It does not the experience of 15 years of work on the existing ASP.NET framework and add to it in a newer version. It’s a different, modern, lean framework, that is still in year 1.

You can see the contrast clearly.

The Standard Answer

A few others have also pointed out that as per Semantic Versioning, a major version number is acceptable for breaking changes.

I see that there is a difference between “Breaking Changes”, and a “new API surface”.

But there is no standard that tells you what to do in that case, so, the use of major version number (which is technically correct) is still sort-of reasonable.

There are many many patterns in versioning software, as Wikipedia explains.

What do you think?

Let me know in a comment below, or in an email, or tweet.