I have a requirement to send some values to a service via HTTP POST. One of the parameters that gets sent must contain blanks. It is the "Key" nvp. But the service always returs a unsuccessful message, as soon as I add a value it work.
Now here is the catch, when the request is done to the same service via iphone device it works just fine when they send BLANKS, am I missing something in my request to allow blank values to be sent via NameVauePair?
Here is my NaveValuePair's
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(5);
nameValuePairs.add(new BasicNameValuePair("id","1"));
nameValuePairs.add(new BasicNameValuePair("uId",android_id));
nameValuePairs.add(new BasicNameValuePair("Key", " ")); // This value must be BLANKS
nameValuePairs.add(new BasicNameValuePair("Rate","0"));
nameValuePairs.add(new BasicNameValuePair("Notes", notes));
Here is my POST request
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(context.getResources()
.getString(R.string.url_event_rating));
try {
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8"));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
String responseBody = EntityUtils.toString(response
.getEntity());
} catch (ClientProtocolException e) {
Log.d("ClientProtocolException", e.getMessage());
} catch (IOException e) {
Log.d("IOException", e.getMessage());
}
Try adding SP instead of a literal space character. This is the syntax given to you by BasicNameValuePair: http://developer.android.com/reference/org/apache/http/message/BasicNameValuePair.html (specifies a general overview of the class) and http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 (specifies the tokens accepted).
Essentially, you want to insert SP instead of " ", according to what I've read on the topic.
Edit: According to the second link above: SP = <US-ASCII SP, space (32)>. Essentially, either place a character whose value is 32 (decimal) or 0x20 (hex). Or, change your encoding in UrlEncodedFormEntity(nameValuePairs, "utf-8") to "US-ASCII".
While we send a POST request there are field in HTTP Headers to be set, like the Content-Type field with value "application/x-www-form-urlencoded", which is default type. We should whatsoever encode the value field of request body before sending it. URLEncoder.encode(String s, String charsetName) functions encode a string with given charsetName i.e, 'utf-8'. The encoding used by default is based on a very early version of the general URI percent encoding rules.
one encoding example: a string like My Name is "Marshal" will be encoded as:
My%20Name%20is%20%22Marshal%22.
So, the safest way is to set (name, value) pair after encoding with this function. That is:
value = URLEncoder.encode(value, "utf-8");
nameValuePairs.add(new BasicNameValuePair(key, value));
Ok, there might be other ways to get this to work but the following code is what worked for me.
I got it to work using the following approach.
String blanks = " ";
nameValuePairs.add(new BasicNameValuePair("Key", blanks.replaceAll(" ", "%20")));
Hope this helps someone who has encountered the same problem.
Related
I keep getting the error above (title) when I try to make a HTTP-request to a server with a special character (the character 'å'). I have tried to call:
_login = URLEncoder.encode(_login, "utf-8");
But I still get exception. If I try to change the URL it works fine. Seems that it happends for whatever URL I try if it has special characters. Like for example http://www.ål.no.
Anyone know about a work-around? One way could of course be to use the IP-address. But I would rather avoid that.
Thanks for any help!
Some of the source code:
private String _login = "http://www.ål.no";
HttpClient httpclient = new DefaultHttpClient();
try {
_login = URLEncoder.encode(_login, "utf-8");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
HttpPost httppost = new HttpPost(_login);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
//nameValuePairs.add(new BasicNameValuePair("Mail", this.Email));
//nameValuePairs.add(new BasicNameValuePair("Password", this.Password));
try
{
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
BasicHttpResponse response = null;
try
{
response = (BasicHttpResponse) httpclient.execute(httppost);
}
catch (ClientProtocolException e)
{
System.out.println("BasicHttpResponse");
e.printStackTrace();
}
}
EDIT: Found a work around. Used Firebug to dig a little deeper. According to Firebug the server has another name when communicating (as far as I can see). This name does not contain any special characters and I successfully managed to communicate with the server using my application. Thanks for all help! :)
I think I understand what you're asking for. Here is a link to a list of special characters that the URL will identify.
http://www.degraeve.com/reference/urlencoding.php
If thats not what you need let me know.
to save you time, the character you're searching for is %E5
I am posting a url with params containg an underscore (_).
sample: http://sdsdsds_asasasahjhd.com/dsdsdsd/login.json?
I am posting it like this:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://sdsdsds_asasasahjhd.com/dsdsdsd/login.json?");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("key1", "value1"));
nameValuePairs.add(new BasicNameValuePair("key2", "value2"));
nameValuePairs
.add(new BasicNameValuePair("key3", "value3"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (Exception e) {
e.printStackTrace();
}
When I am inspecting httpclient.execute(httppost) I am getting IllegalArgumentException and in catch in exception details it is telling Host name cannot be null.
Please specify any solution.
I have gone through some other questions here:
java.lang.IllegalStateException: Target host must not be null, or set in parameters
Host name may not be null in HttpResponse execute for android
but no use as I am not encoding the whole url.
I have an open-source library with network implementation mechanism. It has just receiver an workaround implementation. All you need it to set the host by reflection in case of troubles:
final URI uriObj = new URI("https", host, path, null, null);
if (uriObj.getHost() == null) {
final Field hostField = URI.class.getDeclaredField("host");
hostField.setAccessible(true);
hostField.set(uriObj, host);
}
return uriObj;
The commit is here.
well it clearly states that the host name can not be null.. your url doesn't specify one..
a url is expected to be in the format
http://hostName.com/example..../example.json
HttpPost httppost = new HttpPost(String);
This contructor will attempt to form a URL instance from the provided String. If this fails, you'll be dealing with a null value.
Please post the actual URL you're using and not a sample if you want us to be able to help you further.
See this link. Apache doesnt support underscore. You should change the url
https://issues.apache.org/jira/browse/HTTPCLIENT-911
I want to post to this url
http://abc.com/Registration.aspx?MailID=PickUp&UserName=as&PickUpTime=19191919&Notes=bla&DeviceId=0000
HttpPost httppost = new HttpPost("http://abc.com/Davis/Registration.aspx");
httppost.setHeader("MailID","MailID=PickUp");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
//nameValuePairs.add(new BasicNameValuePair("MailID","PickUp"));
nameValuePairs.add(new BasicNameValuePair("UserName","as"));
nameValuePairs.add(new BasicNameValuePair("PickUpTime",date));
nameValuePairs.add(new BasicNameValuePair("Notes",note));
nameValuePairs.add(new BasicNameValuePair("DeviceId",deviceID));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
Also how can I know what url I am passing . How can I log it ?
Are you sure MailID should be in the header? From the wording of the question, it looks as if all values are in the query string (in the URL past the ? mark). But then why would you need POST for that; a GET would be sufficient.
And passing data, like MailID, in headers is almost unheard of. Querystring and POST form, those are the most popular places.
So first figure out the interface of the server page. Does it expect GET or POST (or either)? Then place the fields into the right place - either into the URL (by string concatenation), or into the entity.
Oh, and the URL you're passing is http://abc.com/Davis/Registration.aspx. Neither setHeader() nor setEntity() modifies the URL per se.
import org.apache.http.message.BasicNameValuePair;
private String getServerData(String returnString) {
InputStream is = null;
String result = "";
//the year data to send
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("year","1970"));
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(KEY_121);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection "+e.toString());
}
}
My Questions...
What does BasicNameValuePair class does?
What does this piece of line do
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
What does is = entity.getContent(); do? and can i pass more than one value in BasicNameValuePair class. Can i entirely pass a VO instead of this.
Like the below ...
nameValuePairs.add(new BasicNameValuePair("year","1970","sas","saassa","sas","asas"));
BasicNameValuePair is an object, specifically a container to holds data and keys.
For example if you have this data:
Name: Bob
Family name: Smith
Date of birth: 10/03/1977
then you would store this data as:
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("name","bob"));
nameValuePairs.add(new BasicNameValuePair("family name","Smith"));
....
As you see you choose a key ("name") and data to be stored as linked to the key ("bob"). It's a type of data structure used to speed up and make easier to store this kind of informations.
On the other end you need a tool to use this data:
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
this code can be divided in 4 parts:
httppost.setEntity: Is a method that take an url as argument, and tries to retrieve data (HTML or what is stored on that page) from that url, using the HTTP Post method.
new UrlEncodedFormEntity: Is a method that trasform key-data value pair in something intelligible by an http server.
it use the convention: &key=input, which one of the most used, but remember that there more ways to do it.
nameValuePair: is the data you stored before. In this case it has key the possible input forms in the html, identified by the "input name=" tag. As data it has the value that you want to give to the forms.
is = entity.getContent();: HttpEntity is an abstraction to help you handle the possible result. If the web site is unreachable or the connection is down, HttpEntity will inform you. getContent() is the method you use the retrieve the body of the Http result, i.e.: the html that the webserver sent you back, as a inputstream. If the request wasn't succesfull it will give you a null value.
BasicNameValuePair accept only couplets, so you'll have to cast it multiple times and everytime add it to the arraylist.
You can't cast it to more than two values, as they would be meaningless for the (key, value) representation of data.
Hope it helped.
In the end you're doing a http POST request with the field "year" having the value "1970".
Just like a webform posting that year would.
A bit extra:
The BasicNameValuePair looks quite aptly named: Its a very simple (basic) group of two things (pair) that serve as a formfield (name) and its contents (value).
The httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); adds that combination of year and 1970 to the HttpPost object, but with encoding (so there are no 'illegal' things in there).
I'm exploring to scan ssid and rssi from android and I'm able to do it, but now i have want send the data to the server, so i explore i found below code
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://101.34.45.45/rawData");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
nameValuePairs.add(new BasicNameValuePair("userId", "00-22-68-E8-EC-F1"));
nameValuePairs.add(new BasicNameValuePair("timestamp", "2010-07-01 11:11:11"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
textView.setText(response.toString());
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
but now i'm having problem when add multi wifi data, the format should as below
http://101.34.45.45/rawData?data={"userId":"guest1","timestamp":"2010-07-01 08:58:23","wifi":[{"ssid":"guest","rssi":"40"},{"ssid":"guest1","rssi":"80"}]},
so how can done for the wifi parameter, can anyone help, I'm still trying for few varieties,
thanks
I would recommend you to switch to JSON for sending data to the server. Google gson is easiest to use to send and parse JSON.
{"userId":"guest1","timestamp":"2010-07-01 08:58:23","wifi":[{"ssid":"guest","rssi":"40"},{"ssid":"guest1","rssi":"80"}]}
You should use a JSON object having a JSON array as one of its items. The JSON array in turn contains another json object.
If you are using Google GSON, you should build a class hierarchy for the same. Heres how you should do the same.
Class data{
String userId;
String timestamp;
Wifi wifi;
}
Class Wifi{
String ssid;
int rssi;
}
You can check here for a sample code on a similar problem on parsing json in android.
This may be useful too.