WebAPI: A callback parameter was not provided in the request URI - json

I am executing a post method in my API using fiddler I get error "A callback parameter was not provided in the request URI.". However, this works for get method.
I have seen several answers to this question, and as per the error I need to specify a callback parameter. However, I'm not sure how to do this using fiddler.
In response to one of those answers from Can I make a jQuery JSONP request without adding the '?callback=' parameter in URL? . I've tried the following in fiddler and I get the same error..
url: http://velopoint-api.localhost.dev/api/v1/tasks?callback=foo
header:
User-Agent: Fiddler
Host: velopoint-api.localhost.dev
ContentType: application/json; charset=utf-8
Authorization: basic "UNQUOTED"
Content-Length: 47
jsonp: true
jsonpCallback: jsonCallback
dataType: jsonp
request body
{ "Title":"New Task", "DueDate":"20-jul-2014" }
Startup
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
// Change Formater to use CamelCasePropertyNamesContractResolver
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
/* Support JsonP */
//register JSONP media type formatter
config.Formatters.Insert(0, new JsonpMediaTypeFormatter(jsonFormatter));
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
...
}

After playing around a little, I've finally figured it wasn't actually routing to the post method.
My header is now
User-Agent: Fiddler
Host: velopoint-api.localhost.dev
Authorization: basic UNQUOTED
Content-Length: 224
Content-Type: application/json
I fixed the problem by specifying Route attribute to my Post method and passing an empty string to the pattern parameter, both on the Get and the Post (as I already have the RoutePrefix attribute specified on the class.
[RoutePrefix("api/v1/tasks")]
[VeloPointAuthorise(perUser: true)]
public class TaskController : BaseApiController
{
[HttpGet]
[Route(template:"", Name = "TaskRoute")]
public HttpResponseMessage Get(int page = 0)
{
....
}
[HttpPost]
[Route(template:"")]
public HttpResponseMessage Post([FromBody] OrganiserTaskModel model)
{
....
}

Related

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..

AJAX works when extension is .json but not when it is .html

So I have an ajax request. When I use .html as below. I receive:
Failed to load resource: the server responded with a status of 406 (Not Acceptable)
When i use .json I receive the correct output. Why does it not work with .html
$("input[value = 'Add Type Targets']")
.click(
function() {
var promise = $
.ajax({
url : '/MyRoot/budget/myUrl.html',
type : 'GET',
beforeSend : function(
xhr) {
xhr
.setRequestHeader(
"Accept",
"application/json");
xhr
.setRequestHeader(
"Content-Type",
"application/json");
}
});
promise
.done(function(data) {
someCode
}
});
});
On the method I have
#RequestMapping(value = "/myUrl", method = RequestMethod.GET, produces = "application/json")
public #ResponseBody List<String> getData() {
return staticDataService.getData();
}
I have the jackson-mapper-asl-1.9.10.jar and jackson-core-asl-1.9.10.jar added.
Is it that because of the .html extension my response header is getting altered. Actually it is not even hitting my method when i use .html.
The HTTP error code 406 (Not Acceptable) means your HTTP request specified that the result must be of a certain type.
In your code, you explicitly mention that you only accept JSON results.
$.ajax({
url : '/MyRoot/budget/myUrl.html',
type : 'GET',
beforeSend : function(xhr) {
xhr.setRequestHeader( "Accept", "application/json");
...
When the server sees a file with a .json extension, it will automatically give it an application/json content-type, while a .html file, with be text/html content-type.
Since these are very different, you see the 406 error.
Since you are actually returning JSON, I would suggest you also use that for the extension. Not only will this help prevent confusion for other developers, it will also prevent you from having to 'fight the system'.
If you for some reason do want the HTML extension, you could try forcing the response content-type to be application/json. Since this extension based content-type is typically added by the server (IIS, Apache, etc.), it depends on your development stack if you can override this.
In ASP.NET you would use the following to explicitly set a header, but I can't say for sure if this will override the settings in IIS.
Response.ContentType = "application/json"
Should this not work, you can also change your AJAX call to be more permissive with it's response accepting.
xhr.setRequestHeader( "Accept", "*/*");

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

Pass additional parameters through a httpservlet request

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.

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
});