Pass additional parameters through a httpservlet request - json

The function deleteGroup() deletes a group and one of the parameters for this method is groupDN. In the front end I use jquery to specify a HTTP delete request. I was previously sending the groupDN by appending it with the URL. I now want to try sending this parameter embedded with the HttpServletRequest. The code for both the front and back end is below. Could someone guide me to the proper way of sending/receiving additional parameters within a request?
Front end
function removeGroup(groupDN) {
var deleteGroupDetails=new Object();
deleteGroupDetails.groupDN=groupDN;
jQuery.ajax({
type : 'DELETE',
url : 'api/groupService/deleteGroup,
dataType : 'json',
data : JSON.stringify(deleteGroupDetails),
contentType : 'application/json',
async: false,
success : function(response) {
utilDisplayMessage(response,"SUCCESS");
window.location.reload();
},
error : function(obj, error, errormsg) {
utilDisplayMessage(obj.responseText,"ERROR");
}
});
}
deleteGroupDetails contains the groupDN parameter which I think I could pass along with the request.
The back end in Java
#DELETE
#Path("deleteGroup")
#Produces({MediaType.APPLICATION_JSON})
public String deleteGroup(#Context HttpServletRequest request) throws Exception {
String groupDN = request.getParameter("groupDN");
}

Don't use a request body with a HTTP DELETE request. What you try to do is not REST but RPC (Remote Procedure Call) over HTTP. Don't do this.
The HTTP DELETE verbs tells the server to delete the resource identified by the URI. So if you do
DELETE /path/to/resources/123
the resource identified by this URI shall be deleted.
If you want to delete more than one entity on the server with one DELETE request, craft your resource URI to mean a collection of entities. For example:
DELETE /path/to/resources/?groupDN=foo
could mean: Delete all entities that somehow match the filter groupDN=foo.

Related

How to: (a) send JSON data from the browser to the controller; and (b) send the transformed data to SQL Server within ASP.NET MVC?

I have a form which includes a variety of <input> elements and makes use of 1-to-n tabulator tables for data input. I have managed to successfully assemble data from these elements into a JSON string. I am now attempting to complete the following two steps:
Using Ajax, post the JSON object to my web server; and
In the ASP.NET MVC controller, upload the deserialized JSON data into a SQL Server 2016 table.
My client-side script to POST the JSON object is as follows:
var myJson = "the data from the form elements is programmatically inserted into the JSON string";
// use parseJSON() to test the syntax
try {
var obj = jQuery.parseJSON(myJson);
}
catch(error) {
console.log(error);
}
$.ajax({
type: "POST",
url: "/Dailies/UploadJson/",
dataType: 'json',
data: JSON.stringify(myJson),
contentType: 'application/json',
crossDomain: true,
cache: false,
success: function(data) { console.log(data); }
});
The method called within my ASP.NET MVC controller appears as follows:
[HttpPost]
public IActionResult UploadJson(Object jsonFile)
{
// insert data into SQL Server table
}
Note: I have already created the appropriate domain model within my ASP.NET MVC app and have also added a DbSet reference to the DbContext model. I have verified my ability to insert rows into the SQL Server table using mock data.
When I place a breakpoint inside the UploadJson() method, I find that the jsonFile object is null.
My quandry at this point is two-fold:
I can't seem to get JSON data from the client to the web server; and
I need to better understand how to transform the JSON data (once received) for upload into my database.
Any assistance is greatly appreciated.
Although there are plenty of questions related to this, the answers to those typically refer to binding to a model instead of just the json string. But those will also help you.
It looks like there are two things:
I would change the controller to receive a string instead of an object.
You'll need to update the json data you're passing to the controller to match the parameter name of the controller. So in this case, the controller would receive a parameter named jsonFile. So in the $.ajax method you'll want update the data to something like:
data: { jsonFile: JSON.stringify(myJson) }
UPDATE:
remove the Content-Type of application/json

REST not working on bluemix due to CORS

