Not hitting with Web API two different GET methods - angularjs

Implemented webapi routing and having two different route methods for for retrieving values but it is differentiated by supplying parameter type.
Api methods are getting hit for the corresponding action methods if we simply specify "apiurl/api/contact/search/sri" and "apiurl/api/contact/get/2" in direct browser url.
But when comes to communicate with angular to webapi, api is not getting hit.
//angular service
contact.search = function (inputName) {
return $http({
method: 'GET',
url: url + 'api/contact/search',
//params: { name: inputName }
data: { name: inputName }
});
//return $http.get(url + 'api/contact/search', name);
}
//WebAPI
[HttpGet]
[Route("search/{name:alpha}")]
public IHttpActionResult GetContacts([FromBody]string name)
{
repository = new ContactRepository();
if (string.IsNullOrEmpty(name))
{
var message = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Search Name can not be empty")
};
throw new HttpResponseException(message);
}
return Ok(repository.GetContact(name));
}
// GET api/contact/5
[HttpGet]
[Route("get/{id:int}")]
public IHttpActionResult Get(int id)
{
repository = new ContactRepository();
if (id == 0)
{
var message = new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent("Issue with Passed Id Parameter.") };
throw new HttpResponseException(message);
}
return Ok(repository.GetContact(id));
}

When you use data: { name: inputName }, it is appended to the url in the following way:
...api/contact/search?name=inputName
but what you want is this:
...api/contact/search/inputName
So, you have two options.
Either change your angular code:
return $http({
method: 'GET',
url: url + 'api/contact/search/' + inputName,
});
or change your API to accept QUERY params.
Hope it helps

Related

POST request not getting mapped to Spring MVC Controller

