Problem Specification:
Resource URI : address/index.php?r=api/employee
Request Header : Content- Type: application/json
HTTP Method: POST
Request Body: { "employeeName" : "ABC","age":"20","ContactNumber": "12341234"}
The above parameters should be passed to the system as a row HTTP POST in a JSON string.
I am trying to solve this problem using RESTSharp. But I am having some problem Like after executing the request my code return a Null response and I am not sure my JSON string is passing properly or not.
Here is my Code:
public ActionResult EmployeeInfo(Employee employee)
{
//string empName = unSubscription.employeeName.ToString();
var client = new RestClient("http://localhost:21779/");
var request = new RestRequest("api/employee ", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddBody(new Employee
{
employeeName = "ABC",
age = "20",
ContactNumber = "12341234"
});
request.AddHeader("Content-Type", #"application/json");
// execute the request
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
return View();
}
Is there anything wrong with my code??
And I am little bit confused about
request.AddUrlSegment("username", "Admin") and request.AddParameter("name", "value").
Basically I want to know how to utilize AdduUrlSegment() and AddParameter().
Thanks in advance.
For using request.AddUrlSegment("username", "Admin") you should define your url template properly: var request = new RestRequest("api/employee/{username} ", Method.POST);
Also you should set Content-Type
request.AddHeader("Content-Type", #"application/json");
befor adding a Body
Related
I have created a simple webapi controller.
// POST request api to get a string base64 image, store it and returns its name.
public string Post([FromBody]string image)
{
if (image == null)
return "No image sent";
// Generating random file name using the current date and time and random text
string fileName = "image-" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + Path.ChangeExtension(
Path.GetRandomFileName(),
".jpg"
);
// If the directory does not exist create a new one
if (!Directory.Exists(#".\uploads\"))
{
DirectoryInfo DI = Directory.CreateDirectory(#".\uploads\");
}
File.WriteAllBytes(#".\uploads\" + fileName, Convert.FromBase64String(image));
return "Submitted as File: " + fileName;
}
When I send a post request through postman, it works as fine and returns the string "Submitted as File ..."
But when I try it in Angular I get the following error.
OPTIONS http://example.com/Api/Image/Index 405 (Method Not Allowed)
My angular service:
getResult(base64image) {
//Where base64image is a string.
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post('http://example.com/Api/Image/Index', base64image, options)
.map(res => res);
}
I know that it has something to with cors. But it is just a simple api.
I'm trying to use the Google Machine Learning API and I'm facing two problems.
In the API explorer I put the correct information and I get a response error:
Code 200
"error": "Missing \"instances\" field in request body: {\n \"httpBody\": \n
{\n \"data\": \"\\"instances\\" : \\"teste\\"\",\n
\"contentType\": \"application/json\"\n }\n}"
The request find my model (if I change the value in field name I get another error) but don't understand my json. That's the json:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
When I do the predict on the command line using gcloud, I get no errors and everything seems ok. The Json that I was create for gcloud is a little bit different:
{"key":"0", "image_bytes": {"b64": "mybase64"} }
I already tryied that one in the API explorer and no success.
So, I decided to use the .Net Api to try the predict and I get other situation: The Response is Empty (???).
Here is my code:
'get the service credential that I created
Dim credential = Await GetCredential()
Dim myService As New CloudMachineLearningEngineService(New BaseClientService.Initializer() With {
.ApplicationName = "my Project Name (Is That It???)",
.ApiKey = "my API Key",
.HttpClientInitializer = credential
})
Dim myBase64 As String = GetBase64("my image path to convert into a base64 String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
'If I change the model name I get error
Dim myPredictRequest = myService.Projects.Predict(myRequest, "projects/myProject/models/myModel/versions/v1")
myPredictRequest.AccessToken = credential.Token.AccessToken
myPredictRequest.OauthToken = credential.Token.AccessToken
myPredictRequest.Key = "my API Key
'Execute the request
Dim myResponse = myPredictRequest.Execute()
'at this point, myResponse is Empty (myResponse.ContentType Is Nothing, myResponse.Data Is Nothing And myResponse.ETag Is Nothing)
If I change the model name I get a error informing that my model was not found, so my credentials are right.
I don't know what I'm doing wrong. Someboby can help with any of this issues?
Thanks!
UPDATE: --------------------------
I changed this Execute Command:
Dim myResponse = myPredictRequest.Execute()
To This One:
Dim s = StreamToString(myPredictRequest.ExecuteAsStream())
and Now I can get the same error with .Net API and google developers interface (Missing instances field...).
So If someboby just Know what is wrong with my Json request, It will help a lot.
The JSON you put in the API explorer is indeed correct (assuming, of course, your model has inputs key and image_bytes). This appears to be a bug with the explorer I will report.
The reason you are getting the error you are in the .NET code is because you are using an .HttpBody field. This code:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
Will produce a JSON request that looks like this:
{
"httpBody": {
"data": "{\"instances\" : [{\"key\":\"0\", \"image_bytes\": {\"b64\": \"mybase64\"} }]}",
"contentType": "application\/json"
}
}
When what you really need is:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
Hence the error message you see.
I don't know how to generate the correct response using the .NET library; based on the Python example in the docs, I would guess:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myPredictRequest = myService.Projects.Predict(myJsonRequest, "projects/myProject/models/myModel/versions/v1")
But I don't have a good way of testing that. For reference, the Python equivalent is:
response = service.projects().predict(
name=name,
body=myJsonRequest
).execute()
I solved the problem with .Net API.
I created two new classes Inherits the Google API's classes.
Something like that:
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleCloudMlV1PredictRequest
Inherits GoogleCloudMlV1PredictRequest
<JsonProperty("instances")>
Public Property MyHttpBody As List(Of myGoogleApiHttpBody)
End Class
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleApiHttpBody
Inherits GoogleApiHttpBody
<JsonProperty("image_bytes")>
Public Property MyData As image_byte
<JsonProperty("key")>
Public Property key As String
End Class
So, in my original code I change this part:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
For this one:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myRequest = New myGoogleCloudMlV1PredictRequest With {
.MyHttpBody = New List(Of myGoogleApiHttpBody)()
}
Dim item As myGoogleApiHttpBody = New myGoogleApiHttpBody With {
.key = "0",
.MyData = New image_byte With {
.b64 = myBase64
}
}
myRequest.MyHttpBody.Add(item)
And voilá, It's working!
Thanks for everyone!!
Github issue #1068 shows two work-arounds for this problem.
In summary, use service.ModifyRequest to insert the raw JSON content.
Or use service.HttpClient.PostAsync(...) directly.
HttpClient myClient = new HttpClient();
myClient.BaseAddress = new Uri(URL);
Base address already specified on client it's URL.
var encodedObject = JsonConvert.SerializeObject(Obj);
myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await myClient.PostAsync("test.php/yourAPI",new StringContent(encodedObject, System.Text.Encoding.UTF8, "application/json"));
if (response.IsSuccessStatusCode)
{
var responseContent = response.ToString();
var responsebody = response.Content.ToString();
Stream receiveStream = response.GetResponseStream();
string responseBodyAsText = response.Content.ReadAsStringAsync().Result;
}
Could be a content negotiation issue. Try clearing the Accept header before adding the json media type
myClient.DefaultRequestHeaders.Accept.Clear();
myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//...other code removed for brevity.
this code sets the Accept header to "application/json", which tells the server to send data in JSON format.
Reference source: Calling a Web API From a .NET Client in ASP.NET Web API 2
the Method PostAsync has as first argument the complete URI of The API. Therefore, it should be like follow :
HttpResponseMessage response = await myClient.PostAsync("http://bla-bla-bla/test.php/test",new StringContent(encodedObject, System.Text.Encoding.UTF8, "application/json"));
And there is no need to define the BaseAddress.
I am attempting to connect to the Twitter API with these instructions
https://dev.twitter.com/docs/auth/application-only-auth
Here is my code:
var baseUrl = "http://api.twitter.com/";
var client = new RestClient(baseUrl);
var request = new RestRequest("/oauth2/token", Method.POST);
var concat = ConfigurationManager.AppSettings["TwitterConsumerKey"] + ":" +
ConfigurationManager.AppSettings["TwitterConsumerSecret"];
string encodeTo64 = concat.EncodeTo64();
request.AddHeader("Authorization", "Basic " + encodeTo64);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
request.AddBody("grant_type=client_credentials");
IRestResponse restResponse = client.Execute(request);
EncodeTo64
static public string EncodeTo64(this string toEncode)
{
byte[] toEncodeAsBytes
= System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue
= System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
Response.Content is the following
"{\"errors\":[{\"code\":170,\"label\":\"forbidden_missing_parameter\",\"message\":\"Missing required parameter: grant_type\"}]}"
Is this part wrong?
request.AddBody("grant_type=client_credentials");
I have verified that my credentials are correct (I got that error before, but resolved it, so it should be OK).
The instructions on the Twitter page confused me. "The body of the request must be grant_type=client_credentials."
As for Restsharp, it's not AddBody, but AddParameter.
So:
request.AddParameter("grant_type", "client_credentials");
Can't get the POST working? What's wrong?
Note: This works for a GET with autocomplete
GET works without signing the url
I'm following the Web services steps to Sign the URL with my "API Key"
Docs say"client id" still?
http://code.google.com/apis/maps/documentation/webservices/
2.Try sending the POST data with the signed URL (tried the unsigned signature aswell)
def signedUrl = "https://maps.googleapis.com/maps/api/place/add/json?key=xxxxxkeyxxxxxx&sensor=false&signature=xxxxxxxxxxsignaturexxxxxx"
String postData = "{'location': { 'lat': '-33.8669710','lng': '151.1958750'},'accuracy': '50','name': 'Google Shoes!'}"
URL urlPost = new URL(signedUrl);
URLConnection connection = urlPost.openConnection();
connection.addRequestProperty("Referer", "http://www.mysite.com");
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("CONTENT-TYPE", "text/json");
connection.setRequestProperty("CONTENT-LENGTH", postData.length() + "");
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(postData);
out.close();
String line;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while((line = reader.readLine()) != null) {
builder.append(line);
}
JSONObject json = new JSONObject(builder.toString());
println json
Returns a 403
"java.io.IOException: Server returned HTTP response code: 403 for URL:"
Simular to the "Java Access"section under they give an example of a GET
http://code.google.com/apis/websearch/docs/#fonje
Ok solved.
No signing the URL required
postData string was wrong
should have been
String postData = "{\"location\": { \"lat\": -33.8669710,\"lng\": 151.1958750},\"accuracy\": 50,\"name\": \"Google Shoes!\", \"types\":[\"bar\"]}"