解析和验证手机号码的最佳做法

时间:2010-12-30 14:28:56

标签: c# asp.net parsing validation

我想知道在发送文本之前解析和验证手机号码的最佳做法是什么。我已经有了可行的代码,但我想找到更好的方法(我的上一个问题,这是我早期新年决议中编写质量更好的代码的一部分!)。

当用户输入表格上的号码时,我们非常宽容,他们可以输入“+44 123 4567890”,“00441234567890”,“0123456789”,“+ 44(0)123456789”,“ 012-345-6789“甚至”还没有电话“。

但是,要发送文本格式必须是44xxxxxxxxxx(这仅适用于英国手机),因此我们需要先解析并验证,然后再发送。下面是我现在的代码(C#,asp.net),如果有人对如何改进它有任何想法会很棒。

谢谢,

Annelie

private bool IsMobileNumberValid(string mobileNumber)
    {
        // parse the number
        _mobileNumber = ParsedMobileNumber(mobileNumber);

        // check if it's the right length
        if (_mobileNumber.Length != 12)
        {
            return false;
        }

        // check if it contains non-numeric characters
        if(!Regex.IsMatch(_mobileNumber, @"^[-+]?[0-9]*\.?[0-9]+$"))
        {
            return false;
        }

        return true;
    }

    private string ParsedMobileNumber(string number)
    {
        number = number.Replace("+", "");
        number = number.Replace(".", "");
        number = number.Replace(" ", "");
        number = number.Replace("-", "");
        number = number.Replace("/", "");
        number = number.Replace("(", "");
        number = number.Replace(")", "");

        number = number.Trim(new char[] { '0' });

        if (!number.StartsWith("44"))
        {
            number = "44" + number;
        }

        return number;
    }

修改

这是我最终的结果:

private bool IsMobileNumberValid(string mobileNumber)
    {
        // remove all non-numeric characters
        _mobileNumber = CleanNumber(mobileNumber);

        // trim any leading zeros
        _mobileNumber = _mobileNumber.TrimStart(new char[] { '0' });

        // check for this in case they've entered 44 (0)xxxxxxxxx or similar
        if (_mobileNumber.StartsWith("440"))
        {
            _mobileNumber = _mobileNumber.Remove(2, 1);
        }

        // add country code if they haven't entered it
        if (!_mobileNumber.StartsWith("44"))
        {
            _mobileNumber = "44" + _mobileNumber;
        }

        // check if it's the right length
        if (_mobileNumber.Length != 12)
        {
            return false;
        }

        return true;
    }

    private string CleanNumber(string phone)
    {
        Regex digitsOnly = new Regex(@"[^\d]");
        return digitsOnly.Replace(phone, "");
    }

4 个答案:

答案 0 :(得分:2)

使用正则表达式删除任何非数字字符,而不是试图猜测一个人将如何输入他们的数字 - 这将删除所有的Replace()和Trim()方法,除非你真的需要修剪前导零

string CleanPhone(string phone)
{
    Regex digitsOnly = new Regex(@"[^\d]");   
    return digitsOnly.Replace(phone, "");
}

或者,我建议您使用蒙版文本框来收集#(有许多可用选项)以仅允许数字输入,并以您想要的任何格式显示输入。这样您就可以保证收到的值都是数字字符。

答案 1 :(得分:1)

查看QAS,这是一个商业解决方案。

他们有电子邮件,电话和地址验证。

http://www.qas.com/phone-number-validation-web-service.htm

我们将他们的服务用于地址和电子邮件(而不是电话)并且对此感到满意。

答案 2 :(得分:0)

@annelie也许您可以将正则表达式更新为更强大的正则表达式。查看此网站here。它包含许多表达式,但我认为网站中前2个表达式中的一个应该适合您。

答案 3 :(得分:0)

public class PhoneNumber
{
    public PhoneNumber(string value)
    {
        if (String.IsNullOrEmpty(value))
            throw new ArgumentNullException("numberString", Properties.Resources.PhoneNumberIsNullOrEmpty);

        var match = new Regex(@"\+(\w+) \((\w+)\) (\w+)", RegexOptions.Compiled).Match(value);
        if (match.Success)
        {
            ushort countryCode = 0;
            ushort localCode = 0;
            int number = 0;

            if (UInt16.TryParse(match.Result("$1"), out countryCode) &&
                UInt16.TryParse(match.Result("$2"), out localCode) &&
                Int32.TryParse(match.Result("$3"), out number))
            {
                this.CountryCode = countryCode;
                this.LocalCode = localCode;
                this.Number = number;
            }
        }
        else
        {
            throw new ArgumentNullException("numberString", Properties.Resources.PhoneNumberInvalid);
        }
    }

    public PhoneNumber(int countryCode, int localCode, int number)
    {
        if (countryCode == 0)
            throw new ArgumentOutOfRangeException("countryCode", Properties.Resources.PhoneNumberIsNullOrEmpty);
        else if (localCode == 0)
            throw new ArgumentOutOfRangeException("localCode", Properties.Resources.PhoneNumberIsNullOrEmpty);
        else if (number == 0)
            throw new ArgumentOutOfRangeException("number", Properties.Resources.PhoneNumberIsNullOrEmpty);

        this.CountryCode = countryCode;
        this.LocalCode = localCode;
        this.Number = number;
    }

    public int CountryCode { get; set; }

    public int LocalCode { get; set; }

    public int Number { get; set; }

    public override string ToString()
    {
        return String.Format(System.Globalization.CultureInfo.CurrentCulture, "+{0} ({1}) {2}", CountryCode, LocalCode, Number);
    }

    public static bool Validate(string value)
    {
        return new Regex(@"\+\w+ \(\w+\) \w+", RegexOptions.Compiled).IsMatch(value);
    }

    public static bool Validate(string countryCode, string localCode, string number, out PhoneNumber phoneNumber)
    {
        var valid = false;
        phoneNumber = null;
        try
        {
            ushort uCountryCode = 0;
            ushort uLocalCode = 0;
            int iNumber = 0;

            // match only if all three numbers have been parsed successfully
            valid = UInt16.TryParse(countryCode, out uCountryCode) &&
                    UInt16.TryParse(localCode, out uLocalCode) &&
                    Int32.TryParse(number, out iNumber);

            if (valid)
                phoneNumber = new PhoneNumber(uCountryCode, uLocalCode, iNumber);
        }
        catch (ArgumentException)
        {
            // still not match
        }
        return valid;
    }
}