WebApi 404's with Parameters - calling via javascript GET - javascript

WebApi Method within LocationsController:
public async Task<IHttpActionResult> GetLocations(int id, long start, long end)
{
return Ok();
}
Calls I have tried to make (GET):
https://api.com/Locations/GetLocations/34934/1/1
https://api.com/Locations/GetLocations?34934&start=1&end=1
As such:
factHttp.httpRequest('/locations/GetLocations', 'GET', vm.ID + '/' + start.getTime() + '/' + now.getTime()).then(function (_result) {
vm.plots = angular.fromJson(_result.data);
});
var _httpRequest = function requestCall(requestPartURL, requestType, requestPayload) {
var _resultHttp = $http({
url: apiURL + requestPartURL,
method: requestType,
data: requestPayload,
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('ACCESS_TOKEN')
}
}).success(function (response) {
console.log("HTTP CALL SUCCESS");
return {
result: 'SUCCESS',
resultObj: response,
errorCode: '',
errorDesc: ''
}
}).error(function (response) {
console.log("HTTP CALL FAIL");
console.log(response);
return getErrorObj(response);
});
return _resultHttp;
}
Routing:
config.Routes.MapHttpRoute(
"IdentWithRange",
"{controller}/{action}/{id}/{start}/{end}"
);
If I change the web api method to just take (int id) and call GetLocation/34934 it works just fine. What have I done wrong here?
I continually get a 404 error. Some of this was not written by myself (namely the JS stuff as I am bad at it), but it's the first time working with any sort of api for me, where I control both ends, I'm a bit stuck.

The routing record you created would be looking for the following route
/api/controller/id/start/end
but you are trying to pass in parameters, not specify a route. You dont need a special routing record to handling multiple parameters. Using a 'standard' routing record will suffice.
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new
{
id = RouteParameter.Optional, action = "DefaultAction"
});

Currently you need to add "api" to your route.
https://api.com/api/Locations/GetLocations/34934/1/1
Recommended:
https://api.com/api/locations/34934/1/1
[HttpGet, Route("locations/{id:int:min(1)}/{start:long}/{end:long}")]
public async Task<IHttpActionResult> GetLocations(int id, long start, long end)
{
return Ok();
}

Related

jQuery $.AJAX to replace with JavaScript fetch - mvc4 method arguments are always null

We had a working jQuery script which calls an MVC4 C# controller method like this:
// C# controller method
public ActionResult MyMethod(String text, String number)
{
... do something ...
... returns a partial view html result ...
}
// javascript call
var myData = { text:"something", number: "12" };
$.ajax({ url:ourUrl, type:"GET", data: myData,
success: function(data) { processAjaxHtml( data )}});
Now we want to replace this $.ajax call to a native fetch(...) call like this (and use a Promise):
function startAjaxHtmlCall(url) {
var result = fetch( url, {method: "GET", body: myData});
return result.then( function(resp) { return resp.text(); });
}
starAjaxCall(ourUrl).then( resp => processAjaxHtml(resp) );
We have problems, and somehow we cannot find the answers:
using GET we cannot attach body parameters (I see that the html GET and POST calls are quite different, but the $.ajax somehow resolved this problem)
we changed the GET to POST but the controller method still got "null"-s in the parameters
we changed the fetch call to "body: JSON.stringify(myData)" but the method still gots null
we constructed a temp class with the 2 properties, changed the method parameters as well - but the properties still contains null
we added to the [FromBody] attribute before the method class parameter but it got still nulls
we replace body: JSON.stringify(myData) to body: myData - still the same
Note: we tried this in Firefox and Chrome, the code is MVC5, C#, .NET Framework 4.5 (not .CORE!) hosted by IIS.
We changed the javascript call as the following (and everything works again):
var promise = new Promise((resolve, reject) => {
$.ajax({
url: url,
method: method,
data: myData,
success: function(data) { resolve(data); },
error: function(error) { reject(error); },
});
});
return promise;
// note: .then( function(resp) { return resp.text(); }) // needs no more
So: what do we wrong? what is the information we do not know, do not understand about fetch? How to replace $.ajax to fetch in this situation correctly? can it works with GET again? how to modify the controller method to receive the arguments?
GET requests do not have a BODY, they have querystring parameters. Using URLSearchParams makes it easy
var myData = { text:"something", number: "12" };
return fetch('https://example.com?' + new URLSearchParams(myData))
.then( function(resp) { return resp.text(); })
Other way of building the URL
const url = new URL('https://example.com');
url.search = new URLSearchParams(myData).toString();
return fetch(url)...
If you were planning on sending JSON to the server with a post request
fetch('https://example.com', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(myData)
});

