Why does System.Uri break my url? - c#

I have the following C# code Uri uri = new Uri("http://localhost/query?param=%E2%80%AE"); and uri interprets it like http://localhost/query?param= instead of http://localhost/query?param=%E2%80%AE. As a result http web server gets http://localhost/query?param= (without value of this parameter). Why does it break my url and how can I create HttpWebRequest correctly using my http://localhost/query?param=%E2%80%AE?
P.S. I have got the %E2%80%AE using System.Uri.EscapeDataString(Convert.ToString((char)8238)).

ToString() will try to render the uri as a string. i.e., it will unescape escaped characters. However the escaped sequence %E2%80%AE is not printable.
Use the AbsoluteUri instead.
var uriStr = uri.AbsoluteUri; // "http://localhost/query?param=%E2%80%AE"

This is kind of mis-using of the methods exposed.
ToString() method, as derived from very first ancestor, Object, is a way to provide some printable form of the given object instance. It's not meant to be instance identity nor full serialization of all internal fields.
Uri class is designed as a URI parser/composer/dissector so it has various methods to merge or split given URI strings to get server name, local path etc. So if you need URI as a whole thing you have to use "Uri.AbsolutePath Property" http://msdn.microsoft.com/en-us/library/system.uri.absolutepath(v=vs.110).aspx

Related

Create new Uri using Url encoded string in C#

Question:
I need to create Uri which Contains all its attributes like (OriginalString, Query) as URL encoded.
What I tried:
I am able to format input string of Uri with below options:
string encodedString = inputString.Replace("'", "%27"); //example encoding
OR
System.Net.WebUtility.UrlEncode (inputString)
Tried all approaches to convert string to encoded string, like EscapeDataString/EscapeUriString etc
What I need to achieve
var uri = new Uri(encodedString);
When I create new Uri (like above) again %27 is replaced by '.
UPDATE 1:
Not all fields of uri are converted into %27. OriginalString is converted in my case.
I want to pass this uri to HttpClient.
Do we have any mechanism to make Uri with encoded string.
Based on locale settings and used keyboard, iOS may use some other apostrophe-like character, for example right single quotation mark U+2019 (').
Solution was to handle that.
Give it a try with HttpUtility.UrlEncode(input string).
Refer to https://secretgeek.net/uri_enconding for more details.

UrlPathEncode() alternative

The MSDN page for UrlPathEncode states the UrlPathEncode shouldn't be used, and that I should use UrlEncode instead.
Do not use; intended only for browser compatibility. Use UrlEncode.
But UrlEncode does not do the same thing as UrlPathEncode.
My use case is that I want to encode a file system path so that a file can be downloaded. The spaces in a path need to be escaped, but not the forward slashes etc. UrlPathEncode does exactly this.
// given the path
string path = "Directory/Path to escape.exe";
Console.WriteLine(System.Web.HttpUtility.UrlPathEncode(path));
// returns "Installer/My%20Installer.msi" <- This is what I require
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path));
// returns "Installer%2fMy+Installer.msi"
// none of these return what I require, either
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.ASCII));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.BigEndianUnicode));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.Default));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.UTF32));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.UTF7));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.UTF8));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(path, Encoding.Unicode));
Another method I've tried is using Uri.EscapeDataString, but this escapes the slashes.
// returns Directory%2FPath%20to%20escape.exe
Console.WriteLine(Uri.EscapeDataString(path));
Question:
If I'm not supposed to use UrlPathEncode, and UrlEncode doesn't produce the required output, what method is equivalent and recommended?
It's funny that when trying to write a question properly, you find your answer:
Uri.EscapeUriString(path);
Produces the required output.
I do think the MSDN page should reflect this, though.
Edit (2020-11-22)
I've recently come across this again, but needing to URL encode URLs with special characters (instead of file names with spaces), but it's essentially the same thing. The approach I used this time was to instantiate the Uri class:
var urlWithSpecialChars = "https://www.example.net/something/contàins-spécial-chars?query-has=spécial-chars-as-well";
var uri = new Uri(urlWithSpecialChars);
// outputs "https://www.example.net/something/contàins-spécial-chars?query-has=spécial-chars-as-well"
Debug.WriteLine(uri.OriginalString);
// outputs "https://www.example.net/something/cont%C3%A0ins-sp%C3%A9cial-chars?query-has=sp%C3%A9cial-chars-as-well"
Debug.WriteLine(uri.AbsoluteUri);
// outputs "/something/cont%C3%A0ins-sp%C3%A9cial-chars?query-has=sp%C3%A9cial-chars-as-well"
Debug.WriteLine(uri.PathAndQuery);
This give you quite a bit of useful Uri properties that are likely to cover most/many Uri processing requirements:

How to get query string with multiple param

