ASP.NET 5 Routing with AngularJS Routing - javascript

I'm developing an application with ASP.NET 5 with AngularJS. I'm using basic client side HTML routing support provided by Angular. I've successfully implemented Angular Routing, the default routing in Startup class is
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Here is my Angular Routing
app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'static/home.html',
controller: 'AppController'
}).
when('/about', {
templateUrl: 'static/about.html',
controller: 'AppController'
}).
when('/contact', {
templateUrl: 'static/contact.html',
controller: 'AppController'
}).
when('/tutorial', {
templateUrl: 'static/tutorial.html',
controller: 'AppController'
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
}]);
It all works fine, but when I create another action in the same controller and wants to redirect to that action through URL, it redirect it to the same action i.e. Index
Here is my code for HomeController
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Web()
{
return View();
}
}
Routing happens in Index, but can't navigate to Web Action. What is the problem that I'm confronting. Thanks.

I think yaht the problem is that your application does not know anything about your Web method. To solve this you can:
1) use attribute routing, and
2) write direct route in your route configuration method.
Also check your web.config file for redirection in rewrite node of system.webServer section or any other redirection configurations
P.S. Be noted that if you redirects to another page your angular application will reconfigured and restarted. It takes some time. You should not use redirections ang all other page reloading methods if you want your app will be really cool. Try think in "angular" way. If you want to change part of the main content - angular will do it with routing. If you want to load some additional content and you want it looks like http://host/controller/method/submethod1/submethod2 url in browser - angular also can do it for you. You just need to place get() method inside your angular controller as the first step. In this case when angular will be resolving this controller it calls your get() method and loads data from server. So, you will have fast apllication with actual content always.
P.P.S. Try to use angular-ui-routing instead of default ng-route. ng-route is good, but it can not support subrouting well and also it has some other issues. angular-ui-routing solves all these messy things

Try this one to register your route,
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Try This:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then also try this below your config:
.controller('RootController', ['$rootScope', '$scope', '$route', '$routeParams', '$location', '$http',
function ($rootScope, $scope, $route, $routeParams, $location, $http) {
$scope.$on('$routeChangeSuccess', function (e, current, previous) {
$scope.activeViewPath = $location.path();
});
}]);
Hope this will help. =)

Related

Angular Route for specific url

I'm currently working on a MEAN stack project and am trying to get a specific template to display on a specific url.
Currently if users goto www.myurl/catalog, it loads the catalog.html template, as it would with any /catalog?catagory=productType url.
I would like it so that when users go to /catalog?category=specificProductType that it loads the catalogSpecific.html template. Currently, the catalog.html template supersedes the catalogSpecific.html template. I can't find much about this specific issue so any help would be appreciated.
Currently my routes look like this:
app/front/app.js
angular.module('app', ['ngRoute',
'app.LandingModule.controller',
'app.CatalogModule.controller',
'app.ProductModule.controller',
'app.HeaderModule.directives',
'app.FooterModule.directives'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'html/landing.html',
controller: 'LandingController'
})
.when('/catalog', {
templateUrl: 'html/catalog.html',
controller: 'CatalogController'
})
.when('/catalog?category=specificProductType', {
templateUrl: 'html/catalogSpecific.html',
controller: 'CatalogController'
})
.otherwise({
redirectTo: '/'
});
}]);
EDIT: Seems I was wrong about this not being possible with the default router. As Hadi describes in their comment, you can replace "templateUrl" with a function that returns a template url given the current route.
To my knowledge you cannot route the way that you want to with the built-in angular router.
As far as I can see you have two options to go with from here:
1: Learn to use the ui-router library (found here: https://github.com/angular-ui/ui-router)
2: Send all routes from /catolog to a controller/page that manually looks at your route-params and re-routes you based off of that manually. (see https://docs.angularjs.org/api/ngRoute/service/$routeParams)
Try use templateUrl function like to this. I have not tested.
templateUrl: function($location){
if($location.category)
return 'html/catalogSpecific.html';
else
return 'html/catalog.html';
},
Demo
I was able to figure this out following Hadi's example:
.when('/catalog', {
templateUrl: function($location){
if($location.category == "specificProductType") {
return 'html/catalogSpecific.html';
} else {
return 'html/catalog.html';
}
},
controller: 'CatalogController'
})

Why is $routeParams not working? Undefined

I'm triyng to build simple applications on Angular and Django rest framework.
I have a next root app:
app.js
angular
.module('sharePhotoApp', [
'ngRoute',
'sharePhotoApp.controllers',
'sharePhotoApp.services'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/',
controller: 'PostListController'
})
.when('/:username', {
templateUrl: '/user/',
controller: 'UserDetailController'
})
.otherwise({
redirectTo: '/'
});
}]);
And the next controller:
angular
.module('sharePhotoApp.controllers')
.controller('UserDetailController', UserDetailController)
UserDetailController.$inject = ['$scope','$routeParams','userService'];
function UserDetailController($scope, $routeParams, userService){
alert($routeParams.username);
$scope.user = userService.get({ username: $routeParams.username });
}
I tried to follow the next URL in browser: http://127.0.0.1:8000/user/#/admin
I suppose in this case should triggered route with username parameter.
But I've gotten undefined.
Could anyone explain where I done mistake?
"Note that the $routeParams are only updated after a route change
completes successfully. This means that you cannot rely on
$routeParams being correct in route resolve functions. Instead you can
use $route.current.params to access the new route's parameters."
https://docs.angularjs.org/api/ngRoute/service/$routeParams
Have you also installed ngRoute module?
As the description says, the route is not finished in your controller, so the params are also undefined.
$scope.$on('$routeChangeSuccess', function() {
// $routeParams should be populated here
});
should do the work.