angularjs$http.get and java api call

I'm trying to make an angularjs $http.get request with parameters but it's not working due to syntaxt may be. Can you please
confirm what i'm doing wrong , maybe syntax is wrong in angularjs call or in java api method
$http.get(document.requestPathPrefix + "/home/my-api",
$scope.requestParametersObject
).then(
function(response) {
$scope.output = response.data;
},
function(response) {
$scope.retrieveErrorMssg = "Failed to retrieve required data.";
});
my parameters are like in this image
parameter object for api call
And in java api call like this
#RequestMapping(value = "/my-api", method = RequestMethod.GET)
public ResponseEntity<Collection<MyObjectResponse>> getMyObjResponse(#RequestBody final MyObjectRequest request)
{
Map<Integer,MyObjectResponse> oResponse = new HashMap<>();
try {
//Manipulation and db calls
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return new ResponseEntity<Collection<MyObjectResponse>>(oResponse.values(), HttpStatus.OK);
}
try ,
$http({
url: '/home/my-api',
method: "GET",
headers: {
'Content-type': 'application/json'
},
data: JSON.stringify(request)
}).success(function(data, status, headers, config) {
}).error(function(data, status, headers, config) {
return null;
});
If you are worried about syntax, take a look at this simple example and modify it to your need.
In JS, your http.get call should contain the URL and its parameters if any,
$http.get('getUserInfo',
{
params : {
'userEmail' : 'userEmail'
}
}).then(function(response) {
console.log(response);
});
If you are passing a parameter to the API call, ensure your Java controller or the service has the parameter defined to receive the same. Ideally the parameters should match between the call and the provider
For example, for the above API call, the spring controller should like below,
#RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
public #ResponseBody User getUserInfo(
#RequestParam("userEmail") String userEmail) {
// Do Something
}

How to pass filter params from angularjs to spring restcontroller with #MatrixVariable

I am not able to find a way to use angularjs's $http.get to pass filter params.
Url is:
http://localhost:8080/template/users/query;username=abcd;firstName=ding...
RestController is:
#RequestMapping(value={"/users/{query}"}, method=RequestMethod.GET)
public ResponseEntity<List<User>> queryUsers(#MatrixVariable(pathVar="query") Map<String, List<String>> filters) {
....
}
When I use the above Url directly in the browser it is working fine. However when I try to call the same using Angularjs's $http.get it is not working.
Angularjs code:
this.searchUser = function() {
var queryStr = '';
for (var key in userObj.search) {
if (userObj.search[key]) {
queryStr += ";" + key + "=" + userObj.search[key];
}
}
console.log('Url ', 'users/query' + queryStr);
if (queryStr === "") {
alert("No filters specified");
return false;
}
$http.get('users/query', angular.toJson(userObj.search)).then(function successCallback(response) {
if (response.data.errorCode) {
console.log(response);
alert(response.data.message);
} else {
console.log('Successfully queried for users ', response.data);
userObj.users = response.data;
}
}, function errorCallback(response) {
console.log('Error ', response);
alert(response.statusText);
});
};
When I call this method: I get the error as
errorCode: 400
message: "Failed to convert value of type [java.lang.String] to required type [long]; nested exception is java.lang.NumberFormatException: For input string: "query""
Even I tried to pass the query string as it is mentioned in the above URL, but still the same error. I am sure it is not even entering inside the RestController method.
How to solve this?
Using get,you can not pass JSON.
You should prepare object if you want to passed it a query string.
var queryStr = {};
for (var key in userObj.search) {
if (userObj.search[key]) {
queryStr[key] = userObj.search[key];
}
}
And your HTTP#GET call should be like this :
$http.get('users/query', {params: queryStr}).then(...
OR
$http({
url: 'users/query',
method: "GET",
params: queryStr
});

Angular $http service cache not working properly

I have a $http service in angular js which has a cache enable for it. When first time load the app service gets call and get cache. Now when i call the service anywhere from the same page the data comes from cache but when i change the page route and again call the service from another page the data come from server(i am just changing the route not refreshing the page)
Edit =>
Code was working !! On route the data also came from cache but it took more time as there are few other call as. It just took more time then i accepted the cache to respond .If i call same from any click event then it will take 2ms to 3ms
here is my service
commonServicesModule.service('getDetails', ['$http', 'urlc',
function($http, urlc) {
return {
consumer: {
profile: function(id) {
return $http({
url: urlc.details.consumer.profile,
cache: true,
params: {
'consumer_id': id,
'hello': id,
},
method: 'GET',
}).success(function(result) {
return result;
});
},
}
}
}
])
Call from controller :
start = new Date().getTime();
/*get user information */
getDetails.consumer.profile('1').then(function(results) {
console.log('time taken for request form listCtrl ' + (new Date().getTime() - start) + 'ms');
});
when i call this from anywhere else after route it take the same time.
Try moving the consumer object into the body of the function, and return a reference to it, like so:
commonServicesModule.service('getDetails', ['$http', 'urlc', function($http, urlc) {
var getConsumer = {
profile: function(id) {
return $http({
url: urlc.details.consumer.profile,
cache: true,
params: {
'consumer_id': id,
'hello': id,
},
method: 'GET',
}).success(function(result) {
return result;
});
}
};
return { consumer: getConsumer };
}]);

AngularJS 1.2.0 $resource PUT/POST/DELETE do not send whole object

I'm using angularjs 1.2.0 with $resource. I would like to have some PUT/POST instance actions that doesn't send the whole object to the server but only some fields and in some cases totally no data.
Is it possible? I searched everywhere but couldn't find anything
UPDATE:
It also happens with DELETE requests:
Given this code:
group.$deleteChatMessage({messageId: message.id}, function(){
var i = _.indexOf(group.chat, message);
if(i !== -1) group.chat.splice(i, 1);
});
The request is this:
See how the whole model is sent (under "Request Payload").
This is the resource:
var Group = $resource(API_URL + '/api/v1/groups/:gid',
{gid:'#_id', messageId: '#_messageId'},
{
deleteChatMessage: {method: "DELETE", url: API_URL + '/api/v1/groups/:gid/chat/:messageId'},
});
This works for me:
$resource(SERVER_URL + 'profile.json',
{},
{
changePassword :
{
method : 'POST',
url : SERVER_URL + 'profile/changePassword.json',
// Don't sent request body
transformRequest : function(data, headersGetter)
{
return '';
}
}
});
You could customise exaclty what is sent to the server by implementing your own code in the transformRequest function. In my example I was adding a new function to the REST client, but you can also overwrite existing functions. Note that 'transformRequest' is only available in version 1.1+
You can use $http for that specifically. However, I have one case I use for a project that might help. Also my example is returning an array from the server but you can change that.
In my service:
app.factory('mySearch', ['$resource', function($resource) {
return $resource('/api/items/:action', {}, {
search: { method: 'POST', isArray: true,
params: { action: 'search' }
}
});
}
]);
In my Controller:
I can build up custom params to post to server or if its only two fields I need from a table row the user selects.
var one = "field_one";
var two = "field_two";
$scope.search({one: one, two: two});
Then I can post those through an event and pass the custom params
$scope.search = function(customParams) {
mySearch.search({query: customParams}, function(data) {
$scope.items = data;
}, function(response) {
console.log("Error: " + response.status);
})
};
Hopefully this was some help. Let me know if this is close to what your looking for and I can help more.
POST
DELETE

Categories

Resources