views:

113

answers:

1

In a custom configuration section of a config file I want to have properties or elements define a new scheme, host and port for a service endpoint, but not define the path. So these should be allowed https://newhost/ or http://newhost:800, but not newhost:800, http://newhost/path/to/service.

What would be the best option to implement?

It feels like there should be a good overload of a Uri.Parse, UriParser that would make it easy. Is there a UriValidator that I have missed? Or is regex going to be the best option (so that it can easily disallow the path)?

Note that this isn't specific to a ConfigurationValidator as a general validator that can be reused would be useful.

+1  A: 

There is always the GetLeftPart method of the Uri class that could help here.

GetLeftPart Method

The GetLeftPart method takes an enumeration from the UriPartial system enumeration, one of which (UriPartial.Authority) will return:

The scheme and authority segments of the URI.

This effectively removes any extraneous path information that may be in the original string, and will usually return a zero-length string if the Uri supplied does not contain a valid scheme (i.e. the http or https etc. parts of the Uri) and/or authority (i.e. in your example, this is the newhost part of the Uri).

From here, you should be able to compare the return value of the call to GetLLeftPart with the original Uri string, and if they're different, the Uri is "invalid". If they're the same, the Uri is "valid" (for your purposes).

Here's a simple example class that will perform this "validation" returning either True or False for the Uri (both C# and VB.NET versions):

C#

public static class UriValidator
{
    public static bool IsUriValid(string uri)
    {
        try
        {
            string original_uri = uri;
            if (uri.Substring(uri.Length - 1, 1) == "/")
            {
                original_uri = uri.Substring(0, uri.Length - 1);
            }
            Uri myUri = new Uri(original_uri);
            string new_uri = myUri.GetLeftPart(UriPartial.Authority);
            if (original_uri.ToLower() == new_uri.ToLower())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        catch
        {
            return false;
        }            
    }
}

VB.NET

Public Class UriValidator
    Public Shared Function IsUriValid(ByVal uri As String) As Boolean
        Try
            Dim original_uri = uri
            If uri.Substring(uri.Length - 1, 1) = "/" Then
                original_uri = uri.Substring(0, uri.Length - 1)
            End If
            Dim myUri As Uri = New Uri(original_uri)
            Dim new_uri As String = myUri.GetLeftPart(UriPartial.Authority)
            If original_uri.ToLower = new_uri.ToLower Then
                Return True
            Else
                Return False
            End If
        Catch ex As Exception
            Return False
        End Try
    End Function
End Class

I ran a simple test using this class:

Console.WriteLine("https://newhost/" + "  " + UriValidator.IsUriValid("https://newhost/"));
Console.WriteLine("http://newhost:800" + "  " + UriValidator.IsUriValid("http://newhost:800"));
Console.WriteLine("newhost:800" + "  " + UriValidator.IsUriValid("newhost:800"));
Console.WriteLine("newhost:" + "  " + UriValidator.IsUriValid("newhost:"));
Console.WriteLine("qwerty:newhost" + "  " + UriValidator.IsUriValid("qwerty:newhost"));
Console.WriteLine("qwerty://newhost" + "  " + UriValidator.IsUriValid("qwerty://newhost"));
Console.WriteLine("qwerty://newhost:800" + "  " + UriValidator.IsUriValid("qwerty://newhost:800"));
Console.WriteLine("http://newhost/path/to/service" + "  " + UriValidator.IsUriValid("http://newhost/path/to/service"));

And it gave the following output:

https://newhost/ True
http://newhost:800 True
newhost:800 False
newhost: False
qwerty:newhost False
qwerty://newhost True
qwerty://newhost:800 True
http://newhost/path/to/service False

which seems to be what you're after!

Note that Uri's like qwerty://newhost still validate as True as qwerty could be a valid protocol registered on your system. If you only wanted to allow http and/or https, it should be trivial to add this in.

CraigTP