I am sending a POST request from Angularjs $http service . It is working fine when my promise is like below and is getting properly mapped to Spring Controller ,
service.js
reassignKsaPendingLeads : function(data,username)
{
var promise = $http({
url : "reassignPendingLeads.htm",
method : "POST",
data : mydata
})
.success(function(data, status, header, config, statusText)
{
}
}
Spring Controller
#RequestMapping({ "reassignPendingLeads.htm" })
public #ResponseBody String updateAccessStatus(#RequestBody List<KsaLead> ksaLeads)
{
log.info("Inside updateAccessStatus");
return "true";
}
The json object i pass from service.js is getting mapped properly to #RequestBody List ksaLeads.
Since the json object contains same keys as bean properties of KsaLead.
But Now i want to pass another parameter username apart from json body (data).
Then i get Request method 'POST' not supported in Spring Controller .
new service.js
reassignKsaPendingLeads : function(data,username)
{
var mydata = JSON.stringify(data) + '&username=' + username;
var promise = $http({
url : "reassignPendingLeads.htm",
method : "POST",
data : mydata
})
.success(function(data, status, header, config, statusText)
{
}
new Spring Controller
#RequestMapping({ "reassignPendingLeads.htm" })
public #ResponseBody String updateAccessStatus(#RequestBody List<KsaLead> ksaLeads,#RequestParam String username)
{
log.info("Inside updateAccessStatus");
return "true";
}
Can anyone guide me as to how should i pass data from angularJs so that it gets mapped correctly to Spring Controller
I would assume that you want to pass the username as a request parameter. In order to do this, the $http can have a params input field:
function(data,username) {
var promise = $http({
url: "reassignPendingLeads.html",
method: "POST",
data: data,
params: { username: username }
})
// continue with your promise here
}
If you want to pass it inside the request body we have to do the following steps:
We have to add the username to the mydata object.
// we assume that data is not a primitive type
function(data,username) {
var mydata;
// check if data is defined
if (data) {
// make a deep copy first, since we don't want to modify the input
mydata = angular.copy(data);
} else {
// if the data is undefined, create e new object
mydata = {};
}
// add the username to mydata
mydata.username = username;
var promise = $http({
url: "reassignPendingLeads.html",
method: "POST",
data: mydata
})
// continue with your promise here
}
On the back-end we have to make sure that we can accept this kind of data. For this it is advised to create a data class which holds the username and any other fields which may appear on your data object from the front-end.
Probably something like this:
public class MyDataClass {
private String username;
// other fields
// no args constructor
public MyDataClass() {}
// all args constructor
public MyDataClass(String username) {
this.username = username;
}
// getter and setters
}
Now we modify the controller to accept it:
#RequestMapping(value = "reassignPendingLeads.htm", method = RequestMethod.POST)
public #ResponseBody String updateAccessStatus(#RequestBody MyDataClass data)
{
log.info(data.getUsername());
return "true";
}

Angular $resource and webApi

I am using webApi and have generated the model using entityframework the overload method of the GET(int id) I am trying to call that using the query of the $resource
I am trying to pass an optional parameter to a call using the $resource but get the error [$resource:badcfg] I have had a google and people say add
{
'get': {method: 'GET'},
'query': {method: 'GET', isArray: true}
}
into the function, so I have tried this: but still have no luck.
function minorResource($resource, appSettings) {
return $resource(appSettings.serverPath + "/api/minorworks/:id",
{
'get': {method: 'GET'},
'query': {method: 'GET', isArray: true}
});
}
Would you use 2 separate methods or can the above function be made to work?
For completness here is my Controller call
minorResource.query({id: vm.seachCriteria}, function (data) {
//console.log(data);
vm.minorWork = data;
});
Note that query is used to retrieve an array of objects and get is used to retrieve a single object. That means that with a get you usually sent the id of the object to the API.
So in your case:
var minorWorksResource = $resource(appSettings.serverPath + "/api/minorworks/:id");
// Note that query returns an array.
var works = minorWorksResource.query(function() {
var firstWork = works[0];
});
// Note that we pass an ID that will be fetched in the query string.
var singleWork = minorWorksResource.get({id: 123}, function() {
});
And the WebAPI part:
[RoutePrefix("api/minorworks")]
public class MinorWorksController : ApiController {
public IHttpActionResult Get(int id) {
var singleWork = null;
// Retrieve a single item;
return Ok(singleWork);
}
public IHttpActionResult Get() {
var workList = null;
// Retrieve the whole list.
return Ok(workList );
}
}

Angular controller doesn't pass value to web api method with $http

This is my angularjs code:
var uname = resetPasswordRequestData.email
var request = $http({
method: "post",
url: workModule.config.Config.CommonUrl + "api/ResetPasswordRequest",
data: uname
});
web api code:
public class PerformPasswordResetController : ApiController
{
public int PerformResetPassword([FromBody]string uname)
{
CrmUser contact = null;
if (ModelState.IsValid)
{
try
{
contact = new PasswordResetProvider().GetUserByName(uname);
}
catch (Exception ex)
{
return 1;
}
}
}
My problem is when I make the call from Fiddler it works, but when I run the code it nicely rout to the web api method but in web api controller "uname" argument is null. when I pass some data from fiddler it pass that data to "uname" (in web api controller uname is not null)
can anyone help me?
I strongly suggest you use a Model class to receive the data on your server.
Something like this:
public class UserModel {
public string UserName { get; set; }
}
public class PerformPasswordResetController : ApiController
{
public int PerformResetPassword([FromBody]UserModel user)
{
...Do your stuff
}
}
And on your angular code:
var model = {
userName: resetPasswordRequestData.email
};
var request = $http({
method: "post",
url: workModule.config.Config.CommonUrl + "api/ResetPasswordRequest",
data: model
});
Also, if you don´t want (or can´t) change your server code, try this please:
var uname = resetPasswordRequestData.email
var request = $http({
method: "post",
url: workModule.config.Config.CommonUrl + "api/ResetPasswordRequest",
data: {
uname: uname
}
});

actions in $resource in angularjs

I have a webapi back end with the following method in the ProductController :
[HttpGet]
[Route("api/product/FindName")]
public Product FindName(string name){
return name & "Hello "
}
I am trying to make use of $resource in the frontend.
var resource = $resource('api/product/:id', {});
resource.query() will return all items which are exposed in the server side using the GetALL() method. This works fine .
What exactly is the {action} in the $resource does ? I have seen examples for the POST, but what if is set
var resource = $resource('api/product/:id', {}, { FindName: { method: 'GET', params: { name: 'phone' } } });
will this call the method FindName in the backend ? or what exactly it does, I mean the parameter if I set the 'GET' in method.
I am calling as
resource.FindName({ name: 'phone' }, function () {
});
But the backend is not getting fired . i see the call that is being requested to the server from fiddler is
Demo/api/product?name=phone
The resource declaration is incorrect. It should be
var resource = $resource('api/product/:id', {}, { FindName: { method: 'GET', params: { id: 'phone' } } });
This defaults the id placeholder to value phone.
For invocation now you can do
resource.FindName({}, function () { //gets api/product/phone
});
or override id part
resource.FindName({id:'tablet'}, function () { //gets api/product/tablet
});
Resource has a built in GET function that should be able to be used without the need to define the extra FindName action that has been added to $resource.
If you changed the route on your webapi to be
[HttpGet]
[Route("api/product/{name}")]
public Product FindName(string name){
return name & "Hello "
}
Then you could use resource like this to get data back from this route.
var resource = $resource('api/product/:id', {}, {});
resource.get({ id: 'phone' }, function () {
});
If you wanted the name params to match on both you could change :id to :name and in the resource.get change id to name also.
I hope this helps.

400 Bad Request when accessing a Sprint Rest method with AngularJs

I am trying to access an update rest method with AngularJs, but it is giving me 400 bad request error.
Here is my code.
#RestController
#RequestMapping("/api/loggedInUser")
public class UserController {
#RequestMapping(value = "/{id}",method = RequestMethod.PUT)
public AppUser updateLoggedInUser(#RequestBody AppUser user){
return userService.updateAppUser(user);
}
}
Here is the code for accessing the service from AngularJs:
App.factory('LoggedInUserService', ['$resource', function($resource) {
console.log('service injected');
return {
getLoggedInUser: $resource('api/loggedInUser', {}, {
query: {method: 'GET'}
}),
updateLoggedInUser: $resource('api/loggedInUser/:id', {}, {
update: {method: 'PUT', params: {id: '#id'}}
})
};
}]);
Here is the code for accessing the service in my app.js file.
.run(function($location, $rootScope, LoggedInUserService) {
LoggedInUserService.getLoggedInUser.query(function(loggedInUser) {
$rootScope.loggedInUser = loggedInUser;
console.log($rootScope.loggedInUser.username);
if (loggedInUser.role[0].authority === 'ADMIN_ROLE' && loggedInUser.pristineAccess) {
$rootScope.loggedInUser.isAdmin = true;
$rootScope.pristineAccess = false;
LoggedInUserService.updateLoggedInUser.update($rootScope.loggedInUser);
$location.path('/admin');
} else {
$rootScope.loggedInUser.isAdmin = false;
$location.path('/dashboard');
}
});
});
When I remove the #RequestBody annotation I don't get a 400 error but the parameter doesn't get populated.
What am I doing wrong here? I used the same kind of code in another place in the same application and it worked fine. The only difference here is that the rest method argument parameter is an entity object and not a pojo.
add consumes = MediaType.APPLICATION_JSON_VALUE to your controller method and check your POST content with web developers tool or firebug or simmilar tool
#RequestMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.PUT)
public AppUser updateLoggedInUser(#RequestBody AppUser user){
return userService.updateAppUser(user);
}

Resources