Вопрос: Как создавать виртуальные домены 3 уровня в ASP.NET MVC 3?

Лучший ответ: Может это поможет.

Худший ответ: Надо писать собственный обработчик маршрутизации.
Я использовал такой вариант. Исходный вариант нашел на одном из форумов и немного его доработал. public class SubDomainRoute : Route
    {
        private Regex domainRegex;
        private Regex pathRegex;
        private readonly string[] namespaces;
        public string Domain { get; set; }

        public SubDomainRoute(string domain, string url, object defaults, string[] namespaces)
            : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
        {
            Domain = domain;
            this.namespaces = namespaces;
        }

        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            // Build regex
            domainRegex = CreateRegex(Domain);
            pathRegex = CreateRegex(Url);

            // Request information
            string requestDomain = httpContext.Request.Headers["host"];
            if (!string.IsNullOrEmpty(requestDomain))
            {
                if (requestDomain.IndexOf(":") > 0)
                {
                    requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
                }
            }
            else
            {
                requestDomain = httpContext.Request.Url.Host;
            }
            string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

            // Match domain and route
            Match domainMatch = domainRegex.Match(requestDomain);
            Match pathMatch = pathRegex.Match(requestPath);

            if (domainMatch.Success && pathMatch.Success)
            {
                var routeData = base.GetRouteData(httpContext);

                if (this.namespaces != null && this.namespaces.Length > 0)
                {
                    routeData.DataTokens["Namespaces"] = this.namespaces;
                }
                //тут добавляем поле {host} к маршрутам
                routeData.DataTokens["Host"] = routeData.Values["host"];
                routeData.DataTokens["UseNamespaceFallback"] = bool.FalseString;

                return routeData;
            }

            return null;
        }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
           
                return base.GetVirtualPath(requestContext, values);
           // return null;
        }

        private Regex CreateRegex(string source)
        {
            // Perform replacements
            source = source.Replace("/", @"\/?");
            source = source.Replace(".", @"\.?");
            source = source.Replace("-", @"\-?");
            source = source.Replace("{", @"(?<");
            source = source.Replace("}", @">([a-zA-Z0-9_]*))");

            return new Regex("^" + source + "$");
        }
    }
А в затем описываю маршрут так:routes.Add("host_default", new SubDomainRoute(
                "{host}.web.ru",
                "{controller}/{action}/{id}",
                new { controller = "User", action = "Index", id = UrlParameter.Optional },
                new[] { typeof(Controllers.UserController).Namespace } // Namespaces defaults
            ));
Надо еще в контроллере User делать проверку на корректность поддомена.