How to config routeProvider with MVC4 and WebAPI2 - asp.net-mvc

I have a small app that shows a calendar with some events.
When I click on one of the events I would like to show details of the selection below the calendar.
The events' urls are generated within a loop like this :
'url': '#/concerts/' + data[idx].id
and my config is the following:
var app = angular.module('EventsApp', ['ngRoute']);
app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider.
when('/concerts/:eventId', {
templateUrl: '/Views/Home/ng-view/details.html',
controller: 'EventCtrl'
}).
otherwise({
redirectTo: '/'
});
}]);
My Index.cshtml:
<div id="bodyApp" ng-app="EventsApp">
<div class="mainBody" ng-controller="EventCtrl as event" ng-init="event.getAllConcerts()">
<div class="search">
<input type="search" />
</div>
<div class="calendar">
<div id="calendar">
</div>
</div>
<div class="crudSection" ng-view>
</div>
</div>
At the moment I am just trying to get the details.html to be shown, but It doesn't redirect. The url is updated with the proper one but my view is not refreshed.
Also, How should the routeProvider config to do a webapi call without exposing the '/api/{controller}/{id}' info?
Edit.: I tried with the standard MVC route '/Home/{action} and a partialview and it works, but not a '/Home/{action}/{id}', so I think I'm missing something about how to combine both routings.

I found the solution in the following link:
AngularJS - How to use $routeParams in generating the templateUrl?
app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider.
when('/concerts/:eventId', {
templateUrl: function (params) { return '/Home/Details/' + params.eventId; },
controller: 'EventCtrl'
}).
otherwise({
redirectTo: '/'
});
}]);

Related

Rails + Angular : Issue with directive

I have Rails 4.2.4 and Angular 1.4.8.
I am trying define a directive:
index.html:
<div ng-app='myApp' ng-controller='myController'>
<foo bar='bar'></foo>
</div>
app.js:
angular.module('myApp', ['templates']);
angular.module('myApp', ['templates']).directive('foo', function(){
return {
restrict: 'AE',
scope: {
bar: '='
},
templateUrl: 'bar.html'
}
});
angular.module('myApp').controller('myController', function($scope, $http){
$scope.bar = "XMan";
});
bar.html:
<h1> Hi {{ bar }}! </h1>
<ng-include src="'{{bar}}.html'"
XMan.html:
<p>Hello I'm XMan</p>
Here I am expecting my foo directive to render
<h1> Hi X Man! </h1>
<p> Hello I'm XMan </p>
but I am getting
<h1> Hi {{ bar }}! </h1>
<!-- ngInclude: undefined -->
What is wrong with my approach. Please guide me; I am very new to Angular.js.
I got a solution. We cannot bind ng-include src with scope variable.
Instead I used function call to get the source then it works!
That is I changed
<ng-include src="'{{bar}}.html'"
to
<ng-include src="barUrl()"
and added a controller scope function:
$scope.barUrl = function(){
return $scope.bar + '.html'
}

Quick Search Form Not Submitting MVC

