Routing in DNN SPA Module is not working as expected - dotnetnuke

I cannot seem to figure out how to access the methods on one of my controllers, the Settings controller works without issue...
ServiceRouteMapper:
public void RegisterRoutes(IMapRoute mapRouteManager)
{
mapRouteManager.MapHttpRoute(
moduleFolderName: "ImportantDatesModule",
routeName: "default",
url: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional },
namespaces: new[] { "company.ImportantDatesModule.Services" });
}
Controller:
[SupportedModules("ImportantDatesModule")]
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]
public class ItemController : DnnApiController
...
[HttpGet]
[ActionName("getItems")]
public HttpResponseMessage GetItems()
{
return Request.CreateResponse(HttpStatusCode.OK, "success");
}
JS file which is doing the call:
dnnspamodule.itemsViewModel = function (moduleId, resx) {
var service = {
path: "ImportantDatesModule",
framework: $.ServicesFramework(moduleId),
controller: "Item"
}
service.baseUrl = service.framework.getServiceRoot(service.path);
...
var getItems = function () {
var restUrl = service.baseUrl + service.controller + "/getItems";
console.log(restUrl);
isLoading(true);
var jqXHR = $.ajax({
url: restUrl,
beforeSend: service.framework.setModuleHeaders,
dataType: "json"
}).done(function (data) {
if (data) {
load(data);
isLoading(false);
}
else {
// No data to load
itemList.removeAll();
}
}).always(function (data) {
});
};

I don't know what your Settings controller looks like, but maybe try separating your routes into action style ({controller}/{action}) vs rest-style routes ({controller}/{id} + derived verb in the method name). Try this in your service route mapper:
mapRouteManager.MapHttpRoute(
moduleFolderName: "ImportantDatesModule",
routeName: "default",
url: "{controller}/{action}",
namespaces: new[] {"company.ImportantDatesModule.Services"});
mapRouteManager.MapHttpRoute(
moduleFolderName: "ImportantDatesModule",
routeName: "rest",
url: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
namespaces: new[] { "company.ImportantDatesModule.Services" });

Related

No action was found on the controller that matches the request angularjs GET

Can somebody please help me what am I missing or doing wrong. I am getting following error :
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:52096/api/Wotc/GetWotcDashBoardSummary?0=9&1=4&2=-&3=3&4=3&5=8&6=5&7=6&8=6&9=6'.","MessageDetail":"No action was found on the controller 'WotcAPI' that matches the request."}
wotcDashBoard.js :
var WotcDashBoardModule = angular.module('WotcDashBoardModule', []);
WotcDashBoardModule.factory('WotcDashBoardModuleService', ['$http', '$window', function ($http, $window) {
return {
GetDashBoardSummary: function (Ein) {
return $http({
url: '/api/Wotc/GetWotcDashBoardSummary',
method: 'GET',
params: Ein
});
}
};
}]);
WotcDashBoardModule.controller('WotcDashBoardController', ['$scope', 'WotcDashBoardModuleService', function ($scope, WotcDashBoardModuleService) {
var Ein = '00-00000';
WotcDashBoardModuleService.GetDashBoardSummary(Ein).then(function (response) {
$scope.Summary = response.data.Employees;
});
}]);
WotcAPIController :
[RoutePrefix("api/Wotc")]
public class WotcAPIController : ApiController
{
[HttpGet]
[Route("GetWotcDashBoardSummary")]
public async Task<IHttpActionResult> GetWotcDashBoardSummary(string Id)
{
CompanyWotcBO wotcSummary = new CompanyWotcBO();
try
{wotcSummary = await CompanyWotcBL.GetDashBoardSummary(Id);}
catch
{}
return Ok(new { WotcSummary = wotcSummary });
}
}
Route.config :
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Jobs",
url: "Jobs/{id}",
defaults: new { controller = "Jobs", action = "ShowJobPosting", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "HomeInit", id = UrlParameter.Optional }
);
}
}
This is because there is a parameter name mismatch.
Changed params: Ein to params: { id: ein } in wotcDashBoard.js.
code :
return {
GetDashBoardSummary: function (Ein) {
return $http({
url: '/api/Wotc/GetWotcDashBoardSummary',
method: 'GET',
params: { id: ein }
});
}
};
There are few things which I think need's fix:
Firstly: instead of url: '/api/Wotc/GetWotcDashBoardSummary',it should be something like url: 'http://www.example.com/api/Wotc/GetWotcDashBoardSummary/id', where example.com is the domain where you have hosted your service.
Secondly:
[RoutePrefix("api/Wotc")]
public class WotcAPIController : ApiController
{
[HttpGet]
[Route("GetWotcDashBoardSummary/{id}")]
public async Task<IHttpActionResult> GetWotcDashBoardSummary(string Id)
{
CompanyWotcBO wotcSummary = new CompanyWotcBO();
try
{wotcSummary = await CompanyWotcBL.GetDashBoardSummary(Id);}
catch
{}
return Ok(new { WotcSummary = wotcSummary });
}
}
You might have to enable CORS after doing this if you get any Cross-origin-request errors.

