0

I'm trying to redirect from an MVC controller to an Angular 2 app that resides within an area of the MVC project, structure is as follows:

Clients.Web (MVC project)
|
+--Areas
   |
   +--Legacy
   |  |
   |  +--Controllers
   |     |
   |     +--Action1ApiController
   |
   +--Web
      |
      +--app
      |  |
      |  +--action1
      |  |  |
      |  |  +--action1.component.ts
      |  |
      |  +--action2
      |  |  |
      |  |  +--action2.component.ts
      |  |
      |  +--app.component.ts
      |  +--index.html
      |  +--main.ts
      |
      +--assets (vendor modules, images etc.)
      +--Controllers
      |  |
      |  +--AppController.cs
      |
      +--node_modules
      +--typings
      |
     ...

I need to be able to traverse from a legacy MVC page into the Angular 2 app, e.g.

/Web/App/Action1?param1=10&param2=15

should be routed to

/Action1/:param1/:param2

in Angular. At the same time I need to be able to invoke actions on

/Areas/Legacy/Controllers/Action1ApiController

I can't, for the love of cookies, figure out how to do that. In my index.html I set the base href to

<base href="/Areas/Web/">

In that same file I imported the main module with SystemJS,

<script>
  System.config({
     baseURL: './',
     map: {
        'angular2': '/Areas/Web/node_modules/angular2',
        'rxjs': '/Areas/Web/node_modules/rxjs'
     }
  });
  System.defaultJSExtensions=true;
  System.import('/Areas/Web/app/main')
     .then(null,console.error.bind(console));
</script>

where I then bootstrap the app

import { bootstrap } from 'angular2/platform/browser';
import { AppComponent } from './app.component';

bootstrap(AppComponent, [])
  .then(success => console.log('Bootstrap success'))
  .catch(error => console.log(error));

Finally, in app.component I set up routing

import { Component } from 'angular2/core';
import { ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig, Route, Redirect } from 'angular2/router';
import { Component1} from './action1/action1.component';
import { Component2} from './action2/action2.component';

@Component({
    selector: "app",
    templateUrl: 'app/app.component.html',
    styleUrls: ['app/app.component.css'],
    directives: [
        ROUTER_DIRECTIVES,
        Action1Component, 
        Action2Component
    ],
    providers: [
        ROUTER_PROVIDERS
    ]  
})
@RouteConfig([
    new Route({ path: '/:param1/:param2, name: 'Action1', component: Action1Component})
])
export class AppComponent {
}

However, if I then navigate to

/Areas/Web/app/index.html?param1=10&param2=!5

I get

param1 = 'app'
param2 = 'index.html'

passed into Action1Component, which is clearly not what I intended. Any pointers would be appreciated.

EDIT:

Routing only targets the AppController at the moment,

routes.MapRoute("SPA", "Web/{controller}/{action}/{id}",
    new { controller = "App", action = "Index", area = "Web", id = UrlParameter.Optional },
    new[] { "SomeSite.Areas.Web.Controllers" }); 

and the code for the action is

public class AppController : Controller
{
   public ActionResult Index(int param1, int param2)
   {
       return Redirect($"/Areas/Web/app/index.html?param1={param1}&param2={param2}");
   }
}

As I'm migrating a legacy web site one page at a time, the idea is to have actions Action1, Action2 etc. on the AppController and link to these actions from legacy pages.

2
  • So a question, you want the parameters to be in the url, not as parameters, correct? Because that is how you have written the route in Angular, but not what you have given it in the example... And can you add your MVC routing because that is what is going to do all the heavy lifting here Commented Apr 15, 2016 at 9:23
  • Yes, parameters should appear in the URL, I'm in the process of migrating to Angular 2 one page at a time. Added routing and action code in my question. Commented Apr 15, 2016 at 9:42

1 Answer 1

2

The thing is, that your routing doesn't match.

You say you want the route

/Action1/:param1/:param2

to be routed but gives it

index.html?param1={param1}&param2={param2}

which is just not the same thing. The problem at this point will be in your MVC app because it will redirect all your traffic starting with /Web to the controller, creating the SPA app. But the SPA app will, only look at the url from the point after /Areas/Web/thus strarting with the \app seeing it as the first parameter becuase you have told it to expect two parameters first in the url.

public ActionResult Index(int param1, int param2)
{
   return Redirect($"/Areas/Web/app/index.html?param1={param1}&param2={param2}");
 }

should be

public ActionResult Index(int param1, int param2)
{
   return Redirect($"/Areas/Web/param1/param2");
}

according to your Angular app but that will start a new cycle of doing routing doing a redirect, and will end up in an endless loop.

I typically have one action in my MVC app that just creates the spa app by returning an html pages and not a redirect to avoid routing outside of catching everything. Like so

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return new FilePathResult("~/index.html", "text/html");
    }
}

In your case, if you need to catch the parameters, maybe combind the two, so if there are parameters, have a controller that catches that and redirects to the correct url (my improvment of your controller above) and then a route that catches the new url and creates the app like my example last would work.

Alternativly, you just use my example in the end, leave the url untouchd and handle it in Angular by redirecting there.

Sign up to request clarification or add additional context in comments.

1 Comment

My fault, got a tad distracted there I meant as query parameters. Anyway, you got me back on the right track again, I changed path to '/app/index.html' (no parameters) and then the optional parameters param1 and param2 where passed into the component. I'll accept your answer as it greatly helped me, but maybe you'd like to add this case (query parameters as opposed to URL parameters) to your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.