Getting a 'base' Domain from a Domain

Posted by Rick Strahl on West-Wind See other posts from West-Wind or by Rick Strahl
Published on Wed, 25 Apr 2012 04:17:07 GMT Indexed on 2012/05/30 16:42 UTC
Read the original article Hit count: 622

Filed under:
|

Here's a simple one: How do you reliably get the base domain from full domain name or URI? Specifically I've run into this scenario in a few recent applications when creating the Forms Auth Cookie in my ASP.NET applications where I explicitly need to force the domain name to the common base domain. So, www.west-wind.com, store.west-wind.com, west-wind.com, dev.west-wind.com all should return west-wind.com.

Here's the code where I need to use this type of logic for issuing an AuthTicket explicitly:

private void IssueAuthTicket(UserState userState, bool rememberMe)
{
    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userState.UserId,
                                                         DateTime.Now, DateTime.Now.AddDays(10),
                                                         rememberMe, userState.ToString());

    string ticketString = FormsAuthentication.Encrypt(ticket);
    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ticketString);
    cookie.HttpOnly = true;
    
    if (rememberMe)
        cookie.Expires = DateTime.Now.AddDays(10);

    // write out a domain cookie
    cookie.Domain = Request.Url.GetBaseDomain();

    HttpContext.Response.Cookies.Add(cookie);
}

Now unfortunately there's no Uri.GetBaseDomain() method unfortunately, as I was surprised to find out. So I ended up creating one:

public static class NetworkUtils
{

    /// <summary>
    /// Retrieves a base domain name from a full domain name.
    /// For example: www.west-wind.com produces west-wind.com
    /// </summary>
    /// <param name="domainName">Dns Domain name as a string</param>
    /// <returns></returns>
    public static string GetBaseDomain(string domainName)
    {
            var tokens = domainName.Split('.');

            // only split 3 segments like www.west-wind.com
            if (tokens == null || tokens.Length != 3)
                return domainName;

            var tok  = new List<string>(tokens);
            var remove = tokens.Length - 2;
            tok.RemoveRange(0, remove);

            return tok[0] + "." + tok[1]; ;                                
    }

    /// <summary>
    /// Returns the base domain from a domain name
    /// Example: http://www.west-wind.com returns west-wind.com
    /// </summary>
    /// <param name="uri"></param>
    /// <returns></returns>
    public static string GetBaseDomain(this Uri uri)
    {
        if (uri.HostNameType == UriHostNameType.Dns)                        
            return GetBaseDomain(uri.DnsSafeHost);
        
        return uri.Host;
    }
 
}

I've had a need for this so frequently it warranted a couple of helpers. The second Uri helper is an Extension method to the Uri class, which is what's used the in the first code sample. This is the preferred way to call this since the URI class can differentiate between Dns names and IP Addresses. If you use the first string based version there's a little more guessing going on if a URL is an IP Address.

There are a couple of small twists in dealing with 'domain names'. When passing a string only there's a possibility to not actually pass domain name, but end up passing an IP address, so the code explicitly checks for three domain segments (can there be more than 3?). IP4 Addresses have 4 and IP6 have none so they'll fall through. Then there are things like localhost or a NetBios machine name which also come back on URL strings, but also shouldn't be handled.

Anyway, small thing but maybe somebody else will find this useful.

© Rick Strahl, West Wind Technologies, 2005-2012
Posted in ASP.NET  Networking  

© West-Wind or respective owner

Related posts about ASP.NET

Related posts about networking