Uri validation in C# - c#

I am trying to implement uri validation as follows.
For the sake of testing, I assigned my url as an empty string "", and tested the following code, but it returns me True.
I wonder what I am doing wrong/missing?
var a = "";
if (Uri.IsWellFormedUriString(a, UriKind.RelativeOrAbsolute))
{
Debug.WriteLine("True");
}
else
{
Debug.WriteLine("Error");
}

See what RFC2396 says about URIs:
4.2. Same-document References
A URI reference that does not contain a URI is a reference to the
current document. In other words, an empty URI reference within a
document is interpreted as a reference to the start of that document,
and a reference containing only a fragment identifier is a reference
to the identified fragment of that document. Traversal of such a
reference should not result in an additional retrieval action.
However, if the URI reference occurs in a context that is always
intended to result in a new request, as in the case of HTML's FORM
element, then an empty URI reference represents the base URI of the
current document and should be replaced by that URI when transformed
into a request.
Casually, see what MSDN says:
The string is considered to be well-formed in accordance with RFC 2396
and RFC 2732 by default. If International Resource Identifiers (IRIs)
or Internationalized Domain Name (IDN) parsing is enabled, the string
is considered to be well-formed in accordance with RFC 3986 and RFC
3987
So how to handle the empty URI scenario?
The answer is up to you. While an empty URI can be considered as valid, maybe in your scenario isn't valid. Thus, you need to add a condition in your if statement:
if (!string.IsNullOrEmpty(a) && Uri.IsWellFormedUriString(a, UriKind.RelativeOrAbsolute))
{
}

Empty string is a valid relative URI.

Related

'#' letter is missing in HttpContext.Request or HttpContext.Current.Request url?

