I have a simple website I am playing around with, that takes in an email and password to log in. This all works fine on a PC browser, and on apple phones / tablets.
However, droid devices will not log in. I routed my test phone via my pc and used fiddler to look at the http traffic, and Android is encoding email addresses, so instead of foo#here.com I am seeing foo%40here.com, and so my server side validation is failing as this is not a valid email address.
The easy way to my mind of detecting this is to simply look at the email string before I validate it, and look for the %40 symbol. But if android is goign to urlencode everything by default, this could give me issues further on down the line, and having to examin strings, and guess whether a % is part of some url encoding, or a genuine percentage will become a problem.
So is there an attribute or filter I can apply to my method so that the framework will unencode it as required, or do I need to handle this on a case by case basis?
try by adding ("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); line in your request before sending request
like this request.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
se the example
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(Constants.mWebURL+Constants.mSendBloodReq);
request.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
// adding paramaters
List<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("user_id",params[0]));
postParameters.add(new BasicNameValuePair("password",params[1]));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters,"UTF-8");
request.setEntity(formEntity);
HttpResponse httpresponse = httpClient.execute(request);
//getting response
response = EntityUtils.toString(httpresponse.getEntity());
My Method on the controller wasn't decorated with a [HttpPost] attribute. That seems to have fixed it for me
Related
I received a Postman json collection from an API vendor that works perfectly, but has something mystifying to me: The request is in a GET format, yet there is an x-www-form-urlencoded body.
URL: https://login.microsoftonline.com/d1e<secret>9563/oauth2/token
And when I look at the postman-generated c# code, the mystery continues:
var client = new RestClient("https://login.microsoftonline.com/d1e...d3/oauth2/token");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("client_id", "c06bb...79");
request.AddParameter("client_secret", "7~u...D");
request.AddParameter("resource", "https://vault.azure.net");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Note the AddParameter constructions for a GET call. To me, this must be a slight-of-hand for merely adding those values to the querystring. But when I look at the postman console I see:
In the postman console I would have expected to see those params appended to the url as a querystring, and then everything would have made sense. But you can see that it's a bonafide Request Body.
When I make GET calls in my c# code I like to use the simple yet solid WebClient object to call the DownloadString() method. But this method is only for GETs and there's no way to send a form-post style body, understandably.
Is postman truly sending a GET with all those values being appended to the url as a querystring? And should I do the same in my DownloadString() call? Or is there something else going on here? Should I instead, in my c#, be calling the UploadString() method and sending a form post BODY as a GET??
Http protocol supports adding a body to a request, but the WebClient class you use doesn't. Presumably because it isn't considered the norm.
I'm sure there's good reasons for Microsoft using it in the OAuth flow though. Those guys normally do things right!
HTTP GET with request body
API is just an abstraction , you can send what ever you want to the API . It depends on the implementation , how the server handles these data.
Some services considers only what it requires and ignores other information
some services considers the entire requests and validates that it has only the allowed data. what should be allowed depends on the service
Postman is just a client that sends data to server , its upto you to decide what all information it should send . If you dont need any body then keep it as none. if you need some thing then add it.
I'm trying to send special characters through an http request, now I'm using Loopj as my http client. The problem is that when I try to send special characters i.e. "áéíóú" the request goes out with the characters "·ÈÌÛ˙", this is causing some issues on the server sider.
I've gone through the Loopj code and couldn't find anything relative to recoding my string or anything like it. In the worst case it seems like it would be encoded in UTF-8 which actually supports this characters.
Hope anyone can help.
Best Regards.
I am guessing you mean AsyncHttpClient library, correct?
AHC defaults to encoding all I/O in UTF-8. Due to the lack of source code, I would point you to investigate the following:
What is the encoding of the input? Make sure it's in UTF-8.
Are you running the input through a filter/function that might change its encoding? Make sure that the filter/function produces UTF-8 also.
Prior to checking what your backend actually receives, change your client to submit to http://httpbin.org/post and then check the result.
If you receive correct submission in httpbin, and bad submission in your backend, the problem is NOT in AHC but in your backend.
If you receive bad submissions in both httpbin and the backend, then the data being sent was originally bad or in a wrong encoding.
I hope this helps you find the problem quickly.
Why Don't you use this Approach:
HttpParams httpParameters = new BasicHttpParams();
HttpProtocolParams.setContentCharset(httpParameters, HTTP.UTF_8);
HttpProtocolParams.setHttpElementCharset(httpParameters, HTTP.UTF_8);
HttpClient client = new DefaultHttpClient(httpParameters);
client.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_1);
client.getParams().setParameter("http.socket.timeout", new Integer(2000));
client.getParams().setParameter("http.protocol.content-charset", HTTP.UTF_8);
httpParameters.setBooleanParameter("http.protocol.expect-continue", false);
HttpPost request = new HttpPost("http://www.server.com/some_script.php?sid=" + String.valueOf(Math.random()));
request.getParams().setParameter("http.socket.timeout", new Integer(5000));
List<NameValuePair> postParameters = new ArrayList<NameValuePair>();
// you get this later in php with $_POST['value_name']
postParameters.add(new BasicNameValuePair("value_name", "value_val"));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters, HTTP.UTF_8);
request.setEntity(formEntity);
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String lineSeparator = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append(lineSeparator);
}
in.close();
String result = sb.toString();
Users of above code says, this code works like charm. And i think if you are facing issues with your approach then you should change your approach to solve your problem.
See this Link which i found useful for you: Android default charset when sending http post/put - Problems with special characters
There is a authentication library that I have to use that helpfully does things like
Response.Redirect(url, false);
inside of it's method calls. I can't change this libraries code and it's fine for MVC style apps but in angular SPA -> WebApi apps this is just awful.
I really need a 401 otherwise I get into trouble with CORS when my angular scripts, using $http, try to call out to the auth server on another domain in response to the 302, that's if it even could as the Response.Redirect also sends down the object moved html and the angle brackets cause an error to be thrown.
Since I have to make the call to the auth library first the Response.Redirect is already in the response pipeline and so I need to clean it up to remove the body content and convert the 302 into a 401. I thought I could just:
return new HttpWebResponse(StatusCode.UnAuthorized){
Content = new StringContent("data");
}
but this just gets appended to the response and doesn't replace it plus I also need the Location: header which I can't seem to access via WebApi methods.
So instead I've had to do this in my ApiController:
var ctxw = this.Request.Properties["MS_HtpContext"] as HttpContextWrapper;
var ctx = ctxw.ApplicationInstance.Context;
var url = ctx.Response.RedirectLocation;
ctx.Response.ClearContent();
return new HttpWebResponse(StatusCode.UnAuthorized){
Content = new StringContent(url);
}
But this seems terrible and counter to webapi "feel". Plus I'm tied to the controller in doing this. I can't get the wrapper in a MessageHandler for example.
What I'd like to do is monitor the response for a given route in a message handler or in an AuthorizationFilterAttribute, if its a 302, I want to read it's headers, take what I want, wipe it and replace it with my own "fresh" response as a 401. How can I do this?
You might want to write your own ActionFilter and override its OnActionExecuted method where you can access HttpActionExecutedContext. From there, you can check response code, for example, and overwrite response with whatever you want.
Ref: https://msdn.microsoft.com/en-us/library/system.web.http.filters.actionfilterattribute.onactionexecuted%28v=vs.118%29.aspx#M:System.Web.Http.Filters.ActionFilterAttribute.OnActionExecuted%28System.Web.Http.Filters.HttpActionExecutedContext%29
I'm constructing an NSUrlSession as follows:
NSUrlSessionConfiguration sessionCfg = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration("mySpecialSessionName");
NSUrlSessionDelegate sessionDelegate = new MySessionDelegate();
urlSession = NSUrlSession.FromConfiguration(sessionCfg, sessionDelegate, NSOperationQueue.MainQueue);
And invoking background downloads with custom HTTP headers:
NSMutableUrlRequest mutableRequest = new NSMutableUrlRequest();
mutableRequest.HttpMethod = "POST";
mutableRequest.Url = NSUrl.FromString(someEndpoint);
mutableRequest["MyCustomHeader"] = someStringWithUnicodeChars;
mutableRequest.Body = NSData.FromString(somePostBody);
NSUrlSessionDownloadTask downloadTask = m_UrlSession.CreateDownloadTask(mutableRequest);
downloadTask.Resume();
However, the header value string seems to get truncated at the first character above 255. For example, the header value:
SupeЯ Σario Bros
is received by the server as
Supe
When instead using .NET HttpClient on xamarin, unicode header strings successfully make it to the server unmodified. However, I'd like to make use of NSUrlSession's background downloading feature.
(I realize that support of unicode in HTTP headers is hit-and-miss, but since the HTTP server in this case is a particular custom server that doesn't currently support things like base64 encoding, passing the raw string is desired)
I don't know whether you'll be able to make that work, but two things come to mind:
What you have here is equivalent to calling setValue:forKey: on the URL request. I don't think that will do what you're expecting. Try calling the setValue:forHTTPHeaderField: method instead.
Try specifying the encoding before you specify your custom header value, e.g. [theRequest setValue:#"...; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
If neither of those helps, you'll probably have to encode the data in some way. I would suggest using URL encoding, because that's a lot simpler to implement on the server side than Base64. For the iOS side, see this link for info on how to URL-encode a string:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/WorkingwithURLEncoding/WorkingwithURLEncoding.html
I have a program that should login to site, it uses POST requests, and all goes fine, until one of the values contain special character('%' for example).
captcha = "ABCDE" //all goes fine and well, server accept captcha
captcha = "ABC&%" //server dont accept captcha and return fail
//here is the bad part:
string request = "password=" + HttpUtility.UrlEncode(encpass, Encoding.UTF8) +
"&username=" + login + "&captcha_text=" + HttpUtility.UrlEncode(captcha, Encoding.UTF8);
Also, i ofcourse googled it, and checked all i could find. I though i need to "warn" server abaut encoding, so i added
request.Headers.TryAddWithoutValidation("Content-Type", #"application/x-www-form-urlencoded; charset=UTF-8");
but it still did not helped me.
Content types and way request should look like i get from Firebug, so if i can find some answers there - please point.
modify0: Also, i compared what my program send to server with browser request(using Firebug) and my request is completley same. Only difference - my request dont get accepted in values it contain special-characters.
modify1: Also, server have no problems handling special-characters when i check it in browser. For example it(browser) sent "K&YF82" as "captcha_text=K%26YF82"(same value in addres propereties and request body) and all worked fine. UrlEncode do same replacement, but in my program it doesnt get accepted by server.
SOLUTION:
{ password:"df464dsj", username:"username", captchaText:"ABC&%", remember_login:"false" }
insteat of
password=f2341f14f&username=username&captha...
Are you dealing with REST application??
If yes then send your post data in request body instead of query string.
Also have a look at the stack post at : Special characters pose problems with REST webservice communication