Pass Parameter with Volley POST
android, android-volley, azure-functions
Solution
The server code is expecting a JSON object is returning string or rather Json string.
JsonObjectRequest
JSONRequest sends a JSON object in the request body and expects a JSON object in the response. Since the server returns a string it ends up throwing ParseError
StringRequest
StringRequest sends a request with body type `x-www-form-urlencoded` but since the server is expecting a JSON object. You end up getting 400 Bad Request
The Solution
The Solution is to change the content-type in the string request to JSON and also pass a JSON object in the body. Since it already expects a string you response you are good there. Code for that should be as follows.
StringRequest sr = new StringRequest(Request.Method.POST, Constants.CLOUD_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
mView.showMessage(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mView.showMessage(error.getMessage());
}
}) {
@Override
public byte[] getBody() throws AuthFailureError {
HashMap<String, String> params2 = new HashMap<String, String>();
params2.put("name", "Val");
params2.put("subject", "Test Subject");
return new JSONObject(params2).toString().getBytes();
}
@Override
public String getBodyContentType() {
return "application/json";
}
};
Also there is a bug here in the server code
var responseMessage = $"Hello {personToGreet}!";
Should be
var responseMessage = $"Hello {name}!";
Problem
I was able to call an HTTP endpoint using Postman and these parameters: ``` { "name":"Val", "subject":"Test" } ``` However I am unable to do the same with Volley through Android: Here is trying to use JSONRequest: ``` HashMap<String, String> params2 = new HashMap<String, String>(); params.put("name", "Val"); params.put("subject", "Test Subject"); JsonObjectRequest jsObjRequest = new JsonObjectRequest (Request.Method.POST, Constants.CLOUD_URL, new JSONObject(params2), new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { mView.showMessage("Response: " + response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub mView.showMessage(error.getMessage()); } }); // Access the RequestQueue through your singleton class. VolleySingleton.getInstance(mContext).addToRequestQueue(jsObjRequest); ``` And here is trying StringRequest ``` private void postMessage(Context context, final String name, final String subject ){ RequestQueue queue = Volley.newRequestQueue(context); StringRequest sr = new StringRequest(Request.Method.POST, Constants.CLOUD_URL, new Response.Listener<String>() { @Override public void onResponse(String response) { mView.showMessage(response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }){ @Override protected Map<String,String> getParams(){ Map<String,String> params = new HashMap<String, String>(); params.put("name", name); params.put("subject", subject); return params; } @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String,String> params = new HashMap<String, String>(); params.put("Content-Type","application/x-www-form-urlencoded"); return params; } }; queue.add(sr); } ``` When I use JSONRequest, the call POSTs but no parameter is passed and when I use StringRequest I get the error below? How can I pass JSON data to Volley call? ``` E/Volley: [13053] BasicNetwork.performRequest: Unexpected response code 400 for ``` Here is the server code that handles the request ``` public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { var helloRequest = await req.Content.ReadAsAsync<HelloRequest>(); var name = helloRequest?.Name ?? "world"; var responseMessage = $"Hello {personToGreet}!"; log.Info($"Message: {responseMessage}"); return req.CreateResponse(HttpStatusCode.OK, $"All went well."); } public class HelloRequest { public string Name { get; set; } public string Subject { get; set; } } ```