C#: Sending HTTP GET request without UTF-8 encoding - c#

I need to send HTTP GET request from C# to CLASSIC ASP service.
The service is built in a way that it decodes the data from the QueryString using Windows-1255 encoding, rather than the standard UTF-8.
It seems that HttpWebRequest class always encodes GET data with UTF-8 and it doesn't work for me. Is there any way to send HTTP GET request from C#, while GET data is encoded with different than UTF-8 encoding?
Thanks.

You need to set a header on your get request:
Content-Type:text/xml; Charset=windows-1255
HttpRequest r = new HttpRequest(.....);
r.Headers.Add("Content-Type", "text/xml; Charset=windows-1255");
Maybe this post will be of some use too:
Read non-english characters from http get request

Ok, I finally got the answer.
First of all, specifying ContentType in the header doesn't work.
If destination URL is containing none-English letters, the HttpWebRequest will always use UTF-8 + URLEncode to build the final URI the request is sent to.
To use encoding different from UTF-8 I needed to encode URL values by myself (instead of providing necessary encoding to HttpWebRequest as I expected).
Following function that builds HTTP GET URL, while values are encoded with any requested encoding (and not with the default UTF-8):
string BuildData(NameValueCollection getData, Encoding enc)
{
StringBuilder urldata = new StringBuilder();
for (int i = 0; i < getData.Count; i++)
{
if (i > 0) urldata.Append("&");
urldata.Append(getData.Keys[i] + "=" + HttpUtility.UrlEncode(enc.GetBytes(getData[i])));
}
return urldata.ToString();
}
The HttpWebRequest can be used with something like
"http://get-destination.com/submit?" + BuildData(keysAndValues, Encoding.GetEncoding(1255));
In this case HttpWebRequest gets already encoded URL which doesn't contain none-English letters and it keeps it as is.

Related

Block length does not match with its complement

I'm trying to handle a redirect authentication piece for a site we have. I configured ADFS on Server2012 R2 to handle this. I set up the relying party trust with a URL in our domain that I'm sending requests from. I added an endpoint back to the specific page they're coming from.
Basically, I'm taking this stuff here: How do I correctly prepare an 'HTTP Redirect Binding' SAML Request using C#
to try and send over a simple SAML request token.
public static string SAMLRequest = #"<samlp:AuthnRequest
xmlns:samlp=""urn:oasis:names:tc:SAML:2.0:protocol""
xmlns:saml=""urn:oasis:names:tc:SAML:2.0:assertion""
ID=""{0}""
Version=""2.0""
AssertionConsumerServiceIndex=""0""
AttributeConsumingServiceIndex=""0"">
<saml:Issuer>URN:xx-xx-xx</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate = ""true""
Format=""urn:oasis:names:tc:SAML:2.0:nameid-format:transient"" />
</samlp:AuthnRequest>";
This is the template URL I'm sending over as a C# string (for the escape characters, and the string replacement on the ID value).
And here is the code I'm using to generate the request parameter that's going into my redirect URL:
public static string GetSAMLHttpRedirectUri(string idpUri)
{
var saml = string.Format(SAMLRequest, Guid.NewGuid());
var bytes = Encoding.UTF8.GetBytes(saml);
using (var output = new MemoryStream())
{
using (var zip = new DeflaterOutputStream(output))
{
zip.Write(bytes, 0, bytes.Length);
}
var base64 = Convert.ToBase64String(output.ToArray());
var urlEncode = HttpUtility.UrlEncode(base64);
return string.Concat(idpUri, "?SAMLRequest=", urlEncode);
}
}
When all is said and done, the page redirects me to the appropriate endpoint with the token base64 encoded properly. Well, sort of properly.
On the AD FS side of things, I get an error on the page and then it just stops authenticating. Looking in the event viewer of AD FS, it gives me this cryptic error:
System.IO.InvalidDataException: Block length does not match with its complement.
I've tried fiddling with the compression and some of the properties on the request object itself, to no avail. Anyone have any ideas I could try on this bad boy?
Assuming DeflaterOutputStream is from SharpZipLib, new DeflaterOutputStream(output) will, in fact, give you a ZLIB output stream, that is RFC 1950, not actually DEFLATE, from RFC 1951. The difference is only that ZLIB adds a header and footer to DEFLATE, which you can suppress in SharpZipLib with new DeflaterOutputStream(output, new Deflater(level: Deflater.DEFAULT_COMPRESSION, noZlibHeaderOrFooter: true)).