angular-ui-router only loads template but not controller not loaded

I tried to migrate my Angular app from using ngRoute to uiRoute. Everything works fine except the controllers. They simple don't load like they did with ngRoute and I don't get why. As I see it from uiRoute it should work like with ngRoute but it doesn't. There is no exception thrown. I also don't find any example for a similar configuration like mine although it's very simple. I home somebody can tell me where my controller is hiding.
http://plnkr.co/edit/VGyi3AxgslgpvwBCTkXI?p=preview
So as for ngRoute the controller should be accessible through 'homepage' but it looks like it's just empty :(
;(function(angular) {
'use strict';
angular
.module('MainRouter', ['ui.router'])
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('home', {
url: '',
views: {
"mainView": {
templateUrl: 'home.html'
}
},
controller: 'HomepageCtrl',
controllerAs: 'homepage'
});
}]);
})(angular);
When you use views option inside the state definition, then ui-router engine doesn't look for templateUrl & controller defined in state level, basically you need to provide controller & templateUrl value from the namedView definition only. In your case you should add controller in mainView definition object.
Code
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('home', {
url: '',
views: {
"mainView": {
templateUrl: 'home.html',
controller: 'HomepageCtrl',
controllerAs: 'homepage'
}
},
});
}]);
Demo Plunkr

How to globally implement Authentication with AngularJS, Devise and UI Router?

