Reputation: 10932
In my ongoing quest of somehow routing from a legacy MVC web site into an Angular 2 SPA on a page by page basis I've finally arrived at the conclusion that it would be best to use Angular 2 routing right off the bat, that is, no query parameter conversion to a valid Angular 2 route, because that has proved to be a total nightmare.
In my legacy web app the plan is to replace the controller action code by a redirect to a corresponding action on AppController
, e.g.
public ActionResult Action1(int param1, int param2)
{
return RedirectTo("Action1", "App", new { param1, param2 });
}
AppController
is in an area of its own (Areas.Web
), which also houses the Angular 2 app
public class AppController : Controller
{
public ActionResult Index()
{
return new FilePathResult("~/Areas/Web/index.html", "text/html");
}
public ActionResult Action1(int param1, int param2)
{
return Redirect($"/Areas/Web#/{param1}/{param2}/action1");
}
}
In index.html
I set the base href
to
<base href="/Areas/Web/">
So the idea is to have ASP.NET MVC grab index.html
and send it to the browser, including the hash location, which should evaluate to
/<param1>/<param2>/action1
on the Angular side of things, right?
In my bootstrap code I make sure that the HashLocationStrategy
is used,
bootstrap(AppComponent, [provide(LocationStrategy, { useClass: HashLocationStrategy })])
.then(success => console.log('Bootstrap success'))
.catch(error => console.log(error));
Routing for app.component.ts
is as follows:
@RouteConfig([
{ path: '/:param1/:param2/action1, name: 'Action1', component: Action1Component}
])
I would assume that this setup should properly route right into Action1Component
, but it doesn't. The route config is completely ignored, Action1
's constructor is never invoked.
Where have I gone wrong?
EDIT: What actually works once the Angular app is running is
http://legacy.com/Areas/Web/<param1>/<param2>/action1
without the #
- but pressing F5 will obviously break this strategy. So not only is the URL that includes the hash sign an invalid route, but the URL without hash tag is perfectly valid. I'm confused....
Upvotes: 4
Views: 2058
Reputation: 10932
Ok, got to the bottom of this, thanks to this answer. The trick is, never to provide ROUTER_PROVIDERS
except for bootstrapping the application:
import { bootstrap } from 'angular2/platform/browser';
import { provide } from 'angular2/core';
import { HTTP_PROVIDERS } from 'angular2/http';
import {
ROUTER_PROVIDERS,
LocationStrategy,
HashLocationStrategy
} from 'angular2/router';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [
ROUTER_PROVIDERS,
HTTP_PROVIDERS,
provide(LocationStrategy, { useClass: HashLocationStrategy }
)])
.then(success => console.log('Bootstrap success'))
.catch(error => console.log(error));
My guess is that, like with any other service that is injected into a component, you get a fresh instance of Router
if you declare ROUTER_PROVIDERS
in the providers
section of your component decorator, thus overriding the instance you configured HashLocationStrategy
for and as PathLocationStrategy
is the default, you get exactly that.
Upvotes: 3