C# HttpWebRequest GET partially encoded url

When I send a get using HttpWebRequest is seems to turn it into a uri, run it through an encoder and send the encoded string. When I look at my address in the request after it is created I have the OriginalString which is correct and an AbsoluteUri which is encoded and incorrect. My code and example urls are below.
HttpWebRequest webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
String responseData = WebResponseGet(webRequest);
OriginalString:"https://api.linkedin.com/v1/people/url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Ffirstmlast"
AbsoluteUri:"https://api.linkedin.com/v1/people/url=https%3A//www.linkedin.com/in/firstmlast"
How can I force HttpWebRequest to send my original string that I passed it and not a uri? Also I cannot send the already encoded string as a query string, LinkedIn requires it to be apart of the url.
I found a HackedUri class here: http://blogs.msdn.com/b/xiangfan/archive/2012/01/16/10256915.aspx and created my request like this passing it a "Hacked Uri" instead of a string. This seems to be a security limitation problem with .Net.
HttpWebRequest webRequest = System.Net.WebRequest.Create(HackedUri.Create(url)) as HttpWebRequest;
Have you tried double-encoding the relevant part of the URL?
var request = WebRequest.CreateHttp("https://api.linkedin.com/v1/people/url=" + HttpUtility.UrlEncode("https%3A%2F%2Fwww.linkedin.com%2Fin%2Ffirstmlast"));

Encode header value using WebClient.Headers.Add()

I am using HTTP headers to send a string which contains Unicode characters (such as ñ) to a custom http server.
When I add the string as a header:
webClient.Headers.Add("Custom-Data", "señor");
It is interpreted by the server as:
se�or
Obviously I need to encode the value differently, but I am unsure what encoding to use.
How should I encode this HTTP header to preserve extended/special characters?
porneL's answer to a related question is confusing.
Unanswered, related: C# WebClient non-english request header value encoding
As #Jordan suggested, representing the string as base64 (with UTF8 encoding) worked well:
On the client side:
webClient.Headers.Add("Custom-Data",
Convert.ToBase64String(Encoding.UTF8.GetBytes("señor")));
And on the server:
string customData = Encoding.UTF8.GetString(Convert.FromBase64String(customHeader.Value));

What characters are html encoded?

TL;DR Düsseldor is encoded to D&#252;sseldor, Düsseldorf isn't encoded (by the default MVC encoding) why?
I'm building an api with soap access. When I get a request I html encode all the data.
Just before I end the current request I copy the Response.Stream and save it for logging.
I noticed that Düsseldorf is encoded by my api to "Düsseldorf". This is expected.
But in my logs it shows Düsseldorf encoded as "D&#252;sseldorf" ( double encoded ) my logs saves after the MVC serializes writes to the response stream.
I think this is because soap encodes values before sending them over the wire.
So my next test was to turn off html encoding in my api.
So this time Düsseldorf was giving to the soap serializer.
But it was encoded as Düsseldorf?
EDIT: When I say I turn on / off the encoding what I mean is each field in the request I use HttpUtility.HtmlEncode("some field"). And save that to the database. Then I return the data with an MVC view like so:
public ActionResult CreateAccessCode ( CreateAccessCodeRequest request )
{
var response = new Response (request);
return new ContentResult (response);
}
My question is when the ContentResult method runs, it seems to do some encoding of its own and I was wondering what that was?
SOAP uses XML - HTML and XML require slightly different encoding, but it may or may not be a problem in your case.
Much more likely your manual construction of XML is not correct. Please do not construct XML with string concatenation - XDocument/XmlDocument are much more suitable for that.

Encoding my string to send an http request via C#

I am trying to send a simple HTTP request like this:
var client = new WebClient();
string myString="this is the string i want to send";
message = client.DownloadString("http://www.viralheat.com/api/sentiment/review.xml?text=" + myString + "&api_key="+currentKey);
but some of the strings I send includes # or & or such characters, so I want to encode the string first before sending it, because it throws an error if it includes these special characters without being encoded.
Call Uri.EscapeDataString.
Unlike HttpUtility, this works on the client profile too.
Use HttpUtility.UrlEncode

Categories

Resources