I currently have a partial view that renders at the top of every page on the site. The point of this partial view is to provide a form that lets the user do a quick search. I have set the partial view form up as follows:
#using (Html.BeginForm())
{
<div class="col-md-7" style="text-align: right">
<div class="input-group input-group-sm col-sm-6 pull-right">
#Html.TextBox("caseReference")
<button type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
}
#Html.Partial("_MainNavigation")
</div>
</div>
</nav>
<script type="text/javascript">
$(function () {
$("form").on("submit", function (event) {
event.preventDefault();
var request = { caseReference: $('#caseReference').val() };
submitForm(request, '#Url.Action("CaseSearch", "QuickSearch", new { area = "Search" })');
});
});
</script>
However under the page source the form action renders as a request to the home page with a post action. I have read numerous examples and this task seems very straight forward. Would it be a better idea to use the parameters on the #html.BeginForm() method?
So after spending a few hours researching, I have finally got the quick search functionality to work on the home page of my site. In the razorview I have the following code:
<div class="input-group input-group-sm col-sm-6 pull-right">
#Html.Kendo().MaskedTextBox().Name("name").Mask("000000/0000").Deferred()
<button id="search" type="submit">
<i class="fa fa-search"></i>
</button>
<script type="text/javascript">
$(function () {
$("#search").on("click", function (event) {
event.preventDefault();
var value = $('#name').val();
value = value.replace(/[/]/g, "_");
var refVal = value;
var url = '#Url.Action("Action", "Contoller", new { area = "Area" })' + '//' + refVal;
$.ajax({
type: 'GET',
url: url,
cache: false,
dataType: 'json',
contentType: "application/json;",
success: function (result) {
if (result.success) {
window.location.href = result.url;
}
else {
bootbox.alert(result.message);
}
}
});
});
});
However in regards to the following line:
var url = '#Url.Action("Action", "Contoller", new { area = "Area" })' + '//' + refVal;
If I hard code the url and append the search term it works on the Home page because we are at the root directory but from other pages it fails, To get around this I tried to use #Url.Action. However this is producing the following result in the html soure code:
var url = '' + '//' + refVal;
Is there a certain way to use the URL.Action method from withing JS?

Rails CSRF token issue in Angular routes

I am using AngularJS routes with rails. For authencation I am using using Angular Devise directive. I am facing some issue with CSRF token.
User Controller
function userController($scope,$http,$route,$location,Auth,User) {
$scope.login = function(){
Auth.login($scope.user).then(function(user) {
User.setCurrentUser(user);
$location.path("/logout");
}, function(error) {
// Authentication failed...
});
}
$scope.logout = function(){
Auth.logout().then(function() {
$location.path("/logout");
}, function(error) {
// An error occurred logging out.
});
}
}
Angular Routes.js
myApp.config(function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when("/login",
{ templateUrl: "/assets/user/login.html",
controller: "userController" })
.when("/logout",
{ templateUrl: "/assets/user/logout.html",
controller: "userController" })
.otherwise({ redirectTo: "/login" });
});
Templates/login.html
<div>
<label for="user_email">Email</label><br>
<input autofocus="autofocus" ng-model="user.email" id="user_email" name="user[email]" type="email" value="">
</div>
<div>
<label for="user_password">Password</label><br>
<input autocomplete="off" ng-model="user.password" id="user_password" name="user[password]" type="password">
</div>
<div>
<input name="commit" type="submit" ng-click="login()" value="Sign in">
</div>
Templates/logout.html
LOGOUT
When I click on Sign-in button which call login() function with user datas and login was successful , after that logout.html page is rendered using angular routes ($location.path) , if I click on logout button logout.html , it throws following error.
ActionController::InvalidAuthenticityToken
Since the authtoken was already used by login action and its no more valid. I am not sure how to generate new one with IN angularJS , If I refresh the page the logout is working.
I replaced
gem 'ng-rails-csrf' to gem 'angular_rails_csrf'
It started working , but I am not sure why Angular devise suggested "ng-rails-csrf" , which not refreshing the token. Simply adding 'angular_rails_csrf' did the trick.

ASP.NET MVC and AngularJS