I have a url:
http://www.abc.com?refurl=/english/info/test.aspx?form=1&h=test&s=AB
If I use
Request.QueryString["refurl"
but gives me
/english/info/test.aspx?form=1
instead I need full url
/english/info/test.aspx?form=1&h=test&s=AB
Fix the problem, and the problem is that you place a full url as parameter refurl with out encoding it.
So where you create that url string use the UrlEncode() function, eg:
"http://www.abc.com?refurl=" + Server.UrlEncode(ReturnUrlParam)
where
ReturnUrlParam="/english/info/test.aspx?form=1&h=test&s=AB";
For that particular case you shouldn't use QueryString, (since your query string contains three parameters,) instead use Uri class, and Uri.Query will give you the required result.
Uri uri = new Uri(#"http://www.abc.com?refurl=/english/info/test.aspx?form=1&h=test&s=AB");
string query = uri.Query;
Which will give you :
?refurl=/english/info/test.aspx?form=1&h=test&s=AB
Later you can remove ?refurl= to get the desired output.
I am pretty sure there is no direct way in the framework for your particular requirement, you have to implement that in your code and that too with string operations.
I had similar situation some time ago.
I solved it by encoding refurl value.
now my url looks similar to that one:
http://www.abc.com?refurl=adsf45a4sdf8sf18as4f6as4fd
I have created 2 methods:
public string encode(string);
public string decode(string);
Before redirect or where you have your link, you simple encode the link and where you are reading it, decode before use:
Response.redirect(String.Format("http://www.abc.com?refurl={0}", encode(/english/info/test.aspx?form=1&h=test&s=AB));
And in the page that you are using refurl:
$refUrl = Request.QueryString["refurl"];
$refUrl = decode($refUrl);
EDIT:
encode/decode methods I actually have as extension methods, then for every string I can simply use string.encode() or string.decode().
you should replace the & with &.

Passing current page url as a parameter in url

I have a repeater.Insidea a repeater there is a button.On item Command I try
protected void rptPost_ItemCommand(object source, RepeaterCommandEventArgs e)
{
int contentID = Int32.Parse(e.CommandArgument.ToString());//Its return 1
string host = HttpContext.Current.Request.Url.ToString();//its return http://localhost:1377/Forum.aspx
//string URL = "~/Modules/Forum/PostDetails.aspx?ID=" + contentID +"&BackUrl=" + host;//Need help hear its not work
string URL = "~/Modules/Forum/PostDetails.aspx?ID=" + contentID ;//Its work
Response.Redirect(URL);
}
when I only try to pass ID its work but if I try to pass multipal url one is ID and next is Current Page Url its unable to find page.And gives page not found error.I unable to understand the problem.Passing Url as a parameter is not support or I missing some thing.Thanks.
Here is the solution:
host = HttpUtility.UrlEncode(host)
and here is why it works:
You are passing the host URL as a GET parameter. GET parameters are part of the GET URI for the redirect. URI syntax includes characters with special meanings, in particular you are using colon (:) and slash (/), which have special meaning in a URI string. In almost all cases special characters should not be used as part of your GET parameter data values.
For cases such as yours, where there is a need to include special characters, UrlEncoding was developed. UrlEncoding, or Percent-encoding, substitutes special characters in URIs with values encoded using the percent sign. These escape sequences are automatically converted back to the original special character as part of URI query processing. The HttpUtility class provides the UrlEncode method as a convenient way to escape all special characters in an input string.
Please note that it is a good idea to URL encode all data that you pass via GET parameters unless you have full control over the data being passed and you can guarantee that encoding is not necessary. This can be a security issue because attackers can include new parameters and otherwise manipulate your URI if you pass user input to a GET parameter without first URL encoding it.

C# URL QueryString Trouble

I have a WP7 project where I am using the below code. It normally works ok, but I am getting a strange result with some particular strings being passed through.
Service = "3q%23L3t41tGfXQDTaZMbn%23w%3D%3D?f"
NavigationService.Navigate(new Uri("/Details.xaml?service=" + Service, UriKind.Relative));
Next Page:
NavigationContext.QueryString.TryGetValue("service", out Service1);
Service1 now = 3q#L3t41tGfXQDTaZMbn#w==?f
Why has the string changed?
The string hasn't changed, but you're looking at it in two different ways.
The way to encode 3q#L3t41tGfXQDTaZMbn#w==?f for as URI content is as 3q%23L3t41tGfXQDTaZMbn%23w%3D%3D?f. (Actually, it's 3q%23L3t41tGfXQDTaZMbn%23w%3D%3D%3Ff but you get away with the ? near the end not being properly escaped to %3F in this context).
Your means of writing the string, expects to receive it escaped.
Your means of reading the string, returns it unescaped.
Things are working pretty much perfectly, really.
When you need to write the string again, then just escape it again:
Service = Uri.EscapeDataString(Service1);
In your first code snippet the string is URL Encoded.
In the 2nd code snippet, the string is URL Decoded.
They are essentially the same strings, just with encoding applied/removed.
For example: urlencoding # you get %23
For further reading check out this wikipedia article on encoding.
Since HttpUtility isn't part of WP7 Silverlight stack, I'd recommend using Uri.EscapeUriString to escape any URI's that have not been escaped.
You should probably URL encode the string if you want it to pass through unscathed.

Categories