I am new to bluemix, I have simple Rest service with few functions and called from angular js.
Here is below in Rest service class:
#POST
#Path("getTest")
#Produces("application/json")
public Response getTest(#QueryParam("accountId") String accountId) throws Exception, IOException {
System.out.println("HelloResource.getTest() "+accountId);
...
...
return Response.ok(dbData).header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods","POST, HEAD, GET, DELETE, PUT, OPTIONS")
.build();
}
Further, in client angular js is invoking this rest service in
$scope.searchcall = function(acctid)
{
$http({
method: 'POST',
url: 'http://javarestapi61.mybluemix.net/api/hello/getTest',
headers: {'Content-Type': 'application/json','Access-Control-Allow-Origin': '*'},
data: {"accountId": $scope.accountId}
}).success(function (data)
{
//never been successful onblue mix
}).error(function(data) {
alert("failure1"); //always landing here..
});
};
Looks like this is best solution which i tried. I am not sure, what i can try further to allow explicit permission on bluemix Rest application. BTW above app when deployed on local liberty, it works well.
Also i can access the same Rest service on bluemix, if i change return type as String and access via browser..(without even any additional permission)
Further, I saw that Chrome network details shows that, Preflight request go and returns with 200 (OPTIONS) then second request is actual POST which never succeeds.
What you can do is modify the method to :
public Response getTest(#QueryParam("accountId") String accountId, HttpServletRequest req) throws Exception, IOException{
//then your code
}
Now after that add the following:
since the browser looks for http://127.0.0.1:8080 in the Allow Origin Header, you need to make sure this is getting added in the following line:
response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8080");
To get the http://127.0.0.1:8080 you can use :
request.getRemoteAddr() + ":" + request.getRemotePort();
But if the browser looks for localhost then go for the :
request.getRemoteHost().
Avoid adding * because some browsers will not still allow that.
Hope that solves your problem.
And of course add this to the header:
response.setHeader("Access-Control-Allow-Methods","POST, HEAD, GET, DELETE, PUT, OPTIONS")
Finally when everything else that i tried did not work, below solution worked for me..
I have just added another separate url in my rest service class..
#Path("/getTest")
#OPTIONS
public Response getOptions() {
return Response.ok().header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, OPTIONS").header("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With").build();
}
Basically response of options have the "allowed" methods given by service..

How can i pass an object and a string to webservice using post request using angularjs

