IP address validation

The job of IPAddress.TryParse() is not to check if the string is a valid IP address, but whether or not the content of the string can be parsed (i.e.; converted) to a valid IP address.

All of the options in your test cases can in fact be parsed to represent and IP. What it comes down to is that your test cases are valid. The issue is that the data for your test cases are not valid, or you're not using the right tool(s) in your test case to get the expected result.

If you're specifically testing for a valid IPv4, with exactly 4 quads (each being an integer between 0 - 255), and want to avoid regex your could instead split then parse and validate.

public static bool IsIPv4(string value)
{
    var octets = value.Split('.');

    // if we do not have 4 octets, return false
    if (octets.Length!=4) return false;

    // for each octet
    foreach(var octet in octets) 
    {
        int q;
        // if parse fails 
        // or length of parsed int != length of octet string (i.e.; '1' vs '001')
        // or parsed int < 0
        // or parsed int > 255
        // return false
        if (!Int32.TryParse(octet, out q) 
            || !q.ToString().Length.Equals(octet.Length) 
            || q < 0 
            || q > 255) { return false; }

    }

    return true;
}

If you want to be very strict about your input, then you can compare the ToString() version of the parsed IPAddress, and reject the input if they are different.

The all-zero address, and other such things, would have to be handled as special cases.


It looks like the docs for IPAddress.Parse rationalize this behavior by pointing out that entering fewer parts is convenient for entering class A and B addresses. If you want to force a four-part address, you might just want to check that there are three periods in the address before feeding it to IPAddress.TryParse, I guess.

Some code for your reference:

// verify that IP consists of 4 parts
if (value.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Length == 4)
{
    IPAddress ipAddr;
    if (IPAddress.TryParse(value, out ipAddr))
    {
        // IP is valid
    }
    else
        // invalid IP
}
else
    // invalid IP

I suggest:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }