Dresel / RouteLocalization

RouteLocalization is an MVC and Web API package that allows localization of your attribute routes.
MIT License
67 stars 13 forks source link

How to use Angular with RouteLocalization #40

Closed mdmoura closed 9 years ago

mdmoura commented 9 years ago

Hello,

I have an ASP.NET MVC / Web API application where each page is a SPA using Angular.

Each page can have multiple sections being each one a partial view as described here: http://www.wintellect.com/devcenter/dbaskin/angularjs-mvc-cookbook-simple-routing

Consider the following route in Angular:

    $routeProvider.when('/About', {
        templateUrl: '/Home/About',
        controller: 'aboutCtrl',
    });

Link "/About" loads calls MVC's "/Home/About" that returns a partial view where aboutCtrl is used.

However RoutesLocalization changes routes depending on culture ... So this won't work ...

My idea would be a GlobalFilter that loads all Routes (MVC and API) into a dictionary:

Dictionary<String, String> routes = new Dictionary<String, String> {
  { "Route1Key", "/en/about" },
  { "Route2Key", "en/contact" }
};

Then transform this in JSON and put it in a global variable using window.routes = ... Then in angular routing use the keys on that dictionary to define routes.

Or instead of a filter I could simply this do on the master view ... Or ViewStart? Can I have the keys for those routes? Should I name every route?

Did anyone ever used Angular with RouteLocalization in such a way?

Thank You, Miguel

Dresel commented 9 years ago

Well you could set AddCultureAsRoutePrefix to false if you do not want the urls to be changed? Why not using T4MVC for setting the routes in templateUrl?

mdmoura commented 9 years ago

Well you could set AddCultureAsRoutePrefix to false if you do not want the urls to be changed?

But I do want Urls do be changed ... I mean I want:

/about in EN to become /quem-somos in Portuguese ...
Or even better:
/en/about to become /pt/quem-somos

So if I am not mistaken in English the angular route for this would be:

$routeProvider.when('/About', {
    templateUrl: '/en/about',
    controller: 'aboutCtrl',
});

And in Portuguese:

$routeProvider.when('/About', {
    templateUrl: '/pt/quem-somos',
    controller: 'aboutCtrl',
});

Why not using T4MVC for setting the routes in templateUrl?

Yes, I did not think of that ... It will force me to have the JS code in the shared view instead of in a JS separate file, right? But maybe it is a better and easier option that what I was trying to do ...

mdmoura commented 9 years ago

Another problem is that I will also have API Urls in my application services ... Which means I would need to have also all Angular services code in shared view.

Well, I will try various options and post here ...

mdmoura commented 9 years ago

The Routes Strings in Angular are different from the Route Strings in MVC and Web API.

So I think the best option is to create a RouteStringProvider to hold an MVC/API Route String and an Angular Route String per Route and Language.

Then when setting the routes in RouteLocalization I would call this Route Provider.

And on the master page inside a Script Tag I would create a Service on the fly containing the Angular routes. This service would be injected into the Angular where Routes are defined.

Or a global function also could be used instead of a service.

Both in RouteLocalization and in Angular which Route String is obtained by specifying the Controller and Action name ...

It seems the best way to do this since Route Strings are different in MVC and Angular.

Other suggestions?

Dresel commented 9 years ago

The Routes Strings in Angular are different from the Route Strings in MVC and Web API.

Can you bring some examples? Could this Angular route be derived from an MVC Route?

mdmoura commented 9 years ago

Can you bring some examples? Could this Angular route be derived from an MVC Route?

There are two major route setup options recommended for Angular:

  1. The native ngRoute as seen in https://docs.angularjs.org/api/ngRoute/provider/$routeProvider In the table of that page you can see path that explains how routes are created.

    /color/:color/largecode/:largecode*\/edit will match /color/brown/largecode/code/with/slashes/edit and extract: where color: brown largecode: code/with/slashes.

  2. UIRoute which is more complete. You can see the UrlMatcher: http://angular-ui.github.io/ui-router/site/#/api/ui.router.util.type:UrlMatcher

    On that page you can see the pattern used in UIRoute.

    I think in this case the route strings are more similar to MVC routes. What do you think?

But nevertheless it would be necessary to create some code on the client ...

It could be a service with a function in it or just a global function:

function getRoute(controller, action) {
    return route for controller / action
}

The route could also be gotten by name and the prefix for culture must also be considered ...

brgrz commented 9 years ago

Routes in angular are completely separate thing to routes in MVC. They are similar but separate. They have nothing to do with what you have in MVC although you might set them up similarly.

You will have to introduce the culture to your routes at client side (in Angular app) also. But your clientside URL will change too, you can't only change the templateUrl. If I want Portuguese content I have to navigate to Portuguese URL, that makes sense.

Also, please consider using angular with MVC/Web API in more RESTful way by loading content via JSON instead of loading server render partial views.

mdmoura commented 9 years ago

Also, please consider using angular with MVC/Web API in more RESTful way by loading content via JSON instead of loading server render partial views.

What do you mean? Did you see the example in: http://www.wintellect.com/devcenter/dbaskin/angularjs-mvc-cookbook-simple-routing

I am not sure how can Angular routes be used without MVC partials ...

Can you clarify?

brgrz commented 9 years ago

Yes, that's one way of doing it, which comes handy if you already have some partials set up that you used in standard ASP.NET MVC app and now you want to use them in SPA app.

However, there is another way and it basically comes down to implementing angular services which call serverside APIs which return JSON data and you'd work with that data in your angular controllers and feed it to clientside HTML/Handlebar templates. But it takes a lot more of Angular to learn.

mdmoura commented 9 years ago

However, there is another way and it basically comes down to implementing angular services which call serverside APIs which return JSON data and you'd work with that data in your angular controllers and feed it to clientside HTML/Handlebar templates. But it takes a lot more of Angular to learn.

Yes, but of course I am injecting Angular services in controllers to get data from APIs and so on ...

But when you use Angular ng-view directive you also use routes to change from view to view but you need to have server side routes so when you hit that route the correct ng-view is displayed and also indexed for SEO ...

What you suggesting, if I am not wrong, is: use MVC to render the page and then use only Angular Controllers / Services and Web API to render content on that page ... But imagine you have a Tree Menu on that page to move from section to section withing that page and you also want those sections to be indexed and available by inserting the url on the browser bar ...Then you need Angular Routing and MVC Routing sincronized with partial views ...

Am I missing something here?

brgrz commented 9 years ago

Those templateUrls you're defining do not need to point to ASP.NET MVC actions which return partial views, they can point to HTML template files on disk.

Your clientside routes should look like this:

$routeProvider.when('/en/about', { templateUrl: '/en/about', controller: 'aboutCtrl', });

$routeProvider.when('/pt/quem-somos', { // clientside route URL templateUrl: '/pt/quem-somos', // serverside template URL (can also be pointing to template file on disk) controller: 'aboutCtrl', });

Now when you navigate to /pt/quem-somos in your clientside Angular app it will load the template from templateUrl.

What you posted above had /About in both routes for clientside route URL..so how can a clientside app know which template do you actually want?

so actually you are kinda mixing up route URL with template URL and clientside/serverside.

brgrz commented 9 years ago

@Dresel I think you should close this issue because it is out of scope of why we need RouteLocalization. Implementing a dictionary to expose localized routes as JSON (or any serverside routes at all) in a way @mdmoura suggested would defeat the principles of clientside/serverside separation.