angular.js:13424 TypeError: $scope.entry.update is not a function. Updating the correct way with angularjs

I am trying to make an update to an existing object but get the following error $scope.entry.update is not a function.
I created a service called 'budgetResource'
"use strict";
angular.module("common.services").factory("budgetResource", ["$resource", "appSettings", budgetResource])
function budgetResource($resource, appSettings) {
return $resource(appSettings.serverPath + "api/budget/:id", null,
{
'update': { method: 'PUT', isArray: true },
'delete': { method: 'DELETE', isArray: true },
'save': { method: 'POST', isArray: true }
});
}
Herewith the function in my controller where budgetResource service is injected with the function $scope.updateBudgetAmount being called.
$scope.updateBudgetAmount = function (categoryId) {
$scope.entry = new budgetResource();
$scope.entry = {
"budgetAmount": $scope.budgetAmount,
"categoryId": categoryId
}
$scope.entry.update({ id: categoryId },
function (data) {
$scope.categories = data;
$scope.category = "";
},
function (error) {
$scope.message = error.statusText;
});
}
which in turn calls the webapi method
public IHttpActionResult Put(int id, [FromBody]Category cat)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
BudgetRepository repo = new BudgetRepository();
var categories = repo.SaveCategory(cat);
return Ok(categories);
}
How can modify this so that it is dine correctly?
After you do $scope.entry = {...},$scope.entry becomes a plain javascript object, so $scope.entry.update is not exist.

Angularjs, ui state routing to access spring data rest uri is going wrong

I have my spring data jpa resource and repositories are as shown below :
In my Student.java, I have
#ManyToOne
private Teacher teacher;
StudentResource.java
#RequestMapping(value = "students/byTeacherId/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public List<Student> getAllStudents(#PathVariable Long teacherId) {
return studentRepository.findAllByTeacher(teacherId);
}
StudentRepository.java
List<Student> findAllByTeacher(Long teacherId);
In Teacher.Java, I have
#OneToMany(mappedBy = "teacher")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Student> student = new HashSet<>();
In Angularjs the ui router state :
Student.js
.state('student.byteacher', {
parent: 'entity',
url: '/students/byTeacherId/{id}',
data: {
roles: ['ROLE_USER'],
pageTitle: 'traceApp.student.detail.title'
},
views: {
'content#': {
templateUrl: 'scripts/app/entities/student/students.html',
controller: 'StudentController'
}
},
resolve: {
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
$translatePartialLoader.addPart('student');
return $translate.refresh();
}],
entity: ['$stateParams', 'Student', function($stateParams, Student) {
return Student.getAll({id : $stateParams.id});
}]
}
})
I have my student factory as :
.factory('Student', function ($resource, DateUtils) {
return $resource('api/students/:id', {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
data = angular.fromJson(data);
return data;
}
},
'update': { method:'PUT' },
'getAll': { method:'GET' }
});
});
So from teacher.html, I have link for each teacher as:
<a ui-sref="student.byteacher(teacher.id)">Get My Students</a>
So I have expected to get all the students of the teacher when I click 'Get My Students' link in for a particular Teacher, but I am getting the following error. Can any one help me in fixing this error.
Error: [$resource:badcfg] Error in resource configuration for action `getAll`. Expected response to contain an object but got an array (Request: GET api/students)
http://errors.angularjs.org/1.4.4/$resource/badcfg?p0=getAll&p1=object&p2=array&p3=GET&p4=api%2Fstudents
minErr/<#http://localhost:8080/bower_components/angular/angular.js:68:12
resourceFactory/</Resource[name]/promise<#http://localhost:8080/bower_components/angular-resource/angular-resource.js:588:1
processQueue#http://localhost:8080/bower_components/angular/angular.js:14634:28
scheduleProcessQueue/<#http://localhost:8080/bower_components/angular/angular.js:14650:27
$RootScopeProvider/this.$get</Scope.prototype.$eval#http://localhost:8080/bower_components/angular/angular.js:15916:16
$RootScopeProvider/this.$get</Scope.prototype.$digest#http://localhost:8080/bower_components/angular/angular.js:15727:15
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://localhost:8080/bower_components/angular/angular.js:16024:13
done#http://localhost:8080/bower_components/angular/angular.js:10511:36
completeRequest#http://localhost:8080/bower_components/angular/angular.js:10683:7
requestLoaded#http://localhost:8080/bower_components/angular/angular.js:10624:1
Can you try without transforming the data from json to array. just return the json response and check.
The error is because the service is expecting a json object but after transformation array is being returned.