I am using AngularJS 1.2.2 (and am totally new to it) and MVC 5. I am trying to get a controller get called but it is not working.
As far as I could tell, the most appropriate 'shell' page is Views/Shared/_Layout.cshtml.
Therefore, in this page I have
<html data-ng-app="myApp">
Latter on in the Views/Shared/_Layout.cshtml I have
<div class="navbar navbar-fixed-top">
<div class="container">
<ul class="nav nav-pills" data-ng-controller="NavbarController">
<li data-ng-class="{'active':getClass('/home')}">Home</li>
<li data-ng-class="{'active':getClass('/albums')}">Albums</li>
</ul>
</div>
</div>
But when I click on either of these two links my getClass method does not get called. The file containing this method is being refernced. Here is the code it contains
app.controller('NavbarController', function ($scope, $location) {
$scope.getClass = function(path) {
if ($location.path().substr(0, path.length) == path) {
return true;
} else {
return false;
}
};
});
Any idea why this is not being called?
EDIT
My structure is such:
I have an app folder in the root.
In the app folder I have an app.js with this code
var app = angular.module('myApp', []);
app.config(function ($routeProvider) {
$routeProvider
.when('/Home',
{
controller: 'HomeController',
templateUrl: '/Views/Home/Index.cshtml'
})
.when('/Album',
{
controller: 'AlbumController',
templateUrl: '/View/Album/Index.cshtml'
})
.otherwise({ redirectTo: '/Home' });
});
(Incidentally I am guessing that by referring to my individual cshtml files like this I will get the correct behavior).
I have a controllers folder with the above NavbarController class.
I also have a services folder with my services in them.
In the _Layout file I have these js files referenced
#Scripts.Render("~/Scripts/angular.js")
#Scripts.Render("~/Scripts/angular-route.js")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
#Scripts.Render("~/app/app.js")
#Scripts.Render("~/app/controllers/navbarController.js")
#Scripts.Render("~/app/controllers/albumController.js")
#Scripts.Render("~/app/services/albumService.js")
There is an error in the console. It is
Error: [$injector:modulerr] Failed to instantiate module myApp due to: [$injector:unpr] Unknown provider: $routeProvider http://errors.angularjs.org/1.2.2/$injector/unpr?p0=%24routeProvider ...
It looks like you missed to include the ngRoute module in your dependency for myApp.
'use strict';
angular.module('myApp', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
//Your code
}]);

Selector [ng\:model="query"] did not match any elements

Why am I getting this error: Selector [ng\:model="query"] did not match any elements
I've read through this: AngularJS: End to End Testing Issue , but that link doesn't really apply in a .net env:
IDE: Visual Studio 2012
Project type: ASP.NET MVC4
File strucure:
Running CI tests through karma start e2e.conf.js in node.js command prompt
My karma conf:
basePath = '../../../';
files = [
ANGULAR_SCENARIO,
ANGULAR_SCENARIO_ADAPTER,
'angular/app/*.js',
'angular/Tests/e2e/*.js'
];
reporters = ['progress'];
port = 10876;
runnerPort = 10100;
colors = true;
logLevel = LOG_ERROR;
autoWatch = true;
browsers = ['Firefox'];
captureTimeout = 60000;
singleRun = false;
proxies = {
'/': 'http://localhost:60607/'
};
My e2e test:
describe('E2E: AMS', function () {
describe('Settings Users', function () {
beforeEach(function () {
browser().navigateTo('/#/settings/users');
});
it('filters the users list as the user types into the search box', function () {
expect(repeater('.users li').count()).toBe(2);
input('query').enter('abc');
expect(repeater('.users li').count()).toBe(1);
input('query').enter('efg');
expect(repeater('.users li').count()).toBe(1);
input('query').enter('ijk');
expect(repeater('.users li').count()).toBe(0);
});
});
});
My View:
<div data-ng-view="">
Add User: <br />
<input type="text" /> <button>Submit</button><br />
Search:
<input data-ng-model="query" type="text" />
Users <br />
<ul class="users">
<li data-ng-repeat="user in users | filter:query">
{{user.name}}
</li>
</ul>
</div>
and for grins, my route
angular.module('AMS', []).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/login', { templateUrl: '/AccessControl/Login/', controller: settingsController }).
when('/dashboard', { templateUrl: '/Dashboard/Dashboard', controller: dashboardController }).
when('/settings', { templateUrl: '/Settings/Settings', controller: settingsController }).
when('/settings/users', { templateUrl: '/Settings/Users', controller: settingsController }).
otherwise({ redirectTo: '/dashboard' });
}]);
It looks like the angular e2e testing api is looking for "ng-model" in your view instead of the "data-ng-model" that you're using.
My understanding is that both are valid, but give that a try to see if that's the problem.
Not an answer, so I wont mark it as such, this is more of a work around.
I've decided to go with chutzpah in order to run the jasmine unit tests, and specflow.xunit for "e2e" testing. It works well in a .net environment and integration into teamcity seems straight forward.

Resources