I'm quite new to Angular so this might be a newbie question.
I'm trying to implement a simple task manager (just an exercise) with Rails as backend and Angular as frontend. So far I followed a tutorial and everything worked fine.
Now I want to globally implement Authentication. That means: When a user is not registered and logged in, she should see a splash page or the login page.
I don't want to do that in every single Angular controller, because DRY. So I figured the UI Router might be a good place. And I have a slight suspicion that maybe $httpProvider.interceptors might be useful.
This is how far I got. I can check if a user is authenticated and prevent the page from loading. But nothing more. How would I go from here? Are there any good tutorials out there I missed?
This question on Stackoverflow goes in a similar direction but doesn't solve my problem since they are not using Devise.
Thanks!
// app.js
var app = angular.module("TaskManager", ['ui.router', 'templates', 'Devise'])
.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider){
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home/_home.html',
controller: 'MainCtrl',
resolve: {
projectPromise: ['projects', function(projects) {
console.log($rootScope);
return projects.getAll();
}]
}
})
.state('projects', {
url: '/projects/{id}',
templateUrl: 'projects/_projects.html',
controller: 'ProjectsCtrl',
resolve: {
project: ['$stateParams', 'projects', function($stateParams, projects) {
return projects.get($stateParams.id);
}]
}
})
.state('login', {
url: '/login',
templateUrl: 'auth/_login.html',
controller: 'AuthCtrl',
onEnter: ['$state', 'Auth', function($state, Auth) {
Auth.currentUser().then(function() {
$state.go('home');
})
}]
})
.state('register', {
url: '/register',
templateUrl: 'auth/_register.html',
controller: 'AuthCtrl',
onEnter: ['$state', 'Auth', function($state, Auth) {
Auth.currentUser().then(function() {
$state.go('home');
})
}]
});
$urlRouterProvider.otherwise('home');
}
]);
// run blocks
app.run(function($rootScope, Auth) {
// you can inject any instance here
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
if(!Auth.isAuthenticated()) {
// So the magic should probably happen here. But how do I implement this?
// And how do I allow users to access the /login and /register page?
event.preventDefault();
}
})
});
I wrote an article that basically answers this question (at a high level at least) called How to Set Up Authentication with AngularJS and Ruby on Rails.
If you want to check whether the user is authenticated at any particular route, you can (in Angular's standard router, although I don't know about ui-router) use resolve. Here are a couple routes from an older project of mine:
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
isPublic: true
})
.when('/today', {
templateUrl: 'views/announcements.html',
controller: 'AnnouncementsCtrl',
resolve: {
auth: ['$auth', function($auth) {
return $auth.validateUser();
}]
}
})
The root route is public but /today requires authentication. Maybe that gives you enough to go on for ui-router as well. Side note: I should really update my article to account for ui-router (or Angular's new router) since I don't think many people use the regular old Angular router.
Edit: I remembered this thing from a different project of mine. This is CoffeeScript. Irrelevant code omitted.
"use strict"
angular.module("fooApp", [
"ngAnimate"
"ngCookies"
"ngResource"
"ngRoute"
"ngSanitize"
"ngTouch"
"ui.router"
"ng-token-auth"
])
.run ($rootScope, $auth, $location) ->
$rootScope.$on "auth:login-success", -> $location.path "/"
$rootScope.$on "auth:logout-success", -> $location.path "/sign-in"
$rootScope.$on "$stateChangeStart", (event, next) ->
$auth.validateUser().then (->
if $location.path() == "/"
$location.path "/file-uploads"
), ->
if !next.isPublic
$location.path "/sign-in"
Hopefully it's kind of self-evident what's going on there. This project DOES use ui-router, as you can tell from the $stateChangeStart.

AngularJS relative url routing issue

I have my backend web framework loading my AngularJS app with following URL
http://localhost/New/Alpha/App
I also have it set up so that anything after App will still load the same thing
http://localhost/New/Alpha/App/home
http://localhost/New/Alpha/App/settings
...
I'm trying to make my AngularJS app to work in the way that it would pick up the bit of URL after App and load a controller/template accordingly. I have a problem with routing in my AngularJS app though
var main = angular.module("main", ["ui.bootstrap", "ngRoute"]);
main.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("home", {
templateUrl: "assets/tpl/home.html",
controller: "mainController"
})
.otherwise({
redirectTo: "fail"
});
$locationProvider.html5Mode(true);
});
main.controller("mainController", function($scope) {
console.log("home")
});
If I try this URL
http://localhost/New/Alpha/App/home
it changes the URL to
http://localhost/fail
instead of leaving the URL as it is and loading the template/controller. If however I change the config and give it a full relative URL it does work as supposed to
.when("/New/Alpha/App/home", {
templateUrl: "assets/tpl/home.html",
controller: "mainController"
})
My problem is, that the part of URL before App - /New/Alpha cannot be hardcoded in. It could be /New/Beta, /New/Gamma, etc.
Is what I want to do possible at all without hardcoding the full relative URL match?
UPDATE Sorry, forgot to mention that the number of URL segments before App can change, as in it could be /New/Beta/App and it also could be /New/Another/Beta/App. I don't suppose something like */App or /New/*/App is possible instead of /New/:placeholder/App?
Will this work for you?
var main = angular.module("main", ["ui.bootstrap", "ngRoute"]);
main.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/New/:greek/App/home", {
templateUrl: "assets/tpl/home.html",
controller: "mainController"
})
.otherwise({
redirectTo: "fail"
});
$locationProvider.html5Mode(true);
});
main.controller("mainController", function($scope) {
console.log("home")
});
You could then retrieve the greek with $routeParams.greek from within your controller.
The general solution to this problem is to have the server pass the app URL to your client-side code. In other words, use server-side code to dynamically write the equivalent of the following on the page:
var appUrl = '/New/Alpha/App';
Then setting up the route provider becomes:
main.config(function($routeProvider, $locationProvider) {
$routeProvider
.when(appUrl + "/home", {
templateUrl: "/assets/tpl/home.html",
controller: "mainController"
})
.otherwise({
redirectTo: appUrl + "/fail"
});
$locationProvider.html5Mode(true);
});
That way the knowledge of the application base URL lives in one place — server-side (which makes sense as only the server is in a position to truly know, if you think about it).
In your specific case, if the application base URL is implicit in the URL structure, you could calculate the following client-side:
var appUrl = window.location.pathname.match(/^\/New\/.*\/App/);
Needs work, but you get the idea. Then you can set up the route provider exactly as above.

Categories

Resources