Am very new to angularjs and i need to post data to a web service, the service accepts two parameters, one is List of object and the other is securityToken,
Here is my code,
$scope.saveCompany=function(){
// alert("Save Company!!!");
var Companies={
Code: 'testMartin',
Name: 'company1',
CompanyType : 'Tenant',
email : 'test#yaoo.com',
Fax : 4235353,
ParentID : 1
};
$http({
url:'http://localhost/masters/smstools.svc/json/SaveComapnies',
dataType: 'json',
method: 'POST',
data: $.param(Companies),
headers: {
"Content-Type": "text/json",
}
}).success(function(response){
alert ("Success");
}).error(function(error){
alert ("Save company!");
});
how can i pass the security token with the companies object as a separate paramenter. my service accepts the parameters like this,
public List<CompanyProfile> Save(List<CompanyProfile> CompanyList,string securityToken)
Since this is a rest call you only have 3 places were you can pass parameters data:
With Post and it will be part of the body, it seems this is what is your first parameter is occupying now.
With Get and you add the parameter to the URL /json/SaveComapnies/mySecParam or by queryString like /json/SaveComapnies?sec=mySecParam but this is not secure nor recommended for security settings.
With header from angular Post:
**headers: {
"Content-Type": "text/json",
"mySecVar": "mySecParamValue"
}**
Server side version:
public List<CompanyProfile> Save(List<CompanyProfile> CompanyList){
WebOperationContext current = WebOperationContext.Current;
WebHeaderCollection headers = current.IncomingRequest.Headers;
if (headers["mySecVar"] != null){
// do something
}
}
You can read more about it here:
How to read HTTP request headers in a WCF web service?
Can you share more information in your Backend?
If it is actually a REST Backend I would rather use an angular $resource
https://docs.angularjs.org/api/ngResource
If you want to pass json object and string as post Parameter you should stick to the $http docs
https://docs.angularjs.org/api/ng/service/$http
In the post example you can pass both params in:
$http.post('/yourEndpoint', {jsonObj:yourCompaniesObj, secKey:yourSecretToken})....(sucess etc)
Typing from my cell - if you need more code examples just tell

Returning JSON with web api controller MVC

I am trying to convert a regular old controller I was using to an API controller and am having a little bit of difficulty. What these series of functions do is, in the jQuery, it iterates over a file containing all the usernames of employees and for each username it makes a call to the PopulateEmployee method in my webapi controller which should return JSON and then populate a results div.
When manually navigating to
..domain../staffinformation/populateemployee/employeeusername
I get the error
This XML file does not appear to have any style information associated with it. The
document tree is shown below.
<Error>
<Message>
The requested resource does not support http method 'GET'.
</Message>
</Error>
Please note that the div it will be populating is a partial view in an Umbraco CMS page and I don't think that is the problem but if you guys think differently please tell me.
There has to be something I am missing either with webAPI routing or something else.
Thanks for your help.
Here's the codez.
Please notice that this method has the HttpPost tag
public class StaffInformationController : ApiController
{
[System.Web.Http.ActionName("PopulateEmployee")]
[System.Web.Http.HttpPost]
public StaffListing PopulateEmployee(string id)
{
//do error checking on input
StaffListing staffListing = new StaffListing(id);
//populate other fields
return staffListing;
}
}
The routing set up for the api controller
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
The jQuery call specifying use of 'POST', please forgive the trickiness of the recursive call in this function.
function getEmployeeObjectByIndex() {
$.ajax({
url: $('#root').val() + '/api/StaffInformation/PopulateEmployee',
type: 'POST',
async: true,
contentType: 'application/json, charset=utf-8',
data: JSON.stringify({ 'username': lines[i] }),
success: function (staffObject) {
if (!(staffObject.Name == undefined)) {
buildHtmlStrings(staffObject);
}
i++;
getEmployeeObjectByIndex(); //recursive call
}
});
}
manually navigating to that address throws the error because, when manually navigating you are doing a GET (and your method only allows POSTs).
You should fire up Fiddler and watch the ajax POST request and response to see how the server is responding / your request is being made
Jquery ------> web api
Web API has one property i.e. CONTENT NEGOTIATION means you send any data and accept any data as you want.
$.ajax({
contentType: 'application/json, charset=utf-8',
// this is sending your data of datatype json to server, here you send any type of data
accept: 'application/json',
//this is receiving/getting data form server to client...
// SO HERE YOU GET JSON DATA AS YOU WANT only mention which data of datatype u want...
//if you sending xml and you want json so only write accept as json it get automatically converted into your required datatype..by MediaTypeFormatter
});

Chrome API responseHeaders

Based on this documentation: https://developer.chrome.com/extensions/webRequest.html#event-onHeadersReceived
I tried to display the response via the console like:
console.log(info.responseHeaders);
But its returning undefined.
But this works though:
console.log("Type: " + info.type);
Please help, I really need to get the responseHeaders data.
You have to request the response headers like this:
chrome.webRequest.onHeadersReceived.addListener(function(details){
console.log(details.responseHeaders);
},
{urls: ["http://*/*"]},["responseHeaders"]);
An example of use. This is one instance of how I use the webRequest api in my extension. (Only showing partial incomplete code)
I need to indirectly access some server data and I do that by making use of a 302 redirect page. I send a Head request to the desired url like this:
$.ajax({
url: url,
type: "HEAD"
success: function(data,status,jqXHR){
//If this was not a HEAD request, `data` would contain the response
//But in my case all I need are the headers so `data` is empty
comparePosts(jqXHR.getResponseHeader('redirUrl')); //where I handle the data
}
});
And then I silently kill the redirect while scraping the location header for my own uses using the webRequest api:
chrome.webRequest.onHeadersReceived.addListener(function(details){
if(details.method == "HEAD"){
var redirUrl;
details.responseHeaders.forEach(function(v,i,a){
if(v.name == "Location"){
redirUrl = v.value;
details.responseHeaders.splice(i,1);
}
});
details.responseHeaders.push({name:"redirUrl",value:redirUrl});
return {responseHeaders:details.responseHeaders}; //I kill the redirect
}
},
{urls: ["http://*/*"]},["responseHeaders","blocking"]);
I actually handle the data inside the onHeadersReceived listener, but this way shows where the response data would be.