I am programatically trying to POST to a web-service. The issue I face is with my data that I post.
Despite
string post_data = "man=HE&game=01&&address=123 Main St.&cap=1,2,3,4";
new ASCIIEncoding().GetBytes( post_data )
it is not getting converted to
man=HE&game=01&&address=123+Main+St.&cap=1%2C2%2C3%2C4
What is the best way to resolve this?
You are only getting a byte stream that way. In order to URL encode the string you could use the URLEncode method of the HttpUtility helper class:
string post_data = "man=HE&game=01&&address=123 Main St.&cap=1,2,3,4";
string[] postTokens = post_data.Split(new Char [] {'&'});
for(int i = 0; i < postTokens.Length; i++)
{
int pos = postTokens[i].IntexOf("=");
string name = postTokens[i].Substring(0, pos);
string value = postTokens[i].Substring(pos + 1);
postTokens[i] = String.Format("{0}={1}", name, HttpUtility.UrlEncode(value));
}
string encodedPostData = String.Join("=", postTokens);
var encodedPostDataBytes = ASCIIEncoding.GetBytes(encodedPostData);
I think you're confusing ascii encoding with url encoding.
You'll want to use System.Web.HttpServerUtility.UrlEncode method and encode each element of the query string separately.
string post_data =
"man=" + HttpUtility.UrlEncode("HE") +
"&game=" + HttpUtility.UrlEncode("01") // and so forth
Related
I'm trying to send percent-encoded ASCII characters using HttpWebRequest, for example https://example.com/%74%65%73%74
Using POSTMAN I'm able to send a request and see in charles that it's still encoded, however, regardless of what I do, any C# library will simplify this to https://example.com/test.
Is there any workaround or async compatible library to work around this?
Thanks in advance
Example Code
string newURL = "";
string path = "test";
foreach (char character in path)
{
string charac = "";
string finished = "";
if (character != '-' || character != '/')
{
if (random.Next(1, 10) >= 5)
{
charac = "%" + Convert.ToInt32(character).ToString("X");
}
else
{
charac = character.ToString();
}
}
newURL = newURL + charac;
}
string main = "http://www.example.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(main + "/en/" + newURL);
In my C# console application, using google translate service I am programmatically trying to translate MyResources.resx file into MyResources.fr-CA.resx
Here is the code:
public static string TranslateText(string input, string languagePair)
{
string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", input, languagePair);
WebClient webClient = new WebClient();
webClient.Encoding = System.Text.Encoding.UTF8;
string result = webClient.DownloadString(url);
result = result.Substring(result.IndexOf("<span title=\"") + "<span title=\"".Length);
result = result.Substring(result.IndexOf(">") + 1);
result = result.Substring(0, result.IndexOf("</span>"));
return result.Trim();
}
static void Main(string[] args)
{
var resWriter = new ResourceWriter("Translations.resources");
ResourceSet resourceSet = MyResources.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (DictionaryEntry entry in resourceSet)
{
string resKey = entry.Key.ToString();
string resValue = entry.Value.ToString();
var result = TranslateText(resValue, "en|fr-CA");
if (result != null)
{
resWriter.AddResource(resKey, System.Web.HttpUtility.HtmlDecode(result));
}
}
resWriter.Close();
}
Problem is that some french characters show up as "?" character in resulting Resources.fr-CA.resx file and that also, only if I use System.Web.HttpUtility.HtmlDecode, otherwise it shows characters for example like "d'"
So how can I programmatically insert French based values in a resource file correctly?
You have to change your webClient encoding type to decode French characters properly.
So this line:
webClient.Encoding = System.Text.Encoding.UTF8;
Have to be like this:
webClient.Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
and your "result" variable (after calling TranslateText method) should be readable in French correctly.
Please try this way and inform me, it worked for me.
Regards.
I've been looking around and all of the answers I've found are either not C#, use the V2.0 API or use a method that doesn't return a valid result for videos with embedding disabled.
Here's what I'm currently using, from a response I found a while back:
public string GetYouTubeTitle(string url)
{
string id = GetArgs(url, "v", '?');
WebClient client = new WebClient();
return "YouTube Video: \"" + GetArgs(client.DownloadString("http://youtube.com/get_video_info?video_id=" + id), "title", '&') + "\"";
}
public string GetArgs(string args, string key, char query)
{
int iqs = args.IndexOf(query);
string querystring = null;
if (iqs != -1)
{
querystring = (iqs < args.Length - 1) ? args.Substring(iqs + 1) : string.Empty;
NameValueCollection nvcArgs = HttpUtility.ParseQueryString(querystring);
return nvcArgs[key];
}
return string.Empty;
}
It works perfectly the first time round, but the second video I tested returned the error: "&errorcode=150&reason=This+video+contains+content+from+Studio71_1_1.+It+is+restricted+from+playback+on+certain+sites"
My goal is just to get the title of a youtube video given the URL. But everything I'm seeing is either vague as hell or is only valid for the 2.0 API which doesn't even work anymore.
EDIT: And at some point I might want to add more to the response such as the length of the video. So I would prefer to have the API working than to just use something like get_video_info if possible.
EDIT:
For completeness and to help anyone who might be looking at this later on this is what I've got now that works like I want:
string titleurl = "https://www.googleapis.com/youtube/v3/videos?part=snippet&id=" + GetArgs(url, "v", '?') + "&key=" + apikey;
string timeurl = "https://www.googleapis.com/youtube/v3/videos?id=" + GetArgs(url, "v", '?') + "&part=contentDetails&key=" + apikey;
HttpWebRequest titlerequest = (HttpWebRequest)WebRequest.Create(titleurl);
HttpWebResponse titleresponse = (HttpWebResponse)titlerequest.GetResponse();
Stream titlestream = titleresponse.GetResponseStream();
StreamReader titlereader = new StreamReader(titlestream);
string titlejson = titlereader.ReadToEnd();
Newtonsoft.Json.Linq.JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(titlejson);
string title = (string)jObject["items"][0]["snippet"]["title"];
HttpWebRequest timerequest = (HttpWebRequest)WebRequest.Create(timeurl);
HttpWebResponse timeresponse = (HttpWebResponse)timerequest.GetResponse();
Stream timestream = timeresponse.GetResponseStream();
StreamReader timereader = new StreamReader(timestream);
string timejson = timereader.ReadToEnd();
Newtonsoft.Json.Linq.JObject jObjectTime = Newtonsoft.Json.Linq.JObject.Parse(timejson);
string time = ParseTime((string)jObjectTime["items"][0]["contentDetails"]["duration"]);
if (title.Length > 0 && time.Length > 0 && time != "0")
return "YouTube Video: \"" + title + "\" (" + time + ")";
else return error; //error is a preset generic error string
It's probably not the cleanest code around, but it's doing what I want. So I don't really mind.
You can get the video title by using the YouTube Data API v3:
You need to get your API key from Here:
Make a GET request to this URL as described in the documentation:
https://www.googleapis.com/youtube/v3/videos?part=snippet&id=v2AC41dglnM,kTHNpusq654&key=YourAPIKeyHere
Parse the response you get with something like Json.NET:
try this:
First you need to install VideoLibrary on your visual studio package manager :
**Install-Package VideoLibrary**
using VideoLibrary;
Let's make a function to get the YouTube video title:
public string getTitle (string url){
YouTube ytb = YouTube.Default; //starting point for YouTube actions
var vid = ytb.GetVideo(url); // gets a Video object with info about the video
string ttl = vid.Title;//get video Title
return ttl;
}
I have the string string test="http://www.test.com//web?testid=12".
I need to replace with in the string // into /.
Problem is if I use string a=test.replace("//","/") I get http:/www.test.com/web?testid=12 all with single slash(/) but I need http://www.test.com/web?testid=12.
I need only the second // nearby web, not first // near by www.
How to do this?
You can make second replace
string test="http://www.test.com//web?testid=12";
string a=test.Replace("//","/").Replace("http:/","http://");
=)
string test = #"http://www.test.com//web?testid=12";
test = test.Substring(0, test.LastIndexOf(#"//") - 1)
+ test.Substring(test.LastIndexOf(#"//")).Replace(#"//", #"/");
Or since its a Uri, you can do:
Uri uri = new Uri(test);
string newTest = uri.Scheme + #"//" + uri.Authority
+ uri.PathAndQuery.Replace(#"//",#"/");
string test="http://www.test.com//web?testid=12"
string[] test2 = test.Split('//');
string test = test2[0] + "//" + test2[1] + "/" + test2[2];
Regex.Replace(test, "[^:]//", "/");
you can use stringbuilder as well.
StringBuilder b =new StringBuilder();
b.Replace("/","//",int startindex,int count);
Simply remove one of the last slashes with String.Remove():
string test="http://www.test.com//web?testid=12";
string output = test.Remove(test.LastIndexOf("//"), 1);
var http = "http://someurl//data";
var splitindex = http.IndexOf("/") + 1;
var res = http.Substring(splitindex+1, (http.Length-1) - splitindex).Replace("//","/");
http = "http://" + res;
Or
StringBuilder strBlder = new StringBuilder();
strBlder.Append("http://someurl//data");
//use the previously used variable splitindex
strBlder.Replace("//", "/", splitindex + 1, (http.Length) - splitindex);
I have a binary file (i.e., it contains bytes with values between 0x00 and 0xFF). There are also ASCII strings in the file (e.g., "Hello World") that I want to find and edit using Regex. I then need to write out the edited file so that it's exactly the same as the old one but with my ASCII edits having been performed. How?
byte[] inbytes = File.ReadAllBytes(wfile);
string instring = utf8.GetString(inbytes);
// use Regex to find/replace some text within instring
byte[] outbytes = utf8.GetBytes(instring);
File.WriteAllBytes(outfile, outbytes);
Even if I don't do any edits, the output file is different from the input file. What's going on, and how can I do what I want?
EDIT: Ok, I'm trying to use the offered suggestion and am having trouble understanding how to actually implement it. Here's my sample code:
string infile = #"C:\temp\in.dat";
string outfile = #"C:\temp\out.dat";
Regex re = new Regex(#"H[a-z]+ W[a-z]+"); // looking for "Hello World"
byte[] inbytes = File.ReadAllBytes(infile);
string instring = new SoapHexBinary(inbytes).ToString();
Match match = re.Match(instring);
if (match.Success)
{
// do work on 'instring'
}
File.WriteAllBytes(outfile, SoapHexBinary.Parse(instring).Value);
Obviously, I know I'll not get a match doing it that way, but if I convert my Regex to a string (or whatever), then I can't use Match, etc. Any ideas? Thanks!
Not all binary strings are valid UTF-8 strings. When you try to interpret the binary as a UTF-8 string, the bytes that can't be thus interpreted are probably getting mangled. Basically, if the whole file is not encoded text, then interpreting it as encoded text will not yield sensible results.
An alternative to playing with binary file can be: converting it to hex string, working on it(Regex can be used here) and then saving it back
byte[] buf = File.ReadAllBytes(file);
var str = new SoapHexBinary(buf).ToString();
//str=89504E470D0A1A0A0000000D49484452000000C8000000C808030000009A865EAC00000300504C544......
//Do your work
File.WriteAllBytes(file,SoapHexBinary.Parse(str).Value);
PS: Namespace : System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary
I got it! Check out the code:
string infile = #"C:\temp\in.dat";
string outfile = #"C:\temp\out.dat";
Regex re = new Regex(#"H[a-z]+ W[a-z]+"); // looking for "Hello World"
string repl = #"Hi there";
Encoding ascii = Encoding.ASCII;
byte[] inbytes = File.ReadAllBytes(infile);
string instr = ascii.GetString(inbytes);
Match match = re.Match(instr);
int beg = 0;
bool replaced = false;
List<byte> newbytes = new List<byte>();
while (match.Success)
{
replaced = true;
for (int i = beg; i < match.Index; i++)
newbytes.Add(inbytes[i]);
foreach (char c in repl)
newbytes.Add(Convert.ToByte(c));
Match nmatch = match.NextMatch();
int end = (nmatch.Success) ? nmatch.Index : inbytes.Length;
for (int i = match.Index + match.Length; i < end; i++)
newbytes.Add(inbytes[i]);
beg = end;
match = nmatch;
}
if (replaced)
{
var newarr = newbytes.ToArray();
File.WriteAllBytes(outfile, newarr);
}
else
{
File.WriteAllBytes(outfile, inbytes);
}