View is not displaying after Homecontroller is executed in asp.net mvc

I am trying to navigating from login page to Home page but it is not navigating to login page even though it is hitting HomeController, here i used angularjs http.get service for navigating.
I have verified RouteConfig settings, but am unable to find the problem where it is.
Below is route config
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
angular code
(function () {
var app = angular.module("AngularApp", []);
app.service("loginservice", function ($http) {
this.Checkuser = function (UserName, password) {
return $http({
method: "Post",
url: "Login/LoginUserAuth/",
data: { UserName: UserName, password: password }
});
}
this.NavigateToHome = function (UserName) {
return $http({
method: "get",
url: "Home/Index"
});
}
});
app.controller("LoginController", function ($scope, $http, loginservice) {
$scope.Checkuser = function () {
var checkresult = loginservice.Checkuser($scope.username, $scope.password);
checkresult.success(function (dataFromServer, status, headers, config) {
//alert(dataFromServer);
if (dataFromServer == '"Login Success"') {
var NavigateToHome = loginservice.NavigateToHome($scope.username);
}
else {
alert('Wrong UserName or Password');
}
});
checkresult.error(function () {
alert('Error in Login');
});
}
});
}
())
Home controller
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}

"Suggest slug name" API call in ngResource in AngularJS/Express app

I want the user to be able to set the slug name (URL) for a document in my app, but also I need some control so users don't override each other. It needs to be a separate call (not integrated with create/update) so the user can get visual feedback on their own slug name suggestions.
Therefore I've created a suggestSlug API call that takes an optional slug parameter as seed for the final slug name.
This is what my Express routes looks like:
app.get('/api/projects/suggestSlug/:slug', projects.suggestSlug);
app.get('/api/projects/suggestSlug', projects.suggestSlug);
app.get('/api/projects', projects.list);
app.get('/api/projects/:id', projects.show);
Now, I want to extend ngResource on the client side (AngularJS) to make use of this API:
angular.module('myapp.common').factory("projectModel", function ($resource) {
return $resource(
"/api/projects/:id",
{ id: "#id" },
{
update: { method: "PUT", params: { id: '#_id' } },
del: { method: "DELETE", params: { id: '#_id' } }
}
);
});
How do I extend the ngResource client to use my new API?
This was my solution: adding a separate $http-based method to my projectModel:
angular.module('myapp.common').factory("projectModel", function ($resource, $http) {
var projectModel = $resource(
"/api/projects/:id",
{ id: "#id" },
{
update: { method: "PUT", params: { id: '#_id' } },
del: { method: "DELETE", params: { id: '#_id' } }
}
);
projectModel.suggestSlug = function (slugSuggestion, callback) {
$http.get(
'/api/projects/suggestSlug/' + slugSuggestion
).success(callback).error(function(error) {
console.log('suggestSlug error:', error);
});
};
return projectModel;
});

Resources