My URL is: http://localhost/myApp/app/job/7#/Nmbr
When I tried to get the URL from HttpContext.Request or HttpContext.Current.Request,
the given url is : /myApp/app/job/7
# and everything after this letter are missing? Why? How can I get the real current url?
Http requests do not include anything after # (The browser does not send it with the request.)
# Is intended to allow for parameters to be specified for the browser only (Anchor target location, or with often with web 2.0 JavaScript parameters)
In order to pass parameters to the server use ? that appears before the #
Here is some information regarding fragments (The part of the URL after #)
The Fragment property gets any text following a fragment marker (#) in the URI, including the fragment marker itself. Given the URI http://www.contoso.com/index.htm#main, the Fragment property would return #main.
https://msdn.microsoft.com/en-us/library/system.uri.fragment(v=vs.110).aspx

How do I create a dot prefixed cookie uri?

I am trying to pass a Uri of new Uri(".example.com")
Invalid URI: The format of the URI could not be determined.
or new Uri("http://.example.com")
Invalid URI: The hostname could not be parsed.
I need to be able to use the CookieContainer.SetCookies function which only has one overload taking a Uri.
According to this page, .NET 4.0 should support dot prefixed cookies now, but it seems the Uri class does not?
In this case, you need to pass a proper uri to the function, and the Uri parser is correctly rejecting the malformed string you are trying to use.
I would advise using the Cookie Constructor that takes 4 parameters - allowing you to set the domain to a dot-prefixed one.
Cookie(string name, string value, string path, string domain);

How to encode a path that contains a hash?

How do you properly encode a path that includes a hash (#) in it? Note the hash is not the fragment (bookmark?) indicator but part of the path name.
For example, if there is a path like this:
http://www.contoso.com/code/c#/somecode.cs
It causes problems when you for example try do this:
Uri myUri = new Uri("http://www.contoso.com/code/c#/somecode.cs");
It would seem that it interprets the hash as the fragment indicator.
It feels wrong to manually replace # with %23. Are there other characters that should be replaced?
There are some escaping methods in Uri and HttpUtility but none seem to do the trick.
There are a few characters you are not supposed to use. You can try to work your way through this very dry documentation, or refer to this handy URL summary on Stack Overflow.
If you check out this very website, you'll see that their C# questions are encoded %23.
Stack Overflow C# Questions
You can do this using either (for ASP.NET):
string.Format("http://www.contoso.com/code/{0}/somecode.cs",
Server.UrlEncode("c#")
);
Or for class libraries / desktop:
string.Format("http://www.contoso.com/code/{0}/somecode.cs",
HttpUtility.UrlEncode("c#")
);
Did some more digging friends and found a duplicate question for Java:
HTTP URL Address Encoding in Java
However, the .Net Uri class does not offer the constructor we need, but the UriBuilder does.
So, in order to construct a proper URI where the path contains illegal characters, do this:
// Build Uri by explicitly specifying the constituent parts. This way, the hash is not confused with fragment identifier
UriBuilder uriBuilder = new UriBuilder("http", "www.contoso.com", 80, "/code/c#/somecode.cs");
Debug.WriteLine(uriBuilder.Uri);
// This outputs: http://www.contoso.com/code/c%23/somecode.cs
Notice how it does not unnecessarily escape parts of the URI that does not need escaping (like the :// part) which is the case with HttpUtility.UrlEncode. It would seem that the purpose of this class is actually to encode the querystring/fragment part of the URL - not the scheme or hostname.
Use UrlEncode: System.Web.HttpUtility.UrlEncode(string)
class Program
{
static void Main(string[] args)
{
string url = "http://www.contoso.com/code/c#/somecode.cs";
string enc = HttpUtility.UrlEncode(url);
Console.WriteLine("Original: {0} ... Encoded {1}", url, enc);
Console.ReadLine();
}
}

Uri Constructor .NET Framework Bug?

Why the thirdRelativeUri fails? Is this a .NET bug? Seems like not fixed in 4.0 either.
var googleU = new Uri("http://www.google.com");
var secondRelativeUri = new Uri(googleU,"//test.htm"); // doesn't fail
var thirdRelativeUri = new Uri(googleU,"///test.htm"); // fails - Invalid URI: The hostname could not be parsed.
UPDATE:
#dariom pointed out that this is because protocol relative URL handling in .NET which make sense however this still seems buggy to me:
var thirdRelativeUri = new Uri("///test.htm",UriKind.Relative); // works as expected
var newUri = new Uri(googleU,thirdRelativeUri); //Fails, same error even though it's a relative URI
It fails even when the second Uri is Relative
The file uri scheme (RFC 1738) file://[host]/path shows that host is optional. ///test.html would mean "Since this usually used for local files the host from RFC 1738 is often empty leading to a starting triple /. (ref)"
Change ///test.htm to file:///test.htm and the URI constructor will parse it properly. It's AbsolutePath will be /test.html.
Hope this helps.
I think that the constructor is interpreting "//test.htm" as a URI with no scheme and a hostname of test.htm. You can see this by examining the value of secondRelativeUri - it's "http://test.htm/".
The third URI you're creating is invalid because you have too many slashes.
new Uri(googleU,"//test.htm") mean Uri = http://test.html/ /* valid, Anyway a root somewhere */
new Uri(googleU,"///test.htm") mean Uri = http:///test.html/ /* invalid, Meaningless */
new Uri("///test.htm",UriKind.Relative); //=> Uri = ///test.htm same mistake, not relative location
var r = new Uri("test.htm",UriKind.Relative);
new Uri(googleU, r); // => Uri = http://www.google.com/test.htm
Even when creating relative URLs, .net treats a string that starts with tow slashes as a host name like in "//example.org/document". Similarly three slahes makes a confusion and an exception is thrown. If you are pretty sure these //test.htm and ///test.htm are paths, then you can try using UriBuilder class.

Encountered invalid root element name 'HTML'. 'root' is the only allowed root element name

i am using msdn sample code and it has jsonp wrapper files you can find the code here
of this article and MSDN article JSON with Padding (AJAX)
but when i run the code it throw me this error:
Encountered invalid root element name 'HTML'. 'root' is the only allowed root element name
what does it mean?
It means that you've made some kind of web request that is expecting to get some kind of XML data back but instead it is getting HTML data back. The usual cause is a messed up URL. If your URL were correct, then XML would be returned as expected. Since it is messed up you end up getting back HTML (probably an error page at that).
Check your URLs to make sure they are correct.
I found the solution to similar problem. In my case, I was getting similar error, when my service was returning raw JSON, that is to say it was returning a Stream which represented this JSON.
The error was: Encountered invalid root element name 'Binary'. 'root' is the only allowed root element name.
The problem is that the MS provided example uses JsonWriter to take convert the message to JSON, but this writer expects that your message consists of JSON objects which he can convert to Stream. In my case the message was compose of binary data, so instead of one "root" element I was having "Binary" element.
I got over this issue by modifying classes provided by the MS sample. Basically I check the format of the message - if it is JSON I can still use the JsonWriter, if it is Binary, I have to take a different approach. In your case the message is in HTML format (I am not sure how do you serve it), but you will find a different way to get the body of the message.
I wrote a blog post about my issue here: http://hoonzis.blogspot.com/2011/07/provide-jsonp-with-your-wcf-services.html
Hope it helps a bit, Honza
I ran into the same error message but in a different scenario. I was adding JSON support to a WCF web service that only supported XML.
Specifically I wanted to return the error messages object in JSON also.
I had a class that was implementing System.ServiceModel.Dispatcher.IErrorHandler. Within the ProvideFault method I was setting the `WebBodyFormateMessageProperty to the corresponding one wither, XML or JSON based on what it was passed in the accept header. I was also setting the content type accordingly. What I was missing was using the correct serializer for each case
Dim webBodyFormatMessageProp As Channels.WebBodyFormatMessageProperty
Dim contentType As String
Dim serializer As XmlObjectSerializer
If WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json Then
webBodyFormatMessageProp = New System.ServiceModel.Channels.WebBodyFormatMessageProperty(System.ServiceModel.Channels.WebContentFormat.Json)
contentType = "application/json"
serializer = New DataContractJsonSerializer(GetType(MyErroClass))
Else
webBodyFormatMessageProp = New System.ServiceModel.Channels.WebBodyFormatMessageProperty(System.ServiceModel.Channels.WebContentFormat.Xml)
contentType = "text/xml"
serializer = New DataContractSerializer(GetType(MyErroClass))
End If
Dim detail = faultException.[GetType]().GetProperty("Detail").GetGetMethod().Invoke(faultException, Nothing)
fault = System.ServiceModel.Channels.Message.CreateMessage(version, "", detail, serializer)
fault.Properties.Add(System.ServiceModel.Channels.WebBodyFormatMessageProperty.Name, webBodyFormatMessageProp)
Dim httpResponseMessageProp = New System.ServiceModel.Channels.HttpResponseMessageProperty()
httpResponseMessageProp.Headers(System.Net.HttpResponseHeader.ContentType) = contentType
httpResponseMessageProp.StatusCode = System.Net.HttpStatusCode.OK
httpResponseMessageProp.StatusDescription = [error].Message
fault.Properties.Add(System.ServiceModel.Channels.HttpResponseMessageProperty.Name, httpResponseMessageProp)
Apologize for the VB.net but that is what I am currently working on.

Categories