Android Volley POST string in body
Asked Answered
P

3

14

I'm trying to use Volley library to communicate with my RESTful API.

I have to POST string in the body, when I'm asking for the bearer Token. String should look like this: grant_type=password&username=Alice&password=password123 And header: Content-Type: application/x-www-form-urlencoded

More info about WebApi Individual Accounts: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

Unfortunately I can't figure out how can I solve it..

I'm trying something like this:

StringRequest req = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        VolleyLog.v("Response:%n %s", response);
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.e("Error: ", error.getMessage());
                    }
                }){
                    @Override
                    protected Map<String, String> getParams() throws AuthFailureError {
                        Map<String, String> params = new HashMap<String, String>();
                        params.put("grant_type", "password");
                        params.put("username", "User0");
                        params.put("password", "Password0");
                        return params;
                    }

                    @Override
                    public Map<String, String> getHeaders() throws AuthFailureError {
                        Map<String, String> headers = new HashMap<String, String>();
                        headers.put("Content-Type", "application/x-www-form-urlencoded");
                        return headers;
                    }
                };

I'm getting 400 Bad Request all the time. I think that I'm actually sending request like this:

grant_type:password, username:User0, password:Password0

instead of:

grant_type=password&username=Alice&password=password123

I would be very grateful if anyone has any ideas or an advice..

Proviso answered 27/2, 2014 at 1:10 Comment(1)
maybe this link help #31623946Quean
R
8

First thing, I advise you to see exactly what you're sending by either printing to the log or using a network sniffer like wireshark or fiddler.

How about trying to put the params in the body? If you still want a StringRequest you'll need to extend it and override the getBody() method (similarly to JsonObjectRequest)

Rattlehead answered 27/2, 2014 at 10:27 Comment(2)
I just googled it few minutes ago! It works!! Thank you :-) For others interested in.. You can use JsonObjectRequest with null JSON and Override getBody() OR use StringRequest and than you have to extend it as wrote above.. One more question about using a network sniffer. I'm using Fiddler and the only way how I can log my requests is using Emulator and set proxy to the Fifdler. Is there another option how to log requests from a real device?Proviso
You can use fiddler with a device by connecting via WiFi to the same network your computer is connected to, setting a proxy on your device on that network using the IP of your PC as the hostname and 8888 as the port. Fiddler should pick up on your request now.Rattlehead
R
32

To send a normal POST request (no JSON) with parameters like username and password, you'd usually override getParams() and pass a Map of parameters:

public void HttpPOSTRequestWithParameters() {
    RequestQueue queue = Volley.newRequestQueue(this);
    String url = "http://www.somewebsite.com/login.asp";
    StringRequest postRequest = new StringRequest(Request.Method.POST, url, 
        new Response.Listener<String>() 
        {
            @Override
            public void onResponse(String response) {
                Log.d("Response", response);
            }
        }, 
        new Response.ErrorListener() 
        {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d("ERROR","error => "+error.toString());
            }
        }
            ) {     
        // this is the relevant method
        @Override
        protected Map<String, String> getParams() 
        {  
            Map<String, String>  params = new HashMap<String, String>();
            params.put("grant_type", "password"); 
            // volley will escape this for you 
            params.put("randomFieldFilledWithAwkwardCharacters", "{{%stuffToBe Escaped/");
            params.put("username", "Alice");  
            params.put("password", "password123");

            return params;
        }
    };
    queue.add(postRequest);
}

And to send an arbitary string as POST body data in a Volley StringRequest, you override getBody()

public void HttpPOSTRequestWithArbitaryStringBody() {
    RequestQueue queue = Volley.newRequestQueue(this);
    String url = "http://www.somewebsite.com/login.asp";
    StringRequest postRequest = new StringRequest(Request.Method.POST, url, 
        new Response.Listener<String>() 
        {
            @Override
            public void onResponse(String response) {
                Log.d("Response", response);
            }
        }, 
        new Response.ErrorListener() 
        {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d("ERROR","error => "+error.toString());
            }
        }
            ) {  
         // this is the relevant method   
        @Override
        public byte[] getBody() throws AuthFailureError {
            String httpPostBody="grant_type=password&username=Alice&password=password123";
            // usually you'd have a field with some values you'd want to escape, you need to do it yourself if overriding getBody. here's how you do it 
            try {
                httpPostBody=httpPostBody+"&randomFieldFilledWithAwkwardCharacters="+URLEncoder.encode("{{%stuffToBe Escaped/","UTF-8");
            } catch (UnsupportedEncodingException exception) {
                Log.e("ERROR", "exception", exception);
                // return null and don't pass any POST string if you encounter encoding error
                return null;
            }
            return httpPostBody.getBytes();
        }
    };
    queue.add(postRequest);
}

As an aside, Volley documentation is non-existent and quality of StackOverflow answers is pretty bad. Can't believe an answer with an example like this wasn't here already.

Roof answered 9/10, 2014 at 4:9 Comment(1)
You're right, Volley documentation didn't help at all!Beckybecloud
R
8

First thing, I advise you to see exactly what you're sending by either printing to the log or using a network sniffer like wireshark or fiddler.

How about trying to put the params in the body? If you still want a StringRequest you'll need to extend it and override the getBody() method (similarly to JsonObjectRequest)

Rattlehead answered 27/2, 2014 at 10:27 Comment(2)
I just googled it few minutes ago! It works!! Thank you :-) For others interested in.. You can use JsonObjectRequest with null JSON and Override getBody() OR use StringRequest and than you have to extend it as wrote above.. One more question about using a network sniffer. I'm using Fiddler and the only way how I can log my requests is using Emulator and set proxy to the Fifdler. Is there another option how to log requests from a real device?Proviso
You can use fiddler with a device by connecting via WiFi to the same network your computer is connected to, setting a proxy on your device on that network using the IP of your PC as the hostname and 8888 as the port. Fiddler should pick up on your request now.Rattlehead
P
3

I know this is old, but I ran into this same problem and there is a much cleaner solution imo found here: How to send a POST request using volley with string body?

Profusion answered 11